diff --git a/research/README.md b/research/README.md
index f9e84fb86f44b687c6a9c221fa72cd461e84c01e..204955b3e082469533885a9b9860b134ee51f46f 100644
--- a/research/README.md
+++ b/research/README.md
@@ -7,14 +7,17 @@ This directory contains code implementations and pre-trained models of published
The research models are maintained by their respective authors.
## Table of Contents
-- [Modeling Libraries and Models](#modeling-libraries-and-models)
-- [Models and Implementations](#models-and-implementations)
- * [Computer Vision](#computer-vision)
- * [Natural Language Processing](#natural-language-processing)
- * [Audio and Speech](#audio-and-speech)
- * [Reinforcement Learning](#reinforcement-learning)
- * [Others](#others)
-- [Archived Models and Implementations](#warning-archived-models-and-implementations) (:no_entry_sign: No longer maintained)
+- [TensorFlow Research Models](#tensorflow-research-models)
+ - [Table of Contents](#table-of-contents)
+ - [Modeling Libraries and Models](#modeling-libraries-and-models)
+ - [Models and Implementations](#models-and-implementations)
+ - [Computer Vision](#computer-vision)
+ - [Natural Language Processing](#natural-language-processing)
+ - [Audio and Speech](#audio-and-speech)
+ - [Reinforcement Learning](#reinforcement-learning)
+ - [Others](#others)
+ - [Old Models and Implementations in TensorFlow 1](#old-models-and-implementations-in-tensorflow-1)
+ - [Contributions](#contributions)
## Modeling Libraries and Models
@@ -49,6 +52,7 @@ The research models are maintained by their respective authors.
| Directory | Paper(s) | Conference | Maintainer(s) |
|-----------|----------|------------|---------------|
| [audioset](audioset) | [1] [Audio Set: An ontology and human-labeled dataset for audio events](https://research.google/pubs/pub45857/)
[2] [CNN Architectures for Large-Scale Audio Classification](https://research.google/pubs/pub45611/) | ICASSP 2017 | plakal, dpwe |
+| [deep_speech](deep_speech) | [Deep Speech 2](https://arxiv.org/abs/1512.02595) | ICLR 2016 | yhliang2018 |
### Reinforcement Learning
@@ -64,58 +68,9 @@ The research models are maintained by their respective authors.
| [lfads](lfads) | [LFADS - Latent Factor Analysis via Dynamical Systems](https://arxiv.org/abs/1608.06315) | | jazcollins, sussillo |
| [rebar](rebar) | [REBAR: Low-variance, unbiased gradient estimates for discrete latent variable models](https://arxiv.org/abs/1703.07370) | NIPS 2017 | gjtucker |
----
-
-## :warning: Archived Models and Implementations
-
-The following research models are no longer maintained.
+### Old Models and Implementations in TensorFlow 1
-**Note**: We will remove archived models from the master branch in June, 2020.
-After removal, you will still be able to access archived models in the archive branch.
-
-| Directory | Paper(s) | Conference | Maintainer(s) |
-|-----------|----------|------------|---------------|
-| [adv_imagenet_models](adv_imagenet_models) | [1] [Adversarial Machine Learning at Scale](https://arxiv.org/abs/1611.01236)
[2] [Ensemble Adversarial Training: Attacks and Defenses](https://arxiv.org/abs/1705.07204) | [1] ICLR 2017
[2] ICLR 2018 | alexeykurakin |
-| [adversarial_crypto](adversarial_crypto) | [Learning to Protect Communications with Adversarial Neural Cryptography](https://arxiv.org/abs/1610.06918) | | dave-andersen |
-| [adversarial_logit_pairing](adversarial_logit_pairing) | [Adversarial Logit Pairing](https://arxiv.org/abs/1803.06373) | | alexeykurakin |
-| [autoencoder](autoencoder) | Various autoencoders | | snurkabill |
-| [brain_coder](brain_coder) | [Neural Program Synthesis with Priority Queue Training](https://arxiv.org/abs/1801.03526) | | danabo, mnorouzi |
-| [cognitive_mapping_and_planning](cognitive_mapping_and_planning) | [Cognitive Mapping and Planning for Visual Navigation](https://arxiv.org/abs/1702.03920) | CVPR 2017 | s-gupta |
-| [compression](compression) | [Full Resolution Image Compression with Recurrent Neural Networks](https://arxiv.org/abs/1608.05148) | CVPR 2017 | nmjohn |
-| [deep_contextual_bandits](deep_contextual_bandits) | [Deep Bayesian Bandits Showdown: An Empirical Comparison of Bayesian Deep Networks for Thompson Sampling](https://arxiv.org/abs/1802.09127) | ICLR 2018 | rikel |
-| [deep_speech](deep_speech) | [Deep Speech 2](https://arxiv.org/abs/1512.02595) | ICLR 2016 | yhliang2018 |
-| [domain_adaptation](domain_adaptation) | [1] [Domain Separation Networks](https://arxiv.org/abs/1608.06019)
[2] [Unsupervised Pixel-Level Domain Adaptation with Generative Adversarial Networks](https://arxiv.org/abs/1612.05424) | NIPS 2016 | bousmalis, dmrd |
-| [feelvos](feelvos)| [FEELVOS](https://arxiv.org/abs/1902.09513) | CVPR 2019 | pvoigtlaender, yuningchai, aquariusjay |
-| [fivo](fivo)| [Filtering variational objectives for training generative sequence models](https://arxiv.org/abs/1705.09279) | NIPS 2017 | dieterichlawson |
-| [global_objectives](global_objectives) | [Scalable Learning of Non-Decomposable Objectives](https://arxiv.org/abs/1608.04802) | AISTATS 2017 | mackeya-google |
-| [im2txt](im2txt) | [Show and Tell: Lessons learned from the 2015 MSCOCO Image Captioning Challenge](https://arxiv.org/abs/1609.06647) | TPAMI 2016 | cshallue |
-| [inception](inception) | [Rethinking the Inception Architecture for Computer Vision](https://arxiv.org/abs/1512.00567) | CVPR 2016 | shlens, vincentvanhoucke |
-| [keypointnet](keypointnet) | [KeypointNet](https://arxiv.org/abs/1807.03146) | | mnorouzi |
-| [learned_optimizer](learned_optimizer) | [Learned Optimizers that Scale and Generalize](https://arxiv.org/abs/1703.04813) | ICML 2017 | olganw, nirum |
-| [learning_to_remember_rare_events](learning_to_remember_rare_events) | [Learning to Remember Rare Events](https://arxiv.org/abs/1703.03129) | ICLR 2017| lukaszkaiser, ofirnachum |
-| [learning_unsupervised_learning](learning_unsupervised_learning) | [Meta-Learning Update Rules for Unsupervised Representation Learning](https://arxiv.org/abs/1804.00222) | ICLR 2019 | lukemetz, nirum |
-| [lexnet_nc](lexnet_nc) | [Olive Oil is Made of Olives, Baby Oil is Made for Babies: Interpreting Noun Compounds using Paraphrases in a Neural Model](https://arxiv.org/abs/1803.08073) | NAACL 2018 | vered1986, waterson |
-| [lm_1b](lm_1b) | [Exploring the Limits of Language Modeling](https://arxiv.org/abs/1602.02410) | | oriolvinyals, panyx0718 |
-| [lm_commonsense](lm_commonsense) | [A Simple Method for Commonsense Reasoning](https://arxiv.org/abs/1806.02847) | | thtrieu |
-| [maskgan](maskgan)| [MaskGAN: Better Text Generation via Filling in the](https://arxiv.org/abs/1801.07736) | ICLR 2018 | liamb315, a-dai |
-| [namignizer](namignizer)| Namignizer | | knathanieltucker |
-| [neural_gpu](neural_gpu)| [Neural GPUs Learn Algorithms](https://arxiv.org/abs/1511.08228) | | lukaszkaiser |
-| [neural_programmer](neural_programmer) | [Learning a Natural Language Interface with Neural Programmer](https://arxiv.org/abs/1611.08945) | ICLR 2017 | arvind2505 |
-| [next_frame_prediction](next_frame_prediction) | [Visual Dynamics: Probabilistic Future Frame Synthesis via Cross Convolutional Networks](https://arxiv.org/abs/1607.02586) | NIPS 2016 | panyx0718 |
-| [ptn](ptn) | [Perspective Transformer Nets: Learning Single-View 3D Object Reconstruction without 3D Supervision](https://arxiv.org/abs/1612.00814) | NIPS 2016 | xcyan, arkanath, hellojas, honglaklee |
-| [qa_kg](qa_kg) | [Learning to Reason: End-to-End Module Networks for Visual Question Answering](https://arxiv.org/abs/1704.05526) | ICCV 2017 | yuyuz |
-| [real_nvp](real_nvp) | [Density estimation using Real NVP](https://arxiv.org/abs/1605.08803) | ICLR 2017 | laurent-dinh |
-| [sentiment_analysis](sentiment_analysis)| [Effective Use of Word Order for Text Categorization with Convolutional Neural Networks](https://arxiv.org/abs/1412.1058) | NAACL HLT 2015 | sculd |
-| [seq2species](seq2species) | [Seq2Species: A deep learning approach to pattern recognition for short DNA sequences](https://doi.org/10.1101/353474) | | apbusia, depristo |
-| [skip_thoughts](skip_thoughts) | [Skip-Thought Vectors](https://arxiv.org/abs/1506.06726) | | cshallue |
-| [steve](steve) | [Sample-Efficient Reinforcement Learning with Stochastic Ensemble Value Expansion](https://arxiv.org/abs/1807.01675) | NeurIPS 2018 | buckman-google |
-| [street](street) | [End-to-End Interpretation of the French Street Name Signs Dataset](https://arxiv.org/abs/1702.03970) | ECCV 2016 | theraysmith |
-| [struct2depth](struct2depth)| [Depth Prediction Without the Sensors: Leveraging Structure for Unsupervised Learning from Monocular Videos](https://arxiv.org/abs/1811.06152) | AAAI 2019 | aneliaangelova |
-| [swivel](swivel) | [Swivel: Improving Embeddings by Noticing What's Missing](https://arxiv.org/abs/1602.02215) | | waterson |
-| [tcn](tcn) | [Time-Contrastive Networks: Self-Supervised Learning from Video](https://arxiv.org/abs/1704.06888) | ICRA 2018 | coreylynch, sermanet |
-| [textsum](textsum)| [A Neural Attention Model for Abstractive Sentence Summarization](https://arxiv.org/abs/1509.00685) | EMNLP 2015 | panyx0718, peterjliu |
-| [transformer](transformer) | [Spatial Transformer Network](https://arxiv.org/abs/1506.02025) | NIPS 2015 | daviddao|
-| [video_prediction](video_prediction) | [Unsupervised Learning for Physical Interaction through Video Prediction](https://arxiv.org/abs/1605.07157) | NIPS 2016 | cbfinn |
+:warning: If you are looking for old models, please visit the [Archive branch](https://github.com/tensorflow/models/tree/archive/research).
---
diff --git a/research/adv_imagenet_models/README.md b/research/adv_imagenet_models/README.md
deleted file mode 100644
index 6129f7347effe09ef0272de9ac42d4872726fcd1..0000000000000000000000000000000000000000
--- a/research/adv_imagenet_models/README.md
+++ /dev/null
@@ -1,91 +0,0 @@
-
-
-
-
-# Adversarially trained ImageNet models
-
-Pre-trained ImageNet models from the following papers:
-
-* [Adversarial Machine Learning at Scale](https://arxiv.org/abs/1611.01236)
-* [Ensemble Adversarial Training: Attacks and Defenses](https://arxiv.org/abs/1705.07204)
-
-## Contact
-
-Author: Alexey Kurakin,
-github: [AlexeyKurakin](https://github.com/AlexeyKurakin)
-
-## Pre-requesites and installation
-
-Ensure that you have installed TensorFlow 1.1 or greater
-([instructions](https://www.tensorflow.org/install/)).
-
-You also need copy of ImageNet dataset if you want to run provided example.
-Follow
-[Preparing the dataset](https://github.com/tensorflow/models/tree/master/research/slim#Data)
-instructions in TF-Slim library to get and preprocess ImageNet data.
-
-## Available models
-
-Following pre-trained models are available:
-
-Network Architecture | Adversarial training | Checkpoint
----------------------|----------------------|----------------
-Inception v3 | Step L.L. | [adv_inception_v3_2017_08_18.tar.gz](http://download.tensorflow.org/models/adv_inception_v3_2017_08_18.tar.gz)
-Inception v3 | Step L.L. on ensemble of 3 models | [ens3_adv_inception_v3_2017_08_18.tar.gz](http://download.tensorflow.org/models/ens3_adv_inception_v3_2017_08_18.tar.gz)
-Inception v3 | Step L.L. on ensemble of 4 models| [ens4_adv_inception_v3_2017_08_18.tar.gz](http://download.tensorflow.org/models/ens4_adv_inception_v3_2017_08_18.tar.gz)
-Inception ResNet v2 | Step L.L. | [adv_inception_resnet_v2_2017_12_18.tar.gz](http://download.tensorflow.org/models/adv_inception_resnet_v2_2017_12_18.tar.gz)
-Inception ResNet v2 | Step L.L. on ensemble of 3 models | [ens_adv_inception_resnet_v2_2017_08_18.tar.gz](http://download.tensorflow.org/models/ens_adv_inception_resnet_v2_2017_08_18.tar.gz)
-
-All checkpoints are compatible with
-[TF-Slim](https://github.com/tensorflow/models/tree/master/research/slim)
-implementation of Inception v3 and Inception Resnet v2.
-
-## How to evaluate models on ImageNet test data
-
-Python script `eval_on_adversarial.py` allow you to evaluate provided models
-on white-box adversarial examples generated from ImageNet test set.
-
-Usage is following:
-
-```bash
-# ${MODEL_NAME} - type of network architecture,
-# either "inception_v3" or "inception_resnet_v2"
-# ${CHECKPOINT_PATH} - path to model checkpoint
-# ${DATASET_DIR} - directory with ImageNet test set
-# ${ADV_METHOD} - which method to use to generate adversarial images,
-# supported method:
-# "none" - use clean images from the dataset
-# "stepll" - one step towards least likely class method (StepLL),
-# see https://arxiv.org/abs/1611.01236 for details
-# "stepllnoise" - RAND+StepLL method from https://arxiv.org/abs/1705.07204
-# ${ADV_EPS} - size of adversarial perturbation, ignored when method is none
-python eval_on_adversarial.py \
- --model_name=${MODEL_NAME} \
- --checkpoint_path=${CHECKPOINT_PATH} \
- --dataset_dir=${DATASET_DIR} \
- --batch_size=50 \
- --adversarial_method=${ADV_METHOD} \
- --adversarial_eps=${ADV_EPS}
-```
-
-Below is an example how to evaluate one of the models on RAND+StepLL adversarial
-examples:
-
-```bash
-# Download checkpoint
-CHECKPOINT_DIR=/tmp/checkpoints
-mkdir ${CHECKPOINT_DIR}
-wget http://download.tensorflow.org/models/ens_adv_inception_resnet_v2_2017_08_18.tar.gz
-tar -xvf ens_adv_inception_resnet_v2_2017_08_18.tar.gz
-mv ens_adv_inception_resnet_v2.ckpt* ${CHECKPOINT_DIR}
-rm ens_adv_inception_resnet_v2_2017_08_18.tar.gz
-
-# Run evaluation
-python eval_on_adversarial.py \
- --model_name=inception_v3 \
- --checkpoint_path=${CHECKPOINT_DIR}/ens_adv_inception_resnet_v2.ckpt \
- --dataset_dir=${DATASET_DIR} \
- --batch_size=50 \
- --adversarial_method=stepllnoise \
- --adversarial_eps=16
-```
diff --git a/research/adv_imagenet_models/eval_on_adversarial.py b/research/adv_imagenet_models/eval_on_adversarial.py
deleted file mode 100644
index f9188845c6c4e10484f9b24797d9ece3b730ffb0..0000000000000000000000000000000000000000
--- a/research/adv_imagenet_models/eval_on_adversarial.py
+++ /dev/null
@@ -1,331 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Script which evaluates model on adversarial examples."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import math
-import imagenet
-import inception_resnet_v2
-
-import tensorflow as tf
-from tensorflow.contrib.slim.nets import inception
-
-
-slim = tf.contrib.slim
-
-tf.app.flags.DEFINE_integer(
- 'batch_size', 50, 'The number of samples in each batch.')
-
-tf.app.flags.DEFINE_integer(
- 'max_num_batches', None,
- 'Max number of batches to evaluate by default use all.')
-
-tf.app.flags.DEFINE_string(
- 'master', '', 'The address of the TensorFlow master to use.')
-
-tf.app.flags.DEFINE_string(
- 'checkpoint_path', '/tmp/tfmodel/',
- 'The directory where the model was written to or an absolute path to a '
- 'checkpoint file.')
-
-tf.app.flags.DEFINE_integer(
- 'num_preprocessing_threads', 4,
- 'The number of threads used to create the batches.')
-
-tf.app.flags.DEFINE_string(
- 'split_name', 'validation', 'The name of the train/test split.')
-
-tf.app.flags.DEFINE_string(
- 'dataset_dir', None, 'The directory where the dataset files are stored.')
-
-tf.app.flags.DEFINE_string(
- 'model_name', 'inception_v3',
- 'Name of the model to use, either "inception_v3" or "inception_resnet_v2"')
-
-tf.app.flags.DEFINE_float(
- 'moving_average_decay', None,
- 'The decay to use for the moving average.'
- 'If left as None, then moving averages are not used.')
-
-tf.app.flags.DEFINE_string(
- 'adversarial_method', 'none',
- 'What kind of adversarial examples to use for evaluation. '
- 'Could be one of: "none", "stepll", "stepllnoise".')
-
-tf.app.flags.DEFINE_float(
- 'adversarial_eps', 0.0,
- 'Size of adversarial perturbation in range [0, 255].')
-
-
-FLAGS = tf.app.flags.FLAGS
-
-
-IMAGE_SIZE = 299
-NUM_CLASSES = 1001
-
-
-def preprocess_for_eval(image, height, width,
- central_fraction=0.875, scope=None):
- """Prepare one image for evaluation.
-
- If height and width are specified it would output an image with that size by
- applying resize_bilinear.
- If central_fraction is specified it would crop the central fraction of the
- input image.
-
- Args:
- image: 3-D Tensor of image. If dtype is tf.float32 then the range should be
- [0, 1], otherwise it would converted to tf.float32 assuming that the range
- is [0, MAX], where MAX is largest positive representable number for
- int(8/16/32) data type (see `tf.image.convert_image_dtype` for details)
- height: integer
- width: integer
- central_fraction: Optional Float, fraction of the image to crop.
- scope: Optional scope for name_scope.
- Returns:
- 3-D float Tensor of prepared image.
- """
- with tf.name_scope(scope, 'eval_image', [image, height, width]):
- if image.dtype != tf.float32:
- image = tf.image.convert_image_dtype(image, dtype=tf.float32)
- # Crop the central region of the image with an area containing 87.5% of
- # the original image.
- if central_fraction:
- image = tf.image.central_crop(image, central_fraction=central_fraction)
-
- if height and width:
- # Resize the image to the specified height and width.
- image = tf.expand_dims(image, 0)
- image = tf.image.resize_bilinear(image, [height, width],
- align_corners=False)
- image = tf.squeeze(image, [0])
- image = tf.subtract(image, 0.5)
- image = tf.multiply(image, 2.0)
- return image
-
-
-def create_model(x, reuse=None):
- """Create model graph.
-
- Args:
- x: input images
- reuse: reuse parameter which will be passed to underlying variable scopes.
- Should be None first call and True every subsequent call.
-
- Returns:
- (logits, end_points) - tuple of model logits and enpoints
-
- Raises:
- ValueError: if model type specified by --model_name flag is invalid.
- """
- if FLAGS.model_name == 'inception_v3':
- with slim.arg_scope(inception.inception_v3_arg_scope()):
- return inception.inception_v3(
- x, num_classes=NUM_CLASSES, is_training=False, reuse=reuse)
- elif FLAGS.model_name == 'inception_resnet_v2':
- with slim.arg_scope(inception_resnet_v2.inception_resnet_v2_arg_scope()):
- return inception_resnet_v2.inception_resnet_v2(
- x, num_classes=NUM_CLASSES, is_training=False, reuse=reuse)
- else:
- raise ValueError('Invalid model name: %s' % (FLAGS.model_name))
-
-
-def step_target_class_adversarial_images(x, eps, one_hot_target_class):
- """Base code for one step towards target class methods.
-
- Args:
- x: source images
- eps: size of adversarial perturbation
- one_hot_target_class: one hot encoded target classes for all images
-
- Returns:
- tensor with adversarial images
- """
- logits, end_points = create_model(x, reuse=True)
- cross_entropy = tf.losses.softmax_cross_entropy(one_hot_target_class,
- logits,
- label_smoothing=0.1,
- weights=1.0)
- cross_entropy += tf.losses.softmax_cross_entropy(one_hot_target_class,
- end_points['AuxLogits'],
- label_smoothing=0.1,
- weights=0.4)
- x_adv = x - eps * tf.sign(tf.gradients(cross_entropy, x)[0])
- x_adv = tf.clip_by_value(x_adv, -1.0, 1.0)
- return tf.stop_gradient(x_adv)
-
-
-def stepll_adversarial_images(x, eps):
- """One step towards least likely class (Step L.L.) adversarial examples.
-
- This method is an alternative to FGSM which does not use true classes.
- Method is described in the "Adversarial Machine Learning at Scale" paper,
- https://arxiv.org/abs/1611.01236
-
- Args:
- x: source images
- eps: size of adversarial perturbation
-
- Returns:
- adversarial images
- """
- logits, _ = create_model(x, reuse=True)
- least_likely_class = tf.argmin(logits, 1)
- one_hot_ll_class = tf.one_hot(least_likely_class, NUM_CLASSES)
- return step_target_class_adversarial_images(x, eps, one_hot_ll_class)
-
-
-def stepllnoise_adversarial_images(x, eps):
- """Step L.L. with noise method.
-
- This is an imporvement of Step L.L. method. This method is better against
- adversarially trained models which learn to mask gradient.
- Method is described in the section "New randomized one shot attack" of
- "Ensemble Adversarial Training: Attacks and Defenses" paper,
- https://arxiv.org/abs/1705.07204
-
- Args:
- x: source images
- eps: size of adversarial perturbation
-
- Returns:
- adversarial images
- """
- logits, _ = create_model(x, reuse=True)
- least_likely_class = tf.argmin(logits, 1)
- one_hot_ll_class = tf.one_hot(least_likely_class, NUM_CLASSES)
- x_noise = x + eps / 2 * tf.sign(tf.random_normal(x.shape))
- return step_target_class_adversarial_images(x_noise, eps / 2,
- one_hot_ll_class)
-
-
-def get_input_images(dataset_images):
- """Gets input images for the evaluation.
-
- Args:
- dataset_images: tensor with dataset images
-
- Returns:
- tensor with input images, which is either dataset images or adversarial
- images.
-
- Raises:
- ValueError: if adversarial method specified by --adversarial_method flag
- is invalid.
- """
- # adversarial_eps defines max difference of values of pixels if
- # pixels are in range [0, 255]. However values of dataset pixels are
- # in range [-1, 1], so converting epsilon.
- eps = FLAGS.adversarial_eps / 255 * 2.0
-
- if FLAGS.adversarial_method == 'stepll':
- return stepll_adversarial_images(dataset_images, eps)
- elif FLAGS.adversarial_method == 'stepllnoise':
- return stepllnoise_adversarial_images(dataset_images, eps)
- elif FLAGS.adversarial_method == 'none':
- return dataset_images
- else:
- raise ValueError('Invalid adversarial method: %s'
- % (FLAGS.adversarial_method))
-
-
-def main(_):
- if not FLAGS.dataset_dir:
- raise ValueError('You must supply the dataset directory with --dataset_dir')
-
- tf.logging.set_verbosity(tf.logging.INFO)
- with tf.Graph().as_default():
- tf_global_step = tf.train.get_or_create_global_step()
-
- ###################
- # Prepare dataset #
- ###################
- dataset = imagenet.get_split(FLAGS.split_name, FLAGS.dataset_dir)
- provider = slim.dataset_data_provider.DatasetDataProvider(
- dataset,
- shuffle=False,
- common_queue_capacity=2 * FLAGS.batch_size,
- common_queue_min=FLAGS.batch_size)
- [dataset_image, label] = provider.get(['image', 'label'])
- dataset_image = preprocess_for_eval(dataset_image, IMAGE_SIZE, IMAGE_SIZE)
- dataset_images, labels = tf.train.batch(
- [dataset_image, label],
- batch_size=FLAGS.batch_size,
- num_threads=FLAGS.num_preprocessing_threads,
- capacity=5 * FLAGS.batch_size)
-
- ########################################
- # Define the model and input exampeles #
- ########################################
- create_model(tf.placeholder(tf.float32, shape=dataset_images.shape))
- input_images = get_input_images(dataset_images)
- logits, _ = create_model(input_images, reuse=True)
-
- if FLAGS.moving_average_decay > 0:
- variable_averages = tf.train.ExponentialMovingAverage(
- FLAGS.moving_average_decay, tf_global_step)
- variables_to_restore = variable_averages.variables_to_restore(
- slim.get_model_variables())
- variables_to_restore[tf_global_step.op.name] = tf_global_step
- else:
- variables_to_restore = slim.get_variables_to_restore()
-
- ######################
- # Define the metrics #
- ######################
- predictions = tf.argmax(logits, 1)
- labels = tf.squeeze(labels)
- names_to_values, names_to_updates = slim.metrics.aggregate_metric_map({
- 'Accuracy': slim.metrics.streaming_accuracy(predictions, labels),
- 'Recall_5': slim.metrics.streaming_sparse_recall_at_k(
- logits, tf.reshape(labels, [-1, 1]), 5),
- })
-
- ######################
- # Run evaluation #
- ######################
- if FLAGS.max_num_batches:
- num_batches = FLAGS.max_num_batches
- else:
- # This ensures that we make a single pass over all of the data.
- num_batches = math.ceil(dataset.num_samples / float(FLAGS.batch_size))
-
- if tf.gfile.IsDirectory(FLAGS.checkpoint_path):
- checkpoint_path = tf.train.latest_checkpoint(FLAGS.checkpoint_path)
- else:
- checkpoint_path = FLAGS.checkpoint_path
-
- tf.logging.info('Evaluating %s' % checkpoint_path)
-
- top1_accuracy, top5_accuracy = slim.evaluation.evaluate_once(
- master=FLAGS.master,
- checkpoint_path=checkpoint_path,
- logdir=None,
- summary_op=None,
- num_evals=num_batches,
- eval_op=list(names_to_updates.values()),
- final_op=[names_to_values['Accuracy'], names_to_values['Recall_5']],
- variables_to_restore=variables_to_restore)
-
- print('Top1 Accuracy: ', top1_accuracy)
- print('Top5 Accuracy: ', top5_accuracy)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/adv_imagenet_models/imagenet.py b/research/adv_imagenet_models/imagenet.py
deleted file mode 100644
index 26c4c7a388a234f647e446951a0765d1c53184cb..0000000000000000000000000000000000000000
--- a/research/adv_imagenet_models/imagenet.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Provides data for the ImageNet ILSVRC 2012 Dataset plus some bounding boxes.
-
-Some images have one or more bounding boxes associated with the label of the
-image. See details here: http://image-net.org/download-bboxes
-
-WARNING: Don't use for object detection, in this case all the bounding boxes
-of the image belong to just one class.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import tensorflow as tf
-
-slim = tf.contrib.slim
-
-_FILE_PATTERN = '%s-*'
-
-_SPLITS_TO_SIZES = {
- 'train': 1281167,
- 'validation': 50000,
-}
-
-_ITEMS_TO_DESCRIPTIONS = {
- 'image': 'A color image of varying height and width.',
- 'label': 'The label id of the image, integer between 0 and 999',
- 'label_text': 'The text of the label.',
- 'object/bbox': 'A list of bounding boxes.',
- 'object/label': 'A list of labels, one per each object.',
-}
-
-_NUM_CLASSES = 1001
-
-
-def get_split(split_name, dataset_dir, file_pattern=None, reader=None):
- """Gets a dataset tuple with instructions for reading ImageNet.
-
- Args:
- split_name: A train/test split name.
- dataset_dir: The base directory of the dataset sources.
- file_pattern: The file pattern to use when matching the dataset sources.
- It is assumed that the pattern contains a '%s' string so that the split
- name can be inserted.
- reader: The TensorFlow reader type.
-
- Returns:
- A `Dataset` namedtuple.
-
- Raises:
- ValueError: if `split_name` is not a valid train/test split.
- """
- if split_name not in _SPLITS_TO_SIZES:
- raise ValueError('split name %s was not recognized.' % split_name)
-
- if not file_pattern:
- file_pattern = _FILE_PATTERN
- file_pattern = os.path.join(dataset_dir, file_pattern % split_name)
-
- # Allowing None in the signature so that dataset_factory can use the default.
- if reader is None:
- reader = tf.TFRecordReader
-
- keys_to_features = {
- 'image/encoded': tf.FixedLenFeature(
- (), tf.string, default_value=''),
- 'image/format': tf.FixedLenFeature(
- (), tf.string, default_value='jpeg'),
- 'image/class/label': tf.FixedLenFeature(
- [], dtype=tf.int64, default_value=-1),
- 'image/class/text': tf.FixedLenFeature(
- [], dtype=tf.string, default_value=''),
- 'image/object/bbox/xmin': tf.VarLenFeature(
- dtype=tf.float32),
- 'image/object/bbox/ymin': tf.VarLenFeature(
- dtype=tf.float32),
- 'image/object/bbox/xmax': tf.VarLenFeature(
- dtype=tf.float32),
- 'image/object/bbox/ymax': tf.VarLenFeature(
- dtype=tf.float32),
- 'image/object/class/label': tf.VarLenFeature(
- dtype=tf.int64),
- }
-
- items_to_handlers = {
- 'image': slim.tfexample_decoder.Image('image/encoded', 'image/format'),
- 'label': slim.tfexample_decoder.Tensor('image/class/label'),
- 'label_text': slim.tfexample_decoder.Tensor('image/class/text'),
- 'object/bbox': slim.tfexample_decoder.BoundingBox(
- ['ymin', 'xmin', 'ymax', 'xmax'], 'image/object/bbox/'),
- 'object/label': slim.tfexample_decoder.Tensor('image/object/class/label'),
- }
-
- decoder = slim.tfexample_decoder.TFExampleDecoder(
- keys_to_features, items_to_handlers)
-
- return slim.dataset.Dataset(
- data_sources=file_pattern,
- reader=reader,
- decoder=decoder,
- num_samples=_SPLITS_TO_SIZES[split_name],
- items_to_descriptions=_ITEMS_TO_DESCRIPTIONS,
- num_classes=_NUM_CLASSES)
diff --git a/research/adv_imagenet_models/inception_resnet_v2.py b/research/adv_imagenet_models/inception_resnet_v2.py
deleted file mode 100644
index 2f690e8d2f70ecde9a55f40375a7f74cd25651c7..0000000000000000000000000000000000000000
--- a/research/adv_imagenet_models/inception_resnet_v2.py
+++ /dev/null
@@ -1,358 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Contains the definition of the Inception Resnet V2 architecture.
-
-As described in http://arxiv.org/abs/1602.07261.
-
- Inception-v4, Inception-ResNet and the Impact of Residual Connections
- on Learning
- Christian Szegedy, Sergey Ioffe, Vincent Vanhoucke, Alex Alemi
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import tensorflow as tf
-
-slim = tf.contrib.slim
-
-
-def block35(net, scale=1.0, activation_fn=tf.nn.relu, scope=None, reuse=None):
- """Builds the 35x35 resnet block."""
- with tf.variable_scope(scope, 'Block35', [net], reuse=reuse):
- with tf.variable_scope('Branch_0'):
- tower_conv = slim.conv2d(net, 32, 1, scope='Conv2d_1x1')
- with tf.variable_scope('Branch_1'):
- tower_conv1_0 = slim.conv2d(net, 32, 1, scope='Conv2d_0a_1x1')
- tower_conv1_1 = slim.conv2d(tower_conv1_0, 32, 3, scope='Conv2d_0b_3x3')
- with tf.variable_scope('Branch_2'):
- tower_conv2_0 = slim.conv2d(net, 32, 1, scope='Conv2d_0a_1x1')
- tower_conv2_1 = slim.conv2d(tower_conv2_0, 48, 3, scope='Conv2d_0b_3x3')
- tower_conv2_2 = slim.conv2d(tower_conv2_1, 64, 3, scope='Conv2d_0c_3x3')
- mixed = tf.concat(axis=3, values=[tower_conv, tower_conv1_1, tower_conv2_2])
- up = slim.conv2d(mixed, net.get_shape()[3], 1, normalizer_fn=None,
- activation_fn=None, scope='Conv2d_1x1')
- net += scale * up
- if activation_fn:
- net = activation_fn(net)
- return net
-
-
-def block17(net, scale=1.0, activation_fn=tf.nn.relu, scope=None, reuse=None):
- """Builds the 17x17 resnet block."""
- with tf.variable_scope(scope, 'Block17', [net], reuse=reuse):
- with tf.variable_scope('Branch_0'):
- tower_conv = slim.conv2d(net, 192, 1, scope='Conv2d_1x1')
- with tf.variable_scope('Branch_1'):
- tower_conv1_0 = slim.conv2d(net, 128, 1, scope='Conv2d_0a_1x1')
- tower_conv1_1 = slim.conv2d(tower_conv1_0, 160, [1, 7],
- scope='Conv2d_0b_1x7')
- tower_conv1_2 = slim.conv2d(tower_conv1_1, 192, [7, 1],
- scope='Conv2d_0c_7x1')
- mixed = tf.concat(axis=3, values=[tower_conv, tower_conv1_2])
- up = slim.conv2d(mixed, net.get_shape()[3], 1, normalizer_fn=None,
- activation_fn=None, scope='Conv2d_1x1')
- net += scale * up
- if activation_fn:
- net = activation_fn(net)
- return net
-
-
-def block8(net, scale=1.0, activation_fn=tf.nn.relu, scope=None, reuse=None):
- """Builds the 8x8 resnet block."""
- with tf.variable_scope(scope, 'Block8', [net], reuse=reuse):
- with tf.variable_scope('Branch_0'):
- tower_conv = slim.conv2d(net, 192, 1, scope='Conv2d_1x1')
- with tf.variable_scope('Branch_1'):
- tower_conv1_0 = slim.conv2d(net, 192, 1, scope='Conv2d_0a_1x1')
- tower_conv1_1 = slim.conv2d(tower_conv1_0, 224, [1, 3],
- scope='Conv2d_0b_1x3')
- tower_conv1_2 = slim.conv2d(tower_conv1_1, 256, [3, 1],
- scope='Conv2d_0c_3x1')
- mixed = tf.concat(axis=3, values=[tower_conv, tower_conv1_2])
- up = slim.conv2d(mixed, net.get_shape()[3], 1, normalizer_fn=None,
- activation_fn=None, scope='Conv2d_1x1')
- net += scale * up
- if activation_fn:
- net = activation_fn(net)
- return net
-
-
-def inception_resnet_v2_base(inputs,
- final_endpoint='Conv2d_7b_1x1',
- output_stride=16,
- align_feature_maps=False,
- scope=None):
- """Inception model from http://arxiv.org/abs/1602.07261.
-
- Constructs an Inception Resnet v2 network from inputs to the given final
- endpoint. This method can construct the network up to the final inception
- block Conv2d_7b_1x1.
-
- Args:
- inputs: a tensor of size [batch_size, height, width, channels].
- final_endpoint: specifies the endpoint to construct the network up to. It
- can be one of ['Conv2d_1a_3x3', 'Conv2d_2a_3x3', 'Conv2d_2b_3x3',
- 'MaxPool_3a_3x3', 'Conv2d_3b_1x1', 'Conv2d_4a_3x3', 'MaxPool_5a_3x3',
- 'Mixed_5b', 'Mixed_6a', 'PreAuxLogits', 'Mixed_7a', 'Conv2d_7b_1x1']
- output_stride: A scalar that specifies the requested ratio of input to
- output spatial resolution. Only supports 8 and 16.
- align_feature_maps: When true, changes all the VALID paddings in the network
- to SAME padding so that the feature maps are aligned.
- scope: Optional variable_scope.
-
- Returns:
- tensor_out: output tensor corresponding to the final_endpoint.
- end_points: a set of activations for external use, for example summaries or
- losses.
-
- Raises:
- ValueError: if final_endpoint is not set to one of the predefined values,
- or if the output_stride is not 8 or 16, or if the output_stride is 8 and
- we request an end point after 'PreAuxLogits'.
- """
- if output_stride != 8 and output_stride != 16:
- raise ValueError('output_stride must be 8 or 16.')
-
- padding = 'SAME' if align_feature_maps else 'VALID'
-
- end_points = {}
-
- def add_and_check_final(name, net):
- end_points[name] = net
- return name == final_endpoint
-
- with tf.variable_scope(scope, 'InceptionResnetV2', [inputs]):
- with slim.arg_scope([slim.conv2d, slim.max_pool2d, slim.avg_pool2d],
- stride=1, padding='SAME'):
- # 149 x 149 x 32
- net = slim.conv2d(inputs, 32, 3, stride=2, padding=padding,
- scope='Conv2d_1a_3x3')
- if add_and_check_final('Conv2d_1a_3x3', net): return net, end_points
-
- # 147 x 147 x 32
- net = slim.conv2d(net, 32, 3, padding=padding,
- scope='Conv2d_2a_3x3')
- if add_and_check_final('Conv2d_2a_3x3', net): return net, end_points
- # 147 x 147 x 64
- net = slim.conv2d(net, 64, 3, scope='Conv2d_2b_3x3')
- if add_and_check_final('Conv2d_2b_3x3', net): return net, end_points
- # 73 x 73 x 64
- net = slim.max_pool2d(net, 3, stride=2, padding=padding,
- scope='MaxPool_3a_3x3')
- if add_and_check_final('MaxPool_3a_3x3', net): return net, end_points
- # 73 x 73 x 80
- net = slim.conv2d(net, 80, 1, padding=padding,
- scope='Conv2d_3b_1x1')
- if add_and_check_final('Conv2d_3b_1x1', net): return net, end_points
- # 71 x 71 x 192
- net = slim.conv2d(net, 192, 3, padding=padding,
- scope='Conv2d_4a_3x3')
- if add_and_check_final('Conv2d_4a_3x3', net): return net, end_points
- # 35 x 35 x 192
- net = slim.max_pool2d(net, 3, stride=2, padding=padding,
- scope='MaxPool_5a_3x3')
- if add_and_check_final('MaxPool_5a_3x3', net): return net, end_points
-
- # 35 x 35 x 320
- with tf.variable_scope('Mixed_5b'):
- with tf.variable_scope('Branch_0'):
- tower_conv = slim.conv2d(net, 96, 1, scope='Conv2d_1x1')
- with tf.variable_scope('Branch_1'):
- tower_conv1_0 = slim.conv2d(net, 48, 1, scope='Conv2d_0a_1x1')
- tower_conv1_1 = slim.conv2d(tower_conv1_0, 64, 5,
- scope='Conv2d_0b_5x5')
- with tf.variable_scope('Branch_2'):
- tower_conv2_0 = slim.conv2d(net, 64, 1, scope='Conv2d_0a_1x1')
- tower_conv2_1 = slim.conv2d(tower_conv2_0, 96, 3,
- scope='Conv2d_0b_3x3')
- tower_conv2_2 = slim.conv2d(tower_conv2_1, 96, 3,
- scope='Conv2d_0c_3x3')
- with tf.variable_scope('Branch_3'):
- tower_pool = slim.avg_pool2d(net, 3, stride=1, padding='SAME',
- scope='AvgPool_0a_3x3')
- tower_pool_1 = slim.conv2d(tower_pool, 64, 1,
- scope='Conv2d_0b_1x1')
- net = tf.concat(
- [tower_conv, tower_conv1_1, tower_conv2_2, tower_pool_1], 3)
-
- if add_and_check_final('Mixed_5b', net): return net, end_points
- # TODO(alemi): Register intermediate endpoints
- net = slim.repeat(net, 10, block35, scale=0.17)
-
- # 17 x 17 x 1088 if output_stride == 8,
- # 33 x 33 x 1088 if output_stride == 16
- use_atrous = output_stride == 8
-
- with tf.variable_scope('Mixed_6a'):
- with tf.variable_scope('Branch_0'):
- tower_conv = slim.conv2d(net, 384, 3, stride=1 if use_atrous else 2,
- padding=padding,
- scope='Conv2d_1a_3x3')
- with tf.variable_scope('Branch_1'):
- tower_conv1_0 = slim.conv2d(net, 256, 1, scope='Conv2d_0a_1x1')
- tower_conv1_1 = slim.conv2d(tower_conv1_0, 256, 3,
- scope='Conv2d_0b_3x3')
- tower_conv1_2 = slim.conv2d(tower_conv1_1, 384, 3,
- stride=1 if use_atrous else 2,
- padding=padding,
- scope='Conv2d_1a_3x3')
- with tf.variable_scope('Branch_2'):
- tower_pool = slim.max_pool2d(net, 3, stride=1 if use_atrous else 2,
- padding=padding,
- scope='MaxPool_1a_3x3')
- net = tf.concat([tower_conv, tower_conv1_2, tower_pool], 3)
-
- if add_and_check_final('Mixed_6a', net): return net, end_points
-
- # TODO(alemi): register intermediate endpoints
- with slim.arg_scope([slim.conv2d], rate=2 if use_atrous else 1):
- net = slim.repeat(net, 20, block17, scale=0.10)
- if add_and_check_final('PreAuxLogits', net): return net, end_points
-
- if output_stride == 8:
- # TODO(gpapan): Properly support output_stride for the rest of the net.
- raise ValueError('output_stride==8 is only supported up to the '
- 'PreAuxlogits end_point for now.')
-
- # 8 x 8 x 2080
- with tf.variable_scope('Mixed_7a'):
- with tf.variable_scope('Branch_0'):
- tower_conv = slim.conv2d(net, 256, 1, scope='Conv2d_0a_1x1')
- tower_conv_1 = slim.conv2d(tower_conv, 384, 3, stride=2,
- padding=padding,
- scope='Conv2d_1a_3x3')
- with tf.variable_scope('Branch_1'):
- tower_conv1 = slim.conv2d(net, 256, 1, scope='Conv2d_0a_1x1')
- tower_conv1_1 = slim.conv2d(tower_conv1, 288, 3, stride=2,
- padding=padding,
- scope='Conv2d_1a_3x3')
- with tf.variable_scope('Branch_2'):
- tower_conv2 = slim.conv2d(net, 256, 1, scope='Conv2d_0a_1x1')
- tower_conv2_1 = slim.conv2d(tower_conv2, 288, 3,
- scope='Conv2d_0b_3x3')
- tower_conv2_2 = slim.conv2d(tower_conv2_1, 320, 3, stride=2,
- padding=padding,
- scope='Conv2d_1a_3x3')
- with tf.variable_scope('Branch_3'):
- tower_pool = slim.max_pool2d(net, 3, stride=2,
- padding=padding,
- scope='MaxPool_1a_3x3')
- net = tf.concat(
- [tower_conv_1, tower_conv1_1, tower_conv2_2, tower_pool], 3)
-
- if add_and_check_final('Mixed_7a', net): return net, end_points
-
- # TODO(alemi): register intermediate endpoints
- net = slim.repeat(net, 9, block8, scale=0.20)
- net = block8(net, activation_fn=None)
-
- # 8 x 8 x 1536
- net = slim.conv2d(net, 1536, 1, scope='Conv2d_7b_1x1')
- if add_and_check_final('Conv2d_7b_1x1', net): return net, end_points
-
- raise ValueError('final_endpoint (%s) not recognized', final_endpoint)
-
-
-def inception_resnet_v2(inputs, num_classes=1001, is_training=True,
- dropout_keep_prob=0.8,
- reuse=None,
- scope='InceptionResnetV2',
- create_aux_logits=True):
- """Creates the Inception Resnet V2 model.
-
- Args:
- inputs: a 4-D tensor of size [batch_size, height, width, 3].
- num_classes: number of predicted classes.
- is_training: whether is training or not.
- dropout_keep_prob: float, the fraction to keep before final layer.
- reuse: whether or not the network and its variables should be reused. To be
- able to reuse 'scope' must be given.
- scope: Optional variable_scope.
- create_aux_logits: Whether to include the auxilliary logits.
-
- Returns:
- logits: the logits outputs of the model.
- end_points: the set of end_points from the inception model.
- """
- end_points = {}
-
- with tf.variable_scope(scope, 'InceptionResnetV2', [inputs, num_classes],
- reuse=reuse) as scope:
- with slim.arg_scope([slim.batch_norm, slim.dropout],
- is_training=is_training):
-
- net, end_points = inception_resnet_v2_base(inputs, scope=scope)
-
- if create_aux_logits:
- with tf.variable_scope('AuxLogits'):
- aux = end_points['PreAuxLogits']
- aux = slim.avg_pool2d(aux, 5, stride=3, padding='VALID',
- scope='Conv2d_1a_3x3')
- aux = slim.conv2d(aux, 128, 1, scope='Conv2d_1b_1x1')
- aux = slim.conv2d(aux, 768, aux.get_shape()[1:3],
- padding='VALID', scope='Conv2d_2a_5x5')
- aux = slim.flatten(aux)
- aux = slim.fully_connected(aux, num_classes, activation_fn=None,
- scope='Logits')
- end_points['AuxLogits'] = aux
-
- with tf.variable_scope('Logits'):
- net = slim.avg_pool2d(net, net.get_shape()[1:3], padding='VALID',
- scope='AvgPool_1a_8x8')
- net = slim.flatten(net)
-
- net = slim.dropout(net, dropout_keep_prob, is_training=is_training,
- scope='Dropout')
-
- end_points['PreLogitsFlatten'] = net
- logits = slim.fully_connected(net, num_classes, activation_fn=None,
- scope='Logits')
- end_points['Logits'] = logits
- end_points['Predictions'] = tf.nn.softmax(logits, name='Predictions')
-
- return logits, end_points
-inception_resnet_v2.default_image_size = 299
-
-
-def inception_resnet_v2_arg_scope(weight_decay=0.00004,
- batch_norm_decay=0.9997,
- batch_norm_epsilon=0.001):
- """Returns the scope with the default parameters for inception_resnet_v2.
-
- Args:
- weight_decay: the weight decay for weights variables.
- batch_norm_decay: decay for the moving average of batch_norm momentums.
- batch_norm_epsilon: small float added to variance to avoid dividing by zero.
-
- Returns:
- a arg_scope with the parameters needed for inception_resnet_v2.
- """
- # Set weight_decay for weights in conv2d and fully_connected layers.
- with slim.arg_scope([slim.conv2d, slim.fully_connected],
- weights_regularizer=slim.l2_regularizer(weight_decay),
- biases_regularizer=slim.l2_regularizer(weight_decay)):
-
- batch_norm_params = {
- 'decay': batch_norm_decay,
- 'epsilon': batch_norm_epsilon,
- }
- # Set activation_fn and parameters for batch_norm.
- with slim.arg_scope([slim.conv2d], activation_fn=tf.nn.relu,
- normalizer_fn=slim.batch_norm,
- normalizer_params=batch_norm_params) as scope:
- return scope
diff --git a/research/adversarial_crypto/README.md b/research/adversarial_crypto/README.md
deleted file mode 100644
index 3822def1325b8d4eb1fd31335f2f8ce053ff747a..0000000000000000000000000000000000000000
--- a/research/adversarial_crypto/README.md
+++ /dev/null
@@ -1,62 +0,0 @@
-
-
-
-
-# Learning to Protect Communications with Adversarial Neural Cryptography
-
-This is a slightly-updated model used for the paper
-["Learning to Protect Communications with Adversarial Neural
-Cryptography"](https://arxiv.org/abs/1610.06918).
-
-> We ask whether neural networks can learn to use secret keys to protect
-> information from other neural networks. Specifically, we focus on ensuring
-> confidentiality properties in a multiagent system, and we specify those
-> properties in terms of an adversary. Thus, a system may consist of neural
-> networks named Alice and Bob, and we aim to limit what a third neural
-> network named Eve learns from eavesdropping on the communication between
-> Alice and Bob. We do not prescribe specific cryptographic algorithms to
-> these neural networks; instead, we train end-to-end, adversarially.
-> We demonstrate that the neural networks can learn how to perform forms of
-> encryption and decryption, and also how to apply these operations
-> selectively in order to meet confidentiality goals.
-
-This code allows you to train encoder/decoder/adversary network triplets
-and evaluate their effectiveness on randomly generated input and key
-pairs.
-
-## Prerequisites
-
-The only software requirements for running the encoder and decoder is having
-TensorFlow installed.
-
-Requires TensorFlow r0.12 or later.
-
-## Training and evaluating
-
-After installing TensorFlow and ensuring that your paths are configured
-appropriately:
-
-```
-python train_eval.py
-```
-
-This will begin training a fresh model. If and when the model becomes
-sufficiently well-trained, it will reset the Eve model multiple times
-and retrain it from scratch, outputting the accuracy thus obtained
-in each run.
-
-## Model differences from the paper
-
-The model has been simplified slightly from the one described in
-the paper - the convolutional layer width was reduced by a factor
-of two. In the version in the paper, there was a nonlinear unit
-after the fully-connected layer; that nonlinear has been removed
-here. These changes improve the robustness of training. The
-initializer for the convolution layers has switched to the
-`tf.contrib.layers default` of `xavier_initializer` instead of
-a simpler `truncated_normal`.
-
-## Contact information
-
-This model repository is maintained by David G. Andersen
-([dave-andersen](https://github.com/dave-andersen)).
diff --git a/research/adversarial_crypto/train_eval.py b/research/adversarial_crypto/train_eval.py
deleted file mode 100644
index df7a00ad50f2ec01b37d8c162309a928207088d6..0000000000000000000000000000000000000000
--- a/research/adversarial_crypto/train_eval.py
+++ /dev/null
@@ -1,276 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Adversarial training to learn trivial encryption functions,
-from the paper "Learning to Protect Communications with
-Adversarial Neural Cryptography", Abadi & Andersen, 2016.
-
-https://arxiv.org/abs/1610.06918
-
-This program creates and trains three neural networks,
-termed Alice, Bob, and Eve. Alice takes inputs
-in_m (message), in_k (key) and outputs 'ciphertext'.
-
-Bob takes inputs in_k, ciphertext and tries to reconstruct
-the message.
-
-Eve is an adversarial network that takes input ciphertext
-and also tries to reconstruct the message.
-
-The main function attempts to train these networks and then
-evaluates them, all on random plaintext and key values.
-
-"""
-
-# TensorFlow Python 3 compatibility
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-import signal
-import sys
-from six.moves import xrange # pylint: disable=redefined-builtin
-import tensorflow as tf
-
-flags = tf.app.flags
-
-flags.DEFINE_float('learning_rate', 0.0008, 'Constant learning rate')
-flags.DEFINE_integer('batch_size', 4096, 'Batch size')
-
-FLAGS = flags.FLAGS
-
-# Input and output configuration.
-TEXT_SIZE = 16
-KEY_SIZE = 16
-
-# Training parameters.
-ITERS_PER_ACTOR = 1
-EVE_MULTIPLIER = 2 # Train Eve 2x for every step of Alice/Bob
-# Train until either max loops or Alice/Bob "good enough":
-MAX_TRAINING_LOOPS = 850000
-BOB_LOSS_THRESH = 0.02 # Exit when Bob loss < 0.02 and Eve > 7.7 bits
-EVE_LOSS_THRESH = 7.7
-
-# Logging and evaluation.
-PRINT_EVERY = 200 # In training, log every 200 steps.
-EVE_EXTRA_ROUNDS = 2000 # At end, train eve a bit more.
-RETRAIN_EVE_ITERS = 10000 # Retrain eve up to ITERS*LOOPS times.
-RETRAIN_EVE_LOOPS = 25 # With an evaluation each loop
-NUMBER_OF_EVE_RESETS = 5 # And do this up to 5 times with a fresh eve.
-# Use EVAL_BATCHES samples each time we check accuracy.
-EVAL_BATCHES = 1
-
-
-def batch_of_random_bools(batch_size, n):
- """Return a batch of random "boolean" numbers.
-
- Args:
- batch_size: Batch size dimension of returned tensor.
- n: number of entries per batch.
-
- Returns:
- A [batch_size, n] tensor of "boolean" numbers, where each number is
- preresented as -1 or 1.
- """
-
- as_int = tf.random.uniform(
- [batch_size, n], minval=0, maxval=2, dtype=tf.int32)
- expanded_range = (as_int * 2) - 1
- return tf.cast(expanded_range, tf.float32)
-
-
-class AdversarialCrypto(object):
- """Primary model implementation class for Adversarial Neural Crypto.
-
- This class contains the code for the model itself,
- and when created, plumbs the pathways from Alice to Bob and
- Eve, creates the optimizers and loss functions, etc.
-
- Attributes:
- eve_loss: Eve's loss function.
- bob_loss: Bob's loss function. Different units from eve_loss.
- eve_optimizer: A tf op that runs Eve's optimizer.
- bob_optimizer: A tf op that runs Bob's optimizer.
- bob_reconstruction_loss: Bob's message reconstruction loss,
- which is comparable to eve_loss.
- reset_eve_vars: Execute this op to completely reset Eve.
- """
-
- def get_message_and_key(self):
- """Generate random pseudo-boolean key and message values."""
-
- batch_size = tf.compat.v1.placeholder_with_default(FLAGS.batch_size, shape=[])
-
- in_m = batch_of_random_bools(batch_size, TEXT_SIZE)
- in_k = batch_of_random_bools(batch_size, KEY_SIZE)
- return in_m, in_k
-
- def model(self, collection, message, key=None):
- """The model for Alice, Bob, and Eve. If key=None, the first fully connected layer
- takes only the message as inputs. Otherwise, it uses both the key
- and the message.
-
- Args:
- collection: The graph keys collection to add new vars to.
- message: The input message to process.
- key: The input key (if any) to use.
- """
-
- if key is not None:
- combined_message = tf.concat(axis=1, values=[message, key])
- else:
- combined_message = message
-
- # Ensure that all variables created are in the specified collection.
- with tf.contrib.framework.arg_scope(
- [tf.contrib.layers.fully_connected, tf.contrib.layers.conv2d],
- variables_collections=[collection]):
-
- fc = tf.contrib.layers.fully_connected(
- combined_message,
- TEXT_SIZE + KEY_SIZE,
- biases_initializer=tf.constant_initializer(0.0),
- activation_fn=None)
-
- # Perform a sequence of 1D convolutions (by expanding the message out to 2D
- # and then squeezing it back down).
- fc = tf.expand_dims(fc, 2) # 2D
- fc = tf.expand_dims(fc, 3) # 3D -- conv2d needs a depth
- # 2,1 -> 1,2
- conv = tf.contrib.layers.conv2d(
- fc, 2, 2, 2, 'SAME', activation_fn=tf.nn.sigmoid)
- # 1,2 -> 1, 2
- conv = tf.contrib.layers.conv2d(
- conv, 2, 1, 1, 'SAME', activation_fn=tf.nn.sigmoid)
- # 1,2 -> 1, 1
- conv = tf.contrib.layers.conv2d(
- conv, 1, 1, 1, 'SAME', activation_fn=tf.nn.tanh)
- conv = tf.squeeze(conv, 3)
- conv = tf.squeeze(conv, 2)
- return conv
-
- def __init__(self):
- in_m, in_k = self.get_message_and_key()
- encrypted = self.model('alice', in_m, in_k)
- decrypted = self.model('bob', encrypted, in_k)
- eve_out = self.model('eve', encrypted, None)
-
- self.reset_eve_vars = tf.group(
- *[w.initializer for w in tf.compat.v1.get_collection('eve')])
-
- optimizer = tf.compat.v1.train.AdamOptimizer(learning_rate=FLAGS.learning_rate)
-
- # Eve's goal is to decrypt the entire message:
- eve_bits_wrong = tf.reduce_sum(
- tf.abs((eve_out + 1.0) / 2.0 - (in_m + 1.0) / 2.0), [1])
- self.eve_loss = tf.reduce_sum(eve_bits_wrong)
- self.eve_optimizer = optimizer.minimize(
- self.eve_loss, var_list=tf.compat.v1.get_collection('eve'))
-
- # Alice and Bob want to be accurate...
- self.bob_bits_wrong = tf.reduce_sum(
- tf.abs((decrypted + 1.0) / 2.0 - (in_m + 1.0) / 2.0), [1])
- # ... and to not let Eve do better than guessing.
- self.bob_reconstruction_loss = tf.reduce_sum(self.bob_bits_wrong)
- bob_eve_error_deviation = tf.abs(float(TEXT_SIZE) / 2.0 - eve_bits_wrong)
- # 7-9 bits wrong is OK too, so we squish the error function a bit.
- # Without doing this, we often tend to hang out at 0.25 / 7.5 error,
- # and it seems bad to have continued, high communication error.
- bob_eve_loss = tf.reduce_sum(
- tf.square(bob_eve_error_deviation) / (TEXT_SIZE / 2)**2)
-
- # Rescale the losses to [0, 1] per example and combine.
- self.bob_loss = (self.bob_reconstruction_loss / TEXT_SIZE + bob_eve_loss)
-
- self.bob_optimizer = optimizer.minimize(
- self.bob_loss,
- var_list=(tf.compat.v1.get_collection('alice') + tf.compat.v1.get_collection('bob')))
-
-
-def doeval(s, ac, n, itercount):
- """Evaluate the current network on n batches of random examples.
-
- Args:
- s: The current TensorFlow session
- ac: an instance of the AdversarialCrypto class
- n: The number of iterations to run.
- itercount: Iteration count label for logging.
-
- Returns:
- Bob and Eve's loss, as a percent of bits incorrect.
- """
-
- bob_loss_accum = 0
- eve_loss_accum = 0
- for _ in xrange(n):
- bl, el = s.run([ac.bob_reconstruction_loss, ac.eve_loss])
- bob_loss_accum += bl
- eve_loss_accum += el
- bob_loss_percent = bob_loss_accum / (n * FLAGS.batch_size)
- eve_loss_percent = eve_loss_accum / (n * FLAGS.batch_size)
- print('%10d\t%20.2f\t%20.2f'%(itercount, bob_loss_percent, eve_loss_percent))
- sys.stdout.flush()
- return bob_loss_percent, eve_loss_percent
-
-
-def train_until_thresh(s, ac):
- for j in xrange(MAX_TRAINING_LOOPS):
- for _ in xrange(ITERS_PER_ACTOR):
- s.run(ac.bob_optimizer)
- for _ in xrange(ITERS_PER_ACTOR * EVE_MULTIPLIER):
- s.run(ac.eve_optimizer)
- if j % PRINT_EVERY == 0:
- bob_avg_loss, eve_avg_loss = doeval(s, ac, EVAL_BATCHES, j)
- if (bob_avg_loss < BOB_LOSS_THRESH and eve_avg_loss > EVE_LOSS_THRESH):
- print('Target losses achieved.')
- return True
- return False
-
-
-def train_and_evaluate():
- """Run the full training and evaluation loop."""
-
- ac = AdversarialCrypto()
- init = tf.compat.v1.global_variables_initializer()
-
- with tf.compat.v1.Session() as s:
- s.run(init)
- print('# Batch size: ', FLAGS.batch_size)
- print('# %10s\t%20s\t%20s'%("Iter","Bob_Recon_Error","Eve_Recon_Error"))
-
- if train_until_thresh(s, ac):
- for _ in xrange(EVE_EXTRA_ROUNDS):
- s.run(ac.eve_optimizer)
- print('Loss after eve extra training:')
- doeval(s, ac, EVAL_BATCHES * 2, 0)
- for _ in xrange(NUMBER_OF_EVE_RESETS):
- print('Resetting Eve')
- s.run(ac.reset_eve_vars)
- eve_counter = 0
- for _ in xrange(RETRAIN_EVE_LOOPS):
- for _ in xrange(RETRAIN_EVE_ITERS):
- eve_counter += 1
- s.run(ac.eve_optimizer)
- doeval(s, ac, EVAL_BATCHES, eve_counter)
- doeval(s, ac, EVAL_BATCHES, eve_counter)
-
-
-def main(unused_argv):
- # Exit more quietly with Ctrl-C.
- signal.signal(signal.SIGINT, signal.SIG_DFL)
- train_and_evaluate()
-
-
-if __name__ == '__main__':
- tf.compat.v1.app.run()
diff --git a/research/adversarial_logit_pairing/README.md b/research/adversarial_logit_pairing/README.md
deleted file mode 100644
index d3f576836c4e0fb28eee9882906b18d88a90c564..0000000000000000000000000000000000000000
--- a/research/adversarial_logit_pairing/README.md
+++ /dev/null
@@ -1,281 +0,0 @@
-
-
-
-
-# Adversarial logit pairing
-
-This directory contains implementation of
-[Adversarial logit pairing](https://arxiv.org/abs/1803.06373) paper as well as
-few models pre-trained on ImageNet and Tiny ImageNet.
-
-Please contact [Alexey Kurakin](https://github.com/AlexeyKurakin) regarding
-this code.
-
-## Pre-requesites
-
-Code dependencies:
-
-* TensorFlow 1.8 and Python 2.7 (other versions may work, but were not tested)
-* [Abseil Python](https://github.com/abseil/abseil-py).
-* Script which converts Tiny Imagenet dataset into TFRecord format also
- depends on [Pandas](https://pandas.pydata.org/).
-
-## Datasets
-
-To use this code you need to download datasets. You only need to download
-those datasets which you're going to use. Following list of datasets is
-supported:
-
-* [ImageNet](http://www.image-net.org/). Follow
- [Preparing the datasets](https://github.com/tensorflow/models/tree/master/research/slim#Data)
- instructions in TF-Slim documentation to download and convert ImageNet dataset
- to TFRecord format.
-
-* [Tiny ImageNet](https://tiny-imagenet.herokuapp.com/).
- To obtain Tiny ImageNet dataset do following:
-
- ```
- # Download zip archive with TinyImagenet
- curl -O http://cs231n.stanford.edu/tiny-imagenet-200.zip
-
- # Extract archive
- unzip tiny-imagenet-200.zip
-
- # Convert dataset to TFRecord format
- mkdir tiny-imagenet-tfrecord
- python tiny_imagenet_converter/converter.py \
- --input_dir=tiny-imagenet-200 \
- --output_dir=tiny-imagenet-tfrecord
- ```
-
-## Running the code
-
-NOTE: Provided code supports distributed training on multiple machines,
-and all provided checkpoints were trained in a distributed way. However it is
-beyond the scope of this document to describe how to do distributed training.
-Readed should refer to
-[other material](https://www.tensorflow.org/deploy/distributed) to learn
-about it.
-
-### Training
-
-Following command runs training:
-
-```
-# Following arguments has to be specified for training:
-# - MAX_NUMBER_OF_TRAINING_STEPS - maximum number of training steps,
-# omit this flag or set it to -1 to have unlimited number of training steps.
-# - MODEL_NAME - name of the model, now only "resnet_v2_50" is supported.
-# - MOVING_AVG_DECAY - decay rate for exponential moving average of the
-# trainable variables. Training with exponential moving average usually
-# leads to better accuracy. Default of 0.9999. -1 disable exponential moving
-# average. Default works well, so typically you set it only if you want
-# to disable this feature.
-# - HYPERPARAMETERS - string with hyperparameters,
-# see model_lib.py for full list of hyperparameters.
-# - DATASET - dataset, either "imagenet" or "tiny_imagenet".
-# - IMAGE_SIZE - size of the image (single number).
-# - OUTPUT_DIRECTORY - directory where to write results.
-# - IMAGENET_DIR - directory with ImageNet dataset in TFRecord format.
-# - TINY_IMAGENET_DIR - directory with Tiny ImageNet dataset in TFRecord format.
-#
-# Note that only one of IMAGENET_DIR or TINY_IMAGENET_DIR has to be provided
-# depending on which dataset you use.
-#
-python train.py \
- --max_steps="${MAX_NUMBER_OF_TRAINING_STEPS}" \
- --model_name="${MODEL_NAME}" \
- --moving_average_decay="${MOVING_AVG_DECAY}" \
- --hparams="${HYPERPARAMETERS}" \
- --dataset="${DATASET}" \
- --dataset_image_size="${IMAGE_SIZE}" \
- --output_dir="${OUTPUT_DIRECTORY}" \
- --imagenet_data_dir="${IMAGENET_DIR}" \
- --tiny_imagenet_data_dir="${TINY_IMAGENET_DIR}"
-```
-
-Full list of training hyperparameters could be found in `model_lib.py`.
-These hyperparameters control learning rate schedule, optimizer, weight decay,
-label smoothing and adversarial training.
-
-Adversarial training is controlled by following hyperparameters:
-
-* `train_adv_method` - method which is used to craft adversarial examples during
- training. Could be one of the following:
-
- * `clean` - perform regular training with clean examples;
- * `pgd_EPS_STEP_NITER` - use non targeted PGD with maximum size of
- perturbation equal to `EPS`, step size equal to `STEP`
- and number of iterations equal to `NITER`. Size of perturbation and step
- size are expected to be integers between 1 and 255.
- * `pgdll_EPS_STEP_NITER` - use targeted PGD, where target class is least
- likely prediction of the network.
- * `pgdrnd_EPS_STEP_NITER` - use targeted PGD, where target class is chosen
- randomly.
-
-* `train_lp_weight` - weight of adversarial logit pairing loss. If zero or
- negarive, then no logit pairing is performed and training is done using
- mixed minibatch PGD. If positive then adversarial logit pairing term is added
- to the loss.
-
-Below is example of how to run training with adversarial logit pairing on
-ImageNet 64x64:
-
-```
-python train.py \
- --model_name="resnet_v2_50" \
- --hparams="train_adv_method=pgdll_16_2_10,train_lp_weight=0.5" \
- --dataset="imagenet" \
- --dataset_image_size=64 \
- --output_dir="/tmp/adv_train" \
- --imagenet_data_dir="${IMAGENET_DIR}"
-```
-
-### Fine tuning
-
-Provided trainin script could be used to fine tune pre-trained checkpoint.
-Following command does this:
-
-```
-# Fine tuning adds following additional arguments:
-# - SCOPES_DO_NOT_LOAD_FROM_CHECKPOINT - comma separates list of scopes of
-# variables, which should not be loadeded from checkpoint (and default
-# initialization should be used instead).
-# SCOPES_DO_NOT_LOAD_FROM_CHECKPOINT should be either same or a subset of
-# LIST_OF_SCOPES_OF_TRAINABLE_VARS.
-# - LIST_OF_SCOPES_OF_TRAINABLE_VARS - comma separated list of scopes of
-# trainable variables. Only variables which are prefixed with these scopes
-# will be trained.
-# - PATH_TO_PRETRAINED_CHECKPOINT - directory with pretrained checkpoint which
-# is used as initialization for fine tuning.
-#
-python train.py \
- --max_steps="${MAX_NUMBER_OF_TRAINING_STEPS}" \
- --model_name="${MODEL_NAME}" \
- --moving_average_decay="${MOVING_AVG_DECAY}" \
- --hparams="${HYPERPARAMETERS}" \
- --dataset="${DATASET}" \
- --dataset_image_size="${IMAGE_SIZE}" \
- --output_dir="${OUTPUT_DIRECTORY}" \
- --imagenet_data_dir="${IMAGENET_DIR}" \
- --tiny_imagenet_data_dir="${TINY_IMAGENET_DIR}" \
- --finetune_exclude_pretrained_scopes="${SCOPES_DO_NOT_LOAD_FROM_CHECKPOINT}" \
- --finetune_trainable_scopes="${LIST_OF_SCOPES_OF_TRAINABLE_VARS}" \
- --finetune_checkpoint_path="${PATH_TO_PRETRAINED_CHECKPOINT}"
-```
-
-Below is an example of how to fine tune last few layers of the model on
-Tiny Imagenet dataset:
-
-```
-python train.py \
- --model_name="resnet_v2_50" \
- --hparams="train_adv_method=pgdll_16_2_10,train_lp_weight=0.5,learning_rate=0.02" \
- --dataset="tiny_imagenet" \
- --dataset_image_size=64 \
- --output_dir="/tmp/adv_finetune" \
- --tiny_imagenet_data_dir="${TINY_IMAGENET_DIR}" \
- --finetune_exclude_pretrained_scopes="resnet_v2_50/logits" \
- --finetune_trainable_scopes="resnet_v2_50/logits,resnet_v2_50/postnorm" \
- --finetune_checkpoint_path="/tmp/adv_train"
-```
-
-### Evaluation
-
-Following command runs evaluation:
-
-```
-# Following arguments should be provided for eval:
-# - TRAINING_DIRECTORY - directory where training checkpoints are saved.
-# - TRAINABLE_SCOPES - when loading checkpoint which was obtained by fine tuning
-# this argument should be the same as LIST_OF_SCOPES_OF_TRAINABLE_VARS
-# during training. Otherwise it should be empty.
-# This is needed to properly load exponential moving average variables.
-# If exponential moving averages are disabled then this flag could be
-# omitted.
-# - EVAL_SUBDIR_NAME - name of the subdirectory inside TRAINING_DIRECTORY
-# where evaluation code will be saving event files.
-# - DATASET - name of the dataset.
-# - IMAGE_SIZE - size of the image in the dataset.
-# - DATSET_SPLIT_NAME - name of the split in the dataset,
-# either 'train' or 'validation'. Default is 'validation'.
-# - MODEL_NAME - name of the model.
-# - MOVING_AVG_DECAY - decay rate for exponential moving average.
-# - ADV_METHOD_FOR_EVAL - should be "clean" to evaluate on clean example or
-# description of the adversarial method to evaluate on adversarial examples.
-# - HYPERPARAMETERS - hyperparameters, only "eval_batch_size" matters for eval
-# - NUMBER_OF_EXAMPLES - how many examples from the dataset use for evaluation,
-# specify -1 to use all examples.
-# - EVAL_ONCE - if True then evaluate only once, otherwise keep evaluation
-# running repeatedly on new checkpoints. Repeated evaluation might be useful
-# when running concurrent with training.
-# - IMAGENET_DIR - directory with ImageNet dataset in TFRecord format.
-# - TINY_IMAGENET_DIR - directory with Tiny ImageNet dataset in TFRecord format.
-#
-python eval.py \
- --train_dir="${TRAINING_DIRECTORY} \
- --trainable_scopes="${TRAINABLE_SCOPES}" \
- --eval_name="${EVAL_SUBDIR_NAME}" \
- --dataset="${DATASET}" \
- --dataset_image_size="${IMAGE_SIZE}" \
- --split_name="${DATSET_SPLIT_NAME}" \
- --model_name="${MODEL_NAME}" \
- --moving_average_decay="${MOVING_AVG_DECAY}" \
- --adv_method="${ADV_METHOD_FOR_EVAL}" \
- --hparams="${HYPERPARAMETERS}" \
- --num_examples="${NUMBER_OF_EXAMPLES}" \
- --eval_once="${EVAL_ONCE}" \
- --imagenet_data_dir="${IMAGENET_DIR}" \
- --tiny_imagenet_data_dir="${TINY_IMAGENET_DIR}"
-```
-
-Example of running evaluation on 10000 of clean examples from ImageNet
-training set:
-
-```
-python eval.py \
- --train_dir=/tmp/adv_train \
- --dataset=imagenet \
- --dataset_image_size=64 \
- --split_name=train \
- --adv_method=clean \
- --hparams="eval_batch_size=50" \
- --num_examples=10000 \
- --eval_once=True \
- --imagenet_data_dir="${IMAGENET_DIR}"
-```
-
-Example of running evaluatin on adversarial images generated from Tiny ImageNet
-validation set using fine-tuned checkpoint:
-
-```
-python eval.py \
- --train_dir=tmp/adv_finetune \
- --trainable_scopes="resnet_v2_50/logits,resnet_v2_50/postnorm" \
- --dataset=tiny_imagenet \
- --dataset_image_size=64 \
- --adv_method=pgdrnd_16_2_10 \
- --hparams="eval_batch_size=50" \
- --eval_once=True \
- --tiny_imagenet_data_dir="${TINY_IMAGENET_DIR}"
-```
-
-### Pre-trained models
-
-Following set of pre-trained checkpoints released with this code:
-
-| Model | Dataset | Accuracy on
clean images | Accuracy on
`pgdll_16_1_20` | Accuracy on
`pgdll_16_2_10` |
-| ----------- | ------------ | --------------- | --------------------------- | -------------- |
-| [Baseline ResNet-v2-50](http://download.tensorflow.org/models/adversarial_logit_pairing/imagenet64_base_2018_06_26.ckpt.tar.gz) | ImageNet 64x64 | 60.5% | 1.8% | 3.5% |
-| [ALP-trained ResNet-v2-50](http://download.tensorflow.org/models/adversarial_logit_pairing/imagenet64_alp025_2018_06_26.ckpt.tar.gz) | ImageNet 64x64 | 55.7% | 27.5% | 27.8% |
-| [Baseline ResNet-v2-50](http://download.tensorflow.org/models/adversarial_logit_pairing/tiny_imagenet_base_2018_06_26.ckpt.tar.gz) | Tiny ImageNet | 69.2% | 0.1% | 0.3% |
-| [ALP-trained ResNet-v2-50](http://download.tensorflow.org/models/adversarial_logit_pairing/tiny_imagenet_alp05_2018_06_26.ckpt.tar.gz) | Tiny ImageNet | 72.0% | 41.3% | 40.8% |
-
-
-* All provided checkpoints were initially trained with exponential moving
- average. However for ease of use they were re-saved without it.
- So to load and use provided checkpoints you need to specify
- `--moving_average_decay=-1` flag.
-* All ALP models were trained with `pgdll_16_2_10` adversarial examples.
-* All Tiny Imagenet models were obtained by fine tuning corresponding
- ImageNet 64x64 models. ALP-trained models were fine tuned with ALP.
diff --git a/research/adversarial_logit_pairing/adversarial_attack.py b/research/adversarial_logit_pairing/adversarial_attack.py
deleted file mode 100644
index 804bd64bcf4444007638f9802a83973ee68eb3cf..0000000000000000000000000000000000000000
--- a/research/adversarial_logit_pairing/adversarial_attack.py
+++ /dev/null
@@ -1,219 +0,0 @@
-# Copyright 2018 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Library with adversarial attacks.
-
-This library designed to be self-contained and have no dependencies other
-than TensorFlow. It only contains PGD / Iterative FGSM attacks,
-see https://arxiv.org/abs/1706.06083 and https://arxiv.org/abs/1607.02533
-for details.
-
-For wider set of adversarial attacks refer to Cleverhans library:
-https://github.com/tensorflow/cleverhans
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-
-def generate_pgd_common(x,
- bounds,
- model_fn,
- attack_params,
- one_hot_labels,
- perturbation_multiplier):
- """Common code for generating PGD adversarial examples.
-
- Args:
- x: original examples.
- bounds: tuple with bounds of image values, bounds[0] < bounds[1].
- model_fn: model function with signature model_fn(images).
- attack_params: parameters of the attack.
- one_hot_labels: one hot label vector to use in the loss.
- perturbation_multiplier: multiplier of adversarial perturbation,
- either +1.0 or -1.0.
-
- Returns:
- Tensor with adversarial examples.
-
- Raises:
- ValueError: if attack parameters are invalid.
- """
- # parse attack_params
- # Format of attack_params: 'EPS_STEP_NITER'
- # where EPS - epsilon, STEP - step size, NITER - number of iterations
- params_list = attack_params.split('_')
- if len(params_list) != 3:
- raise ValueError('Invalid parameters of PGD attack: %s' % attack_params)
- epsilon = int(params_list[0])
- step_size = int(params_list[1])
- niter = int(params_list[2])
-
- # rescale epsilon and step size to image bounds
- epsilon = float(epsilon) / 255.0 * (bounds[1] - bounds[0])
- step_size = float(step_size) / 255.0 * (bounds[1] - bounds[0])
-
- # clipping boundaries
- clip_min = tf.maximum(x - epsilon, bounds[0])
- clip_max = tf.minimum(x + epsilon, bounds[1])
-
- # compute starting point
- start_x = x + tf.random_uniform(tf.shape(x), -epsilon, epsilon)
- start_x = tf.clip_by_value(start_x, clip_min, clip_max)
-
- # main iteration of PGD
- loop_vars = [0, start_x]
-
- def loop_cond(index, _):
- return index < niter
-
- def loop_body(index, adv_images):
- logits = model_fn(adv_images)
- loss = tf.reduce_sum(
- tf.nn.softmax_cross_entropy_with_logits_v2(
- labels=one_hot_labels,
- logits=logits))
- perturbation = step_size * tf.sign(tf.gradients(loss, adv_images)[0])
- new_adv_images = adv_images + perturbation_multiplier * perturbation
- new_adv_images = tf.clip_by_value(new_adv_images, clip_min, clip_max)
- return index + 1, new_adv_images
-
- with tf.control_dependencies([start_x]):
- _, result = tf.while_loop(
- loop_cond,
- loop_body,
- loop_vars,
- back_prop=False,
- parallel_iterations=1)
- return result
-
-
-def generate_pgd_ll(x, bounds, model_fn, attack_params):
- # pylint: disable=g-doc-args
- """Generats targeted PGD adversarial examples with least likely target class.
-
- See generate_pgd_common for description of arguments.
-
- Returns:
- Tensor with adversarial examples.
- """
- # pylint: enable=g-doc-args
-
- # compute one hot least likely class
- logits = model_fn(x)
- num_classes = tf.shape(logits)[1]
- one_hot_labels = tf.one_hot(tf.argmin(model_fn(x), axis=1), num_classes)
-
- return generate_pgd_common(x, bounds, model_fn, attack_params,
- one_hot_labels=one_hot_labels,
- perturbation_multiplier=-1.0)
-
-
-def generate_pgd_rand(x, bounds, model_fn, attack_params):
- # pylint: disable=g-doc-args
- """Generats targeted PGD adversarial examples with random target class.
-
- See generate_pgd_common for description of arguments.
-
- Returns:
- Tensor with adversarial examples.
- """
- # pylint: enable=g-doc-args
-
- # compute one hot random class
- logits = model_fn(x)
- batch_size = tf.shape(logits)[0]
- num_classes = tf.shape(logits)[1]
- random_labels = tf.random_uniform(shape=[batch_size],
- minval=0,
- maxval=num_classes,
- dtype=tf.int32)
- one_hot_labels = tf.one_hot(random_labels, num_classes)
-
- return generate_pgd_common(x, bounds, model_fn, attack_params,
- one_hot_labels=one_hot_labels,
- perturbation_multiplier=-1.0)
-
-
-def generate_pgd(x, bounds, model_fn, attack_params):
- # pylint: disable=g-doc-args
- """Generats non-targeted PGD adversarial examples.
-
- See generate_pgd_common for description of arguments.
-
- Returns:
- tensor with adversarial examples.
- """
- # pylint: enable=g-doc-args
-
- # compute one hot predicted class
- logits = model_fn(x)
- num_classes = tf.shape(logits)[1]
- one_hot_labels = tf.one_hot(tf.argmax(model_fn(x), axis=1), num_classes)
-
- return generate_pgd_common(x, bounds, model_fn, attack_params,
- one_hot_labels=one_hot_labels,
- perturbation_multiplier=1.0)
-
-
-def generate_adversarial_examples(x, bounds, model_fn, attack_description):
- """Generates adversarial examples.
-
- Args:
- x: original examples.
- bounds: tuple with bounds of image values, bounds[0] < bounds[1]
- model_fn: model function with signature model_fn(images).
- attack_description: string which describes an attack, see notes below for
- details.
-
- Returns:
- Tensor with adversarial examples.
-
- Raises:
- ValueError: if attack description is invalid.
-
-
- Attack description could be one of the following strings:
- - "clean" - no attack, return original images.
- - "pgd_EPS_STEP_NITER" - non-targeted PGD attack.
- - "pgdll_EPS_STEP_NITER" - tageted PGD attack with least likely target class.
- - "pgdrnd_EPS_STEP_NITER" - targetd PGD attack with random target class.
-
- Meaning of attack parameters is following:
- - EPS - maximum size of adversarial perturbation, between 0 and 255.
- - STEP - step size of one iteration of PGD, between 0 and 255.
- - NITER - number of iterations.
- """
- if attack_description == 'clean':
- return x
- idx = attack_description.find('_')
- if idx < 0:
- raise ValueError('Invalid value of attack description %s'
- % attack_description)
- attack_name = attack_description[:idx]
- attack_params = attack_description[idx+1:]
- if attack_name == 'pgdll':
- return generate_pgd_ll(x, bounds, model_fn, attack_params)
- elif attack_name == 'pgdrnd':
- return generate_pgd_rand(x, bounds, model_fn, attack_params)
- elif attack_name == 'pgd':
- return generate_pgd(x, bounds, model_fn, attack_params)
- else:
- raise ValueError('Invalid value of attack description %s'
- % attack_description)
-
diff --git a/research/adversarial_logit_pairing/datasets/__init__.py b/research/adversarial_logit_pairing/datasets/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/adversarial_logit_pairing/datasets/dataset_factory.py b/research/adversarial_logit_pairing/datasets/dataset_factory.py
deleted file mode 100644
index 01c36d4ff4710e1742e989b20a3daef75a6922e1..0000000000000000000000000000000000000000
--- a/research/adversarial_logit_pairing/datasets/dataset_factory.py
+++ /dev/null
@@ -1,62 +0,0 @@
-# Copyright 2018 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Library which creates datasets."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from datasets import imagenet_input
-from datasets import tiny_imagenet_input
-
-
-def get_dataset(dataset_name, split, batch_size, image_size, is_training):
- """Returns dataset.
-
- Args:
- dataset_name: name of the dataset, "imagenet" or "tiny_imagenet".
- split: name of the split, "train" or "validation".
- batch_size: size of the minibatch.
- image_size: size of the one side of the image. Output images will be
- resized to square shape image_size*image_size.
- is_training: if True then training preprocessing is done, otherwise eval
- preprocessing is done.
-
- Raises:
- ValueError: if dataset_name is invalid.
-
- Returns:
- dataset: instance of tf.data.Dataset with the dataset.
- num_examples: number of examples in given split of the dataset.
- num_classes: number of classes in the dataset.
- bounds: tuple with bounds of image values. All returned image pixels
- are between bounds[0] and bounds[1].
- """
- if dataset_name == 'tiny_imagenet':
- dataset = tiny_imagenet_input.tiny_imagenet_input(
- split, batch_size, image_size, is_training)
- num_examples = tiny_imagenet_input.num_examples_per_epoch(split)
- num_classes = 200
- bounds = (-1, 1)
- elif dataset_name == 'imagenet':
- dataset = imagenet_input.imagenet_input(
- split, batch_size, image_size, is_training)
- num_examples = imagenet_input.num_examples_per_epoch(split)
- num_classes = 1001
- bounds = (-1, 1)
- else:
- raise ValueError('Invalid dataset %s' % dataset_name)
- return dataset, num_examples, num_classes, bounds
diff --git a/research/adversarial_logit_pairing/datasets/imagenet_input.py b/research/adversarial_logit_pairing/datasets/imagenet_input.py
deleted file mode 100644
index 0b210b8ce11f3dbf1f14482b1b4f3a95da02a48a..0000000000000000000000000000000000000000
--- a/research/adversarial_logit_pairing/datasets/imagenet_input.py
+++ /dev/null
@@ -1,255 +0,0 @@
-# Copyright 2018 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Imagenet input."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-from absl import flags
-import tensorflow as tf
-
-FLAGS = flags.FLAGS
-
-
-flags.DEFINE_string('imagenet_data_dir', None,
- 'Directory with Imagenet dataset in TFRecord format.')
-
-
-def _decode_and_random_crop(image_buffer, bbox, image_size):
- """Randomly crops image and then scales to target size."""
- with tf.name_scope('distorted_bounding_box_crop',
- values=[image_buffer, bbox]):
- sample_distorted_bounding_box = tf.image.sample_distorted_bounding_box(
- tf.image.extract_jpeg_shape(image_buffer),
- bounding_boxes=bbox,
- min_object_covered=0.1,
- aspect_ratio_range=[0.75, 1.33],
- area_range=[0.08, 1.0],
- max_attempts=10,
- use_image_if_no_bounding_boxes=True)
- bbox_begin, bbox_size, _ = sample_distorted_bounding_box
-
- # Crop the image to the specified bounding box.
- offset_y, offset_x, _ = tf.unstack(bbox_begin)
- target_height, target_width, _ = tf.unstack(bbox_size)
- crop_window = tf.stack([offset_y, offset_x, target_height, target_width])
- image = tf.image.decode_and_crop_jpeg(image_buffer, crop_window, channels=3)
- image = tf.image.convert_image_dtype(
- image, dtype=tf.float32)
-
- image = tf.image.resize_bicubic([image],
- [image_size, image_size])[0]
-
- return image
-
-
-def _decode_and_center_crop(image_buffer, image_size):
- """Crops to center of image with padding then scales to target size."""
- shape = tf.image.extract_jpeg_shape(image_buffer)
- image_height = shape[0]
- image_width = shape[1]
-
- padded_center_crop_size = tf.cast(
- 0.875 * tf.cast(tf.minimum(image_height, image_width), tf.float32),
- tf.int32)
-
- offset_height = ((image_height - padded_center_crop_size) + 1) // 2
- offset_width = ((image_width - padded_center_crop_size) + 1) // 2
- crop_window = tf.stack([offset_height, offset_width,
- padded_center_crop_size, padded_center_crop_size])
- image = tf.image.decode_and_crop_jpeg(image_buffer, crop_window, channels=3)
- image = tf.image.convert_image_dtype(
- image, dtype=tf.float32)
-
- image = tf.image.resize_bicubic([image],
- [image_size, image_size])[0]
-
- return image
-
-
-def _normalize(image):
- """Rescale image to [-1, 1] range."""
- return tf.multiply(tf.subtract(image, 0.5), 2.0)
-
-
-def image_preprocessing(image_buffer, bbox, image_size, is_training):
- """Does image decoding and preprocessing.
-
- Args:
- image_buffer: string tensor with encoded image.
- bbox: bounding box of the object at the image.
- image_size: image size.
- is_training: whether to do training or eval preprocessing.
-
- Returns:
- Tensor with the image.
- """
- if is_training:
- image = _decode_and_random_crop(image_buffer, bbox, image_size)
- image = _normalize(image)
- image = tf.image.random_flip_left_right(image)
- else:
- image = _decode_and_center_crop(image_buffer, image_size)
- image = _normalize(image)
- image = tf.reshape(image, [image_size, image_size, 3])
- return image
-
-
-def imagenet_parser(value, image_size, is_training):
- """Parse an ImageNet record from a serialized string Tensor.
-
- Args:
- value: encoded example.
- image_size: size of the output image.
- is_training: if True then do training preprocessing,
- otherwise do eval preprocessing.
-
- Returns:
- image: tensor with the image.
- label: true label of the image.
- """
- keys_to_features = {
- 'image/encoded':
- tf.FixedLenFeature((), tf.string, ''),
- 'image/format':
- tf.FixedLenFeature((), tf.string, 'jpeg'),
- 'image/class/label':
- tf.FixedLenFeature([], tf.int64, -1),
- 'image/class/text':
- tf.FixedLenFeature([], tf.string, ''),
- 'image/object/bbox/xmin':
- tf.VarLenFeature(dtype=tf.float32),
- 'image/object/bbox/ymin':
- tf.VarLenFeature(dtype=tf.float32),
- 'image/object/bbox/xmax':
- tf.VarLenFeature(dtype=tf.float32),
- 'image/object/bbox/ymax':
- tf.VarLenFeature(dtype=tf.float32),
- 'image/object/class/label':
- tf.VarLenFeature(dtype=tf.int64),
- }
-
- parsed = tf.parse_single_example(value, keys_to_features)
-
- image_buffer = tf.reshape(parsed['image/encoded'], shape=[])
-
- xmin = tf.expand_dims(parsed['image/object/bbox/xmin'].values, 0)
- ymin = tf.expand_dims(parsed['image/object/bbox/ymin'].values, 0)
- xmax = tf.expand_dims(parsed['image/object/bbox/xmax'].values, 0)
- ymax = tf.expand_dims(parsed['image/object/bbox/ymax'].values, 0)
- # Note that ordering is (y, x)
- bbox = tf.concat([ymin, xmin, ymax, xmax], 0)
- # Force the variable number of bounding boxes into the shape
- # [1, num_boxes, coords].
- bbox = tf.expand_dims(bbox, 0)
- bbox = tf.transpose(bbox, [0, 2, 1])
-
- image = image_preprocessing(
- image_buffer=image_buffer,
- bbox=bbox,
- image_size=image_size,
- is_training=is_training
- )
-
- # Labels are in [1, 1000] range
- label = tf.cast(
- tf.reshape(parsed['image/class/label'], shape=[]), dtype=tf.int32)
-
- return image, label
-
-
-def imagenet_input(split, batch_size, image_size, is_training):
- """Returns ImageNet dataset.
-
- Args:
- split: name of the split, "train" or "validation".
- batch_size: size of the minibatch.
- image_size: size of the one side of the image. Output images will be
- resized to square shape image_size*image_size.
- is_training: if True then training preprocessing is done, otherwise eval
- preprocessing is done.
-
- Raises:
- ValueError: if name of the split is incorrect.
-
- Returns:
- Instance of tf.data.Dataset with the dataset.
- """
- if split.lower().startswith('train'):
- file_pattern = os.path.join(FLAGS.imagenet_data_dir, 'train-*')
- elif split.lower().startswith('validation'):
- file_pattern = os.path.join(FLAGS.imagenet_data_dir, 'validation-*')
- else:
- raise ValueError('Invalid split: %s' % split)
-
- dataset = tf.data.Dataset.list_files(file_pattern, shuffle=is_training)
-
- if is_training:
- dataset = dataset.repeat()
-
- def fetch_dataset(filename):
- return tf.data.TFRecordDataset(filename, buffer_size=8*1024*1024)
-
- # Read the data from disk in parallel
- dataset = dataset.apply(
- tf.data.experimental.parallel_interleave(
- fetch_dataset, cycle_length=4, sloppy=True))
- dataset = dataset.shuffle(1024)
-
- # Parse, preprocess, and batch the data in parallel
- dataset = dataset.apply(
- tf.data.experimental.map_and_batch(
- lambda value: imagenet_parser(value, image_size, is_training),
- batch_size=batch_size,
- num_parallel_batches=4,
- drop_remainder=True))
-
- def set_shapes(images, labels):
- """Statically set the batch_size dimension."""
- images.set_shape(images.get_shape().merge_with(
- tf.TensorShape([batch_size, None, None, None])))
- labels.set_shape(labels.get_shape().merge_with(
- tf.TensorShape([batch_size])))
- return images, labels
-
- # Assign static batch size dimension
- dataset = dataset.map(set_shapes)
-
- # Prefetch overlaps in-feed with training
- dataset = dataset.prefetch(tf.data.experimental.AUTOTUNE)
- return dataset
-
-
-def num_examples_per_epoch(split):
- """Returns the number of examples in the data set.
-
- Args:
- split: name of the split, "train" or "validation".
-
- Raises:
- ValueError: if split name is incorrect.
-
- Returns:
- Number of example in the split.
- """
- if split.lower().startswith('train'):
- return 1281167
- elif split.lower().startswith('validation'):
- return 50000
- else:
- raise ValueError('Invalid split: %s' % split)
diff --git a/research/adversarial_logit_pairing/datasets/tiny_imagenet_input.py b/research/adversarial_logit_pairing/datasets/tiny_imagenet_input.py
deleted file mode 100644
index 6d216d53ed0bd9f6e7a5770510cedc7f3d9f0a42..0000000000000000000000000000000000000000
--- a/research/adversarial_logit_pairing/datasets/tiny_imagenet_input.py
+++ /dev/null
@@ -1,157 +0,0 @@
-# Copyright 2018 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tiny imagenet input."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-from absl import flags
-import tensorflow as tf
-
-FLAGS = flags.FLAGS
-
-
-flags.DEFINE_string('tiny_imagenet_data_dir', None,
- 'Directory with Tiny Imagenet dataset in TFRecord format.')
-
-
-def tiny_imagenet_parser(value, image_size, is_training):
- """Parses tiny imagenet example.
-
- Args:
- value: encoded example.
- image_size: size of the image.
- is_training: if True then do training preprocessing (which includes
- random cropping), otherwise do eval preprocessing.
-
- Returns:
- image: tensor with the image.
- label: true label of the image.
- """
- keys_to_features = {
- 'image/encoded': tf.FixedLenFeature((), tf.string, ''),
- 'label/tiny_imagenet': tf.FixedLenFeature([], tf.int64, -1),
- }
-
- parsed = tf.parse_single_example(value, keys_to_features)
-
- image_buffer = tf.reshape(parsed['image/encoded'], shape=[])
- image = tf.image.decode_image(image_buffer, channels=3)
- image = tf.image.convert_image_dtype(
- image, dtype=tf.float32)
-
- # Crop image
- if is_training:
- bbox_begin, bbox_size, _ = tf.image.sample_distorted_bounding_box(
- tf.shape(image),
- bounding_boxes=tf.constant([0.0, 0.0, 1.0, 1.0],
- dtype=tf.float32,
- shape=[1, 1, 4]),
- min_object_covered=0.5,
- aspect_ratio_range=[0.75, 1.33],
- area_range=[0.5, 1.0],
- max_attempts=20,
- use_image_if_no_bounding_boxes=True)
- image = tf.slice(image, bbox_begin, bbox_size)
-
- # resize image
- image = tf.image.resize_bicubic([image], [image_size, image_size])[0]
-
- # Rescale image to [-1, 1] range.
- image = tf.multiply(tf.subtract(image, 0.5), 2.0)
-
- image = tf.reshape(image, [image_size, image_size, 3])
-
- # Labels are in [0, 199] range
- label = tf.cast(
- tf.reshape(parsed['label/tiny_imagenet'], shape=[]), dtype=tf.int32)
-
- return image, label
-
-
-def tiny_imagenet_input(split, batch_size, image_size, is_training):
- """Returns Tiny Imagenet Dataset.
-
- Args:
- split: name of the split, "train" or "validation".
- batch_size: size of the minibatch.
- image_size: size of the one side of the image. Output images will be
- resized to square shape image_size*image_size.
- is_training: if True then training preprocessing is done, otherwise eval
- preprocessing is done.instance of tf.data.Dataset with the dataset.
-
- Raises:
- ValueError: if name of the split is incorrect.
-
- Returns:
- Instance of tf.data.Dataset with the dataset.
- """
- if split.lower().startswith('train'):
- filepath = os.path.join(FLAGS.tiny_imagenet_data_dir, 'train.tfrecord')
- elif split.lower().startswith('validation'):
- filepath = os.path.join(FLAGS.tiny_imagenet_data_dir, 'validation.tfrecord')
- else:
- raise ValueError('Invalid split: %s' % split)
-
- dataset = tf.data.TFRecordDataset(filepath, buffer_size=8*1024*1024)
-
- if is_training:
- dataset = dataset.shuffle(10000)
- dataset = dataset.repeat()
-
- dataset = dataset.apply(
- tf.data.experimental.map_and_batch(
- lambda value: tiny_imagenet_parser(value, image_size, is_training),
- batch_size=batch_size,
- num_parallel_batches=4,
- drop_remainder=True))
-
- def set_shapes(images, labels):
- """Statically set the batch_size dimension."""
- images.set_shape(images.get_shape().merge_with(
- tf.TensorShape([batch_size, None, None, None])))
- labels.set_shape(labels.get_shape().merge_with(
- tf.TensorShape([batch_size])))
- return images, labels
-
- # Assign static batch size dimension
- dataset = dataset.map(set_shapes)
-
- dataset = dataset.prefetch(tf.data.experimental.AUTOTUNE)
-
- return dataset
-
-
-def num_examples_per_epoch(split):
- """Returns the number of examples in the data set.
-
- Args:
- split: name of the split, "train" or "validation".
-
- Raises:
- ValueError: if split name is incorrect.
-
- Returns:
- Number of example in the split.
- """
- if split.lower().startswith('train'):
- return 100000
- elif split.lower().startswith('validation'):
- return 10000
- else:
- raise ValueError('Invalid split: %s' % split)
diff --git a/research/adversarial_logit_pairing/eval.py b/research/adversarial_logit_pairing/eval.py
deleted file mode 100644
index 504cc0b0bcf52edff9e7aaa2c0d051079ba521aa..0000000000000000000000000000000000000000
--- a/research/adversarial_logit_pairing/eval.py
+++ /dev/null
@@ -1,181 +0,0 @@
-# Copyright 2018 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Program which runs evaluation of Imagenet 64x64 and TinyImagenet models."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-
-from absl import app
-from absl import flags
-
-import tensorflow as tf
-
-import adversarial_attack
-import model_lib
-from datasets import dataset_factory
-
-FLAGS = flags.FLAGS
-
-
-flags.DEFINE_string('train_dir', None,
- 'Training directory. If specified then this program '
- 'runs in continuous evaluation mode.')
-
-flags.DEFINE_string('checkpoint_path', None,
- 'Path to the file with checkpoint. If specified then '
- 'this program evaluates only provided checkpoint one time.')
-
-flags.DEFINE_string('output_file', None,
- 'Name of output file. Used only in single evaluation mode.')
-
-flags.DEFINE_string('eval_name', 'default', 'Name for eval subdirectory.')
-
-flags.DEFINE_string('master', '', 'Tensorflow master.')
-
-flags.DEFINE_string('model_name', 'resnet_v2_50', 'Name of the model.')
-
-flags.DEFINE_string('adv_method', 'clean',
- 'Method which is used to generate adversarial examples.')
-
-flags.DEFINE_string('dataset', 'imagenet',
- 'Dataset: "tiny_imagenet" or "imagenet".')
-
-flags.DEFINE_integer('dataset_image_size', 64,
- 'Size of the images in the dataset.')
-
-flags.DEFINE_string('hparams', '', 'Hyper parameters.')
-
-flags.DEFINE_string('split_name', 'validation', 'Name of the split.')
-
-flags.DEFINE_float('moving_average_decay', 0.9999,
- 'The decay to use for the moving average.')
-
-flags.DEFINE_integer('eval_interval_secs', 120,
- 'The frequency, in seconds, with which evaluation is run.')
-
-flags.DEFINE_integer(
- 'num_examples', -1,
- 'If positive - maximum number of example to use for evaluation.')
-
-flags.DEFINE_bool('eval_once', False,
- 'If true then evaluate model only once.')
-
-flags.DEFINE_string('trainable_scopes', None,
- 'If set then it defines list of variable scopes for '
- 'trainable variables.')
-
-
-def main(_):
- if not FLAGS.train_dir and not FLAGS.checkpoint_path:
- print('Either --train_dir or --checkpoint_path flags has to be provided.')
- if FLAGS.train_dir and FLAGS.checkpoint_path:
- print('Only one of --train_dir or --checkpoint_path should be provided.')
- params = model_lib.default_hparams()
- params.parse(FLAGS.hparams)
- tf.logging.info('User provided hparams: %s', FLAGS.hparams)
- tf.logging.info('All hyper parameters: %s', params)
- batch_size = params.eval_batch_size
- graph = tf.Graph()
- with graph.as_default():
- # dataset
- dataset, num_examples, num_classes, bounds = dataset_factory.get_dataset(
- FLAGS.dataset,
- FLAGS.split_name,
- batch_size,
- FLAGS.dataset_image_size,
- is_training=False)
- dataset_iterator = dataset.make_one_shot_iterator()
- images, labels = dataset_iterator.get_next()
- if FLAGS.num_examples > 0:
- num_examples = min(num_examples, FLAGS.num_examples)
-
- # setup model
- global_step = tf.train.get_or_create_global_step()
- model_fn_two_args = model_lib.get_model(FLAGS.model_name, num_classes)
- model_fn = lambda x: model_fn_two_args(x, is_training=False)
- if not FLAGS.adv_method or FLAGS.adv_method == 'clean':
- logits = model_fn(images)
- else:
- adv_examples = adversarial_attack.generate_adversarial_examples(
- images, bounds, model_fn, FLAGS.adv_method)
- logits = model_fn(adv_examples)
-
- # update trainable variables if fine tuning is used
- model_lib.filter_trainable_variables(FLAGS.trainable_scopes)
-
- # Setup the moving averages
- if FLAGS.moving_average_decay and (FLAGS.moving_average_decay > 0):
- variable_averages = tf.train.ExponentialMovingAverage(
- FLAGS.moving_average_decay, global_step)
- variables_to_restore = variable_averages.variables_to_restore(
- tf.contrib.framework.get_model_variables())
- variables_to_restore[global_step.op.name] = global_step
- else:
- variables_to_restore = tf.contrib.framework.get_variables_to_restore()
-
- # Setup evaluation metric
- with tf.name_scope('Eval'):
- names_to_values, names_to_updates = (
- tf.contrib.metrics.aggregate_metric_map({
- 'Accuracy': tf.metrics.accuracy(labels, tf.argmax(logits, 1)),
- 'Top5': tf.metrics.recall_at_k(tf.to_int64(labels), logits, 5)
- }))
-
- for name, value in names_to_values.iteritems():
- tf.summary.scalar(name, value)
-
- # Run evaluation
- num_batches = int(num_examples / batch_size)
- if FLAGS.train_dir:
- output_dir = os.path.join(FLAGS.train_dir, FLAGS.eval_name)
- if not tf.gfile.Exists(output_dir):
- tf.gfile.MakeDirs(output_dir)
- tf.contrib.training.evaluate_repeatedly(
- FLAGS.train_dir,
- master=FLAGS.master,
- scaffold=tf.train.Scaffold(
- saver=tf.train.Saver(variables_to_restore)),
- eval_ops=names_to_updates.values(),
- eval_interval_secs=FLAGS.eval_interval_secs,
- hooks=[
- tf.contrib.training.StopAfterNEvalsHook(num_batches),
- tf.contrib.training.SummaryAtEndHook(output_dir),
- tf.train.LoggingTensorHook(names_to_values, at_end=True),
- ],
- max_number_of_evaluations=1 if FLAGS.eval_once else None)
- else:
- result = tf.contrib.training.evaluate_once(
- FLAGS.checkpoint_path,
- master=FLAGS.master,
- scaffold=tf.train.Scaffold(
- saver=tf.train.Saver(variables_to_restore)),
- eval_ops=names_to_updates.values(),
- final_ops=names_to_values,
- hooks=[
- tf.contrib.training.StopAfterNEvalsHook(num_batches),
- tf.train.LoggingTensorHook(names_to_values, at_end=True),
- ])
- if FLAGS.output_file:
- with tf.gfile.Open(FLAGS.output_file, 'a') as f:
- f.write('%s,%.3f,%.3f\n'
- % (FLAGS.eval_name, result['Accuracy'], result['Top5']))
-
-
-if __name__ == '__main__':
- app.run(main)
diff --git a/research/adversarial_logit_pairing/model_lib.py b/research/adversarial_logit_pairing/model_lib.py
deleted file mode 100644
index 1499a378ea1ba6511122ebe54ceed1226d38d649..0000000000000000000000000000000000000000
--- a/research/adversarial_logit_pairing/model_lib.py
+++ /dev/null
@@ -1,189 +0,0 @@
-# Copyright 2018 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Library with common functions for training and eval."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import six
-
-import tensorflow as tf
-
-from tensorflow.contrib.slim.nets import resnet_v2
-
-
-def default_hparams():
- """Returns default hyperparameters."""
- return tf.contrib.training.HParams(
- # Batch size for training and evaluation.
- batch_size=32,
- eval_batch_size=50,
-
- # General training parameters.
- weight_decay=0.0001,
- label_smoothing=0.1,
-
- # Parameters of the adversarial training.
- train_adv_method='clean', # adversarial training method
- train_lp_weight=0.0, # Weight of adversarial logit pairing loss
-
- # Parameters of the optimizer.
- optimizer='rms', # possible values are: 'rms', 'momentum', 'adam'
- momentum=0.9, # momentum
- rmsprop_decay=0.9, # Decay term for RMSProp
- rmsprop_epsilon=1.0, # Epsilon term for RMSProp
-
- # Parameters of learning rate schedule.
- lr_schedule='exp_decay', # Possible values: 'exp_decay', 'step', 'fixed'
- learning_rate=0.045,
- lr_decay_factor=0.94, # Learning exponential decay
- lr_num_epochs_per_decay=2.0, # Number of epochs per lr decay
- lr_list=[1.0 / 6, 2.0 / 6, 3.0 / 6,
- 4.0 / 6, 5.0 / 6, 1.0, 0.1, 0.01,
- 0.001, 0.0001],
- lr_decay_epochs=[1, 2, 3, 4, 5, 30, 60, 80,
- 90])
-
-
-def get_lr_schedule(hparams, examples_per_epoch, replicas_to_aggregate=1):
- """Returns TensorFlow op which compute learning rate.
-
- Args:
- hparams: hyper parameters.
- examples_per_epoch: number of training examples per epoch.
- replicas_to_aggregate: number of training replicas running in parallel.
-
- Raises:
- ValueError: if learning rate schedule specified in hparams is incorrect.
-
- Returns:
- learning_rate: tensor with learning rate.
- steps_per_epoch: number of training steps per epoch.
- """
- global_step = tf.train.get_or_create_global_step()
- steps_per_epoch = float(examples_per_epoch) / float(hparams.batch_size)
- if replicas_to_aggregate > 0:
- steps_per_epoch /= replicas_to_aggregate
-
- if hparams.lr_schedule == 'exp_decay':
- decay_steps = long(steps_per_epoch * hparams.lr_num_epochs_per_decay)
- learning_rate = tf.train.exponential_decay(
- hparams.learning_rate,
- global_step,
- decay_steps,
- hparams.lr_decay_factor,
- staircase=True)
- elif hparams.lr_schedule == 'step':
- lr_decay_steps = [long(epoch * steps_per_epoch)
- for epoch in hparams.lr_decay_epochs]
- learning_rate = tf.train.piecewise_constant(
- global_step, lr_decay_steps, hparams.lr_list)
- elif hparams.lr_schedule == 'fixed':
- learning_rate = hparams.learning_rate
- else:
- raise ValueError('Invalid value of lr_schedule: %s' % hparams.lr_schedule)
-
- if replicas_to_aggregate > 0:
- learning_rate *= replicas_to_aggregate
-
- return learning_rate, steps_per_epoch
-
-
-def get_optimizer(hparams, learning_rate):
- """Returns optimizer.
-
- Args:
- hparams: hyper parameters.
- learning_rate: learning rate tensor.
-
- Raises:
- ValueError: if type of optimizer specified in hparams is incorrect.
-
- Returns:
- Instance of optimizer class.
- """
- if hparams.optimizer == 'rms':
- optimizer = tf.train.RMSPropOptimizer(learning_rate,
- hparams.rmsprop_decay,
- hparams.momentum,
- hparams.rmsprop_epsilon)
- elif hparams.optimizer == 'momentum':
- optimizer = tf.train.MomentumOptimizer(learning_rate,
- hparams.momentum)
- elif hparams.optimizer == 'adam':
- optimizer = tf.train.AdamOptimizer(learning_rate)
- else:
- raise ValueError('Invalid value of optimizer: %s' % hparams.optimizer)
- return optimizer
-
-
-RESNET_MODELS = {'resnet_v2_50': resnet_v2.resnet_v2_50}
-
-
-def get_model(model_name, num_classes):
- """Returns function which creates model.
-
- Args:
- model_name: Name of the model.
- num_classes: Number of classes.
-
- Raises:
- ValueError: If model_name is invalid.
-
- Returns:
- Function, which creates model when called.
- """
- if model_name.startswith('resnet'):
- def resnet_model(images, is_training, reuse=tf.AUTO_REUSE):
- with tf.contrib.framework.arg_scope(resnet_v2.resnet_arg_scope()):
- resnet_fn = RESNET_MODELS[model_name]
- logits, _ = resnet_fn(images, num_classes, is_training=is_training,
- reuse=reuse)
- logits = tf.reshape(logits, [-1, num_classes])
- return logits
- return resnet_model
- else:
- raise ValueError('Invalid model: %s' % model_name)
-
-
-def filter_trainable_variables(trainable_scopes):
- """Keep only trainable variables which are prefixed with given scopes.
-
- Args:
- trainable_scopes: either list of trainable scopes or string with comma
- separated list of trainable scopes.
-
- This function removes all variables which are not prefixed with given
- trainable_scopes from collection of trainable variables.
- Useful during network fine tuning, when you only need to train subset of
- variables.
- """
- if not trainable_scopes:
- return
- if isinstance(trainable_scopes, six.string_types):
- trainable_scopes = [scope.strip() for scope in trainable_scopes.split(',')]
- trainable_scopes = {scope for scope in trainable_scopes if scope}
- if not trainable_scopes:
- return
- trainable_collection = tf.get_collection_ref(
- tf.GraphKeys.TRAINABLE_VARIABLES)
- non_trainable_vars = [
- v for v in trainable_collection
- if not any([v.op.name.startswith(s) for s in trainable_scopes])
- ]
- for v in non_trainable_vars:
- trainable_collection.remove(v)
diff --git a/research/adversarial_logit_pairing/tiny_imagenet_converter/converter.py b/research/adversarial_logit_pairing/tiny_imagenet_converter/converter.py
deleted file mode 100644
index 4fdccc32071f8c677bb1395e324c6b94aa7e85af..0000000000000000000000000000000000000000
--- a/research/adversarial_logit_pairing/tiny_imagenet_converter/converter.py
+++ /dev/null
@@ -1,241 +0,0 @@
-# Copyright 2018 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Converts Tiny Imagenet dataset into TFRecord format.
-
-As an output this program generates following files in TFRecord format:
-- train.tfrecord
-- validation.tfrecord
-- test.tfrecord
-
-Generated train and validation files will contain tf.Example entries with
-following features:
-- image/encoded - encoded image
-- image/format - image format
-- label/wnid - label WordNet ID
-- label/imagenet - imagenet label [1 ... 1000]
-- label/tiny_imagenet - tiny imagenet label [0 ... 199]
-- bbox/xmin
-- bbox/ymin
-- bbox/xmax
-- bbox/ymax
-
-Test file will contain entries with 'image/encoded' and 'image/format' features.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from collections import namedtuple
-import os
-import random
-
-from absl import app
-from absl import flags
-from absl import logging
-
-import pandas as pd
-
-import tensorflow as tf
-
-
-FLAGS = flags.FLAGS
-
-flags.DEFINE_string('input_dir', '', 'Input directory')
-flags.DEFINE_string('output_dir', '', 'Output directory')
-
-flags.DEFINE_string('imagenet_synsets_path', '',
- 'Optional path to /imagenet_lsvrc_2015_synsets.txt')
-
-
-ImageMetadata = namedtuple('ImageMetadata', ['label', 'x1', 'y1', 'x2', 'y2'])
-
-
-class WnIdToNodeIdConverter(object):
- """Converts WordNet IDs to numerical labels."""
-
- def __init__(self, wnids_path, background_class):
- self._wnid_to_node_id = {}
- self._node_id_to_wnid = {}
- with tf.gfile.Open(wnids_path) as f:
- wnids_sequence = [wnid.strip() for wnid in f.readlines() if wnid.strip()]
- node_id_offset = 1 if background_class else 0
- for i, label in enumerate(wnids_sequence):
- self._wnid_to_node_id[label] = i + node_id_offset
- self._node_id_to_wnid[i + node_id_offset] = label
-
- def to_node_id(self, wnid):
- return self._wnid_to_node_id[wnid]
-
- def to_wnid(self, node_id):
- return self._node_id_to_wnid[node_id]
-
- def all_wnids(self):
- return self._wnid_to_node_id.keys()
-
-
-def read_tiny_imagenet_annotations(annotations_filename,
- images_dir,
- one_label=None):
- """Reads one file with Tiny Imagenet annotations."""
- result = []
- if one_label:
- column_names = ['filename', 'x1', 'y1', 'x2', 'y2']
- else:
- column_names = ['filename', 'label', 'x1', 'y1', 'x2', 'y2']
- with tf.gfile.Open(annotations_filename) as f:
- data = pd.read_csv(f, sep='\t', names=column_names)
- for row in data.itertuples():
- label = one_label if one_label else getattr(row, 'label')
- full_filename = os.path.join(images_dir, getattr(row, 'filename'))
- result.append((full_filename,
- ImageMetadata(label=label,
- x1=getattr(row, 'x1'),
- y1=getattr(row, 'y1'),
- x2=getattr(row, 'x2'),
- y2=getattr(row, 'y2'))))
- return result
-
-
-def read_validation_annotations(validation_dir):
- """Reads validation data annotations."""
- return read_tiny_imagenet_annotations(
- os.path.join(validation_dir, 'val_annotations.txt'),
- os.path.join(validation_dir, 'images'))
-
-
-def read_training_annotations(training_dir):
- """Reads training data annotations."""
- result = []
- sub_dirs = tf.gfile.ListDirectory(training_dir)
- for sub_dir in sub_dirs:
- if not sub_dir.startswith('n'):
- logging.warning('Found non-class directory in training dir: %s', sub_dir)
- continue
- sub_dir_results = read_tiny_imagenet_annotations(
- os.path.join(training_dir, sub_dir, sub_dir + '_boxes.txt'),
- os.path.join(training_dir, sub_dir, 'images'),
- one_label=sub_dir)
- result.extend(sub_dir_results)
- return result
-
-
-def read_test_annotations(test_dir):
- """Reads test data annotations."""
- files = tf.gfile.ListDirectory(os.path.join(test_dir, 'images'))
- return [(os.path.join(test_dir, 'images', f), None)
- for f in files if f.endswith('.JPEG')]
-
-
-def get_image_format(filename):
- """Returns image format from filename."""
- filename = filename.lower()
- if filename.endswith('jpeg') or filename.endswith('jpg'):
- return 'jpeg'
- elif filename.endswith('png'):
- return 'png'
- else:
- raise ValueError('Unrecognized file format: %s' % filename)
-
-
-class TinyImagenetWriter(object):
- """Helper class which writes Tiny Imagenet dataset into TFRecord file."""
-
- def __init__(self, tiny_imagenet_wnid_conveter, imagenet_wnid_converter):
- self.tiny_imagenet_wnid_conveter = tiny_imagenet_wnid_conveter
- self.imagenet_wnid_converter = imagenet_wnid_converter
-
- def write_tf_record(self,
- annotations,
- output_file):
- """Generates TFRecord file from given list of annotations."""
- with tf.python_io.TFRecordWriter(output_file) as writer:
- for image_filename, image_metadata in annotations:
- with tf.gfile.Open(image_filename) as f:
- image_buffer = f.read()
- image_format = get_image_format(image_filename)
- features = {
- 'image/encoded': tf.train.Feature(
- bytes_list=tf.train.BytesList(value=[image_buffer])),
- 'image/format': tf.train.Feature(
- bytes_list=tf.train.BytesList(value=[image_format]))
- }
- if image_metadata:
- # bounding box features
- features['bbox/xmin'] = tf.train.Feature(
- int64_list=tf.train.Int64List(value=[image_metadata.x1]))
- features['bbox/ymin'] = tf.train.Feature(
- int64_list=tf.train.Int64List(value=[image_metadata.y1]))
- features['bbox/xmax'] = tf.train.Feature(
- int64_list=tf.train.Int64List(value=[image_metadata.x2]))
- features['bbox/ymax'] = tf.train.Feature(
- int64_list=tf.train.Int64List(value=[image_metadata.y2]))
- # tiny imagenet label, from [0, 200) iterval
- tiny_imagenet_label = self.tiny_imagenet_wnid_conveter.to_node_id(
- image_metadata.label)
- features['label/wnid'] = tf.train.Feature(
- bytes_list=tf.train.BytesList(value=image_metadata.label))
- features['label/tiny_imagenet'] = tf.train.Feature(
- int64_list=tf.train.Int64List(value=[tiny_imagenet_label]))
- # full imagenet label, from [1, 1001) interval
- if self.imagenet_wnid_converter:
- imagenet_label = self.imagenet_wnid_converter.to_node_id(
- image_metadata.label)
- features['label/imagenet'] = tf.train.Feature(
- int64_list=tf.train.Int64List(value=[imagenet_label]))
- example = tf.train.Example(features=tf.train.Features(feature=features))
- writer.write(example.SerializeToString())
-
-
-def main(_):
- assert FLAGS.input_dir, 'Input directory must be provided'
- assert FLAGS.output_dir, 'Output directory must be provided'
-
- # Create WordNet ID conveters for tiny imagenet and possibly for imagenet
- tiny_imagenet_wnid_conveter = WnIdToNodeIdConverter(
- os.path.join(FLAGS.input_dir, 'wnids.txt'),
- background_class=False)
- if FLAGS.imagenet_synsets_path:
- imagenet_wnid_converter = WnIdToNodeIdConverter(FLAGS.imagenet_synsets_path,
- background_class=True)
- else:
- imagenet_wnid_converter = None
-
- # read tiny imagenet annotations
- train_annotations = read_training_annotations(
- os.path.join(FLAGS.input_dir, 'train'))
- random.shuffle(train_annotations)
- val_annotations = read_validation_annotations(
- os.path.join(FLAGS.input_dir, 'val'))
- test_filenames = read_test_annotations(os.path.join(FLAGS.input_dir, 'test'))
-
- # Generate TFRecord files
- writer = TinyImagenetWriter(tiny_imagenet_wnid_conveter,
- imagenet_wnid_converter)
- tf.logging.info('Converting %d training images', len(train_annotations))
- writer.write_tf_record(train_annotations,
- os.path.join(FLAGS.output_dir, 'train.tfrecord'))
- tf.logging.info('Converting %d validation images ', len(val_annotations))
- writer.write_tf_record(val_annotations,
- os.path.join(FLAGS.output_dir, 'validation.tfrecord'))
- tf.logging.info('Converting %d test images', len(test_filenames))
- writer.write_tf_record(test_filenames,
- os.path.join(FLAGS.output_dir, 'test.tfrecord'))
- tf.logging.info('All files are converted')
-
-
-if __name__ == '__main__':
- app.run(main)
diff --git a/research/adversarial_logit_pairing/train.py b/research/adversarial_logit_pairing/train.py
deleted file mode 100644
index dd20969f8d09c59f7d294ee34a9e41bd44f86b39..0000000000000000000000000000000000000000
--- a/research/adversarial_logit_pairing/train.py
+++ /dev/null
@@ -1,288 +0,0 @@
-# Copyright 2018 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Program which train models."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from absl import app
-from absl import flags
-
-import tensorflow as tf
-
-import adversarial_attack
-import model_lib
-from datasets import dataset_factory
-
-FLAGS = flags.FLAGS
-
-
-flags.DEFINE_integer('max_steps', -1, 'Number of steps to stop at.')
-
-flags.DEFINE_string('output_dir', None,
- 'Training directory where checkpoints will be saved.')
-
-flags.DEFINE_integer('ps_tasks', 0, 'Number of parameter servers.')
-
-flags.DEFINE_integer('task', 0, 'Task ID for running distributed training.')
-
-flags.DEFINE_string('master', '', 'Tensorflow master.')
-
-flags.DEFINE_string('model_name', 'resnet_v2_50', 'Name of the model.')
-
-flags.DEFINE_string('dataset', 'imagenet',
- 'Dataset: "tiny_imagenet" or "imagenet".')
-
-flags.DEFINE_integer('dataset_image_size', 64,
- 'Size of the images in the dataset.')
-
-flags.DEFINE_integer('num_summary_images', 3,
- 'Number of images to display in Tensorboard.')
-
-flags.DEFINE_integer(
- 'save_summaries_steps', 100,
- 'The frequency with which summaries are saved, in steps.')
-
-flags.DEFINE_integer(
- 'save_summaries_secs', None,
- 'The frequency with which summaries are saved, in seconds.')
-
-flags.DEFINE_integer(
- 'save_model_steps', 500,
- 'The frequency with which the model is saved, in steps.')
-
-flags.DEFINE_string('hparams', '', 'Hyper parameters.')
-
-flags.DEFINE_integer('replicas_to_aggregate', 1,
- 'Number of gradients to collect before param updates.')
-
-flags.DEFINE_integer('worker_replicas', 1, 'Number of worker replicas.')
-
-flags.DEFINE_float('moving_average_decay', 0.9999,
- 'The decay to use for the moving average.')
-
-# Flags to control fine tuning
-
-flags.DEFINE_string('finetune_checkpoint_path', None,
- 'Path to checkpoint for fine tuning. '
- 'If None then no fine tuning is done.')
-
-flags.DEFINE_string('finetune_exclude_pretrained_scopes', '',
- 'Variable scopes to exclude when loading checkpoint for '
- 'fine tuning.')
-
-flags.DEFINE_string('finetune_trainable_scopes', None,
- 'If set then it defines list of variable scopes for '
- 'trainable variables.')
-
-
-def _get_finetuning_init_fn(variable_averages):
- """Returns an init functions, used for fine tuning."""
- if not FLAGS.finetune_checkpoint_path:
- return None
-
- if tf.train.latest_checkpoint(FLAGS.output_dir):
- return None
-
- if tf.gfile.IsDirectory(FLAGS.finetune_checkpoint_path):
- checkpoint_path = tf.train.latest_checkpoint(FLAGS.finetune_checkpoint_path)
- else:
- checkpoint_path = FLAGS.finetune_checkpoint_path
-
- if not checkpoint_path:
- tf.logging.warning('Not doing fine tuning, can not find checkpoint in %s',
- FLAGS.finetune_checkpoint_path)
- return None
-
- tf.logging.info('Fine-tuning from %s', checkpoint_path)
-
- if FLAGS.finetune_exclude_pretrained_scopes:
- exclusions = {
- scope.strip()
- for scope in FLAGS.finetune_exclude_pretrained_scopes.split(',')
- }
- else:
- exclusions = set()
-
- filtered_model_variables = [
- v for v in tf.contrib.framework.get_model_variables()
- if not any([v.op.name.startswith(e) for e in exclusions])
- ]
-
- if variable_averages:
- variables_to_restore = {}
- for v in filtered_model_variables:
- # variables_to_restore[variable_averages.average_name(v)] = v
- if v in tf.trainable_variables():
- variables_to_restore[variable_averages.average_name(v)] = v
- else:
- variables_to_restore[v.op.name] = v
- else:
- variables_to_restore = {v.op.name: v for v in filtered_model_variables}
-
- assign_fn = tf.contrib.framework.assign_from_checkpoint_fn(
- checkpoint_path,
- variables_to_restore)
- if assign_fn:
- return lambda _, sess: assign_fn(sess)
- else:
- return None
-
-
-def main(_):
- assert FLAGS.output_dir, '--output_dir has to be provided'
- if not tf.gfile.Exists(FLAGS.output_dir):
- tf.gfile.MakeDirs(FLAGS.output_dir)
- params = model_lib.default_hparams()
- params.parse(FLAGS.hparams)
- tf.logging.info('User provided hparams: %s', FLAGS.hparams)
- tf.logging.info('All hyper parameters: %s', params)
- batch_size = params.batch_size
- graph = tf.Graph()
- with graph.as_default():
- with tf.device(tf.train.replica_device_setter(ps_tasks=FLAGS.ps_tasks)):
- # dataset
- dataset, examples_per_epoch, num_classes, bounds = (
- dataset_factory.get_dataset(
- FLAGS.dataset,
- 'train',
- batch_size,
- FLAGS.dataset_image_size,
- is_training=True))
- dataset_iterator = dataset.make_one_shot_iterator()
- images, labels = dataset_iterator.get_next()
- one_hot_labels = tf.one_hot(labels, num_classes)
-
- # set up model
- global_step = tf.train.get_or_create_global_step()
- model_fn = model_lib.get_model(FLAGS.model_name, num_classes)
- if params.train_adv_method == 'clean':
- logits = model_fn(images, is_training=True)
- adv_examples = None
- else:
- model_fn_eval_mode = lambda x: model_fn(x, is_training=False)
- adv_examples = adversarial_attack.generate_adversarial_examples(
- images, bounds, model_fn_eval_mode, params.train_adv_method)
- all_examples = tf.concat([images, adv_examples], axis=0)
- logits = model_fn(all_examples, is_training=True)
- one_hot_labels = tf.concat([one_hot_labels, one_hot_labels], axis=0)
-
- # update trainable variables if fine tuning is used
- model_lib.filter_trainable_variables(
- FLAGS.finetune_trainable_scopes)
-
- # set up losses
- total_loss = tf.losses.softmax_cross_entropy(
- onehot_labels=one_hot_labels,
- logits=logits,
- label_smoothing=params.label_smoothing)
- tf.summary.scalar('loss_xent', total_loss)
-
- if params.train_lp_weight > 0:
- images1, images2 = tf.split(logits, 2)
- loss_lp = tf.losses.mean_squared_error(
- images1, images2, weights=params.train_lp_weight)
- tf.summary.scalar('loss_lp', loss_lp)
- total_loss += loss_lp
-
- if params.weight_decay > 0:
- loss_wd = (
- params.weight_decay
- * tf.add_n([tf.nn.l2_loss(v) for v in tf.trainable_variables()])
- )
- tf.summary.scalar('loss_wd', loss_wd)
- total_loss += loss_wd
-
- # Setup the moving averages:
- if FLAGS.moving_average_decay and (FLAGS.moving_average_decay > 0):
- with tf.name_scope('moving_average'):
- moving_average_variables = tf.contrib.framework.get_model_variables()
- variable_averages = tf.train.ExponentialMovingAverage(
- FLAGS.moving_average_decay, global_step)
- else:
- moving_average_variables = None
- variable_averages = None
-
- # set up optimizer and training op
- learning_rate, steps_per_epoch = model_lib.get_lr_schedule(
- params, examples_per_epoch, FLAGS.replicas_to_aggregate)
-
- optimizer = model_lib.get_optimizer(params, learning_rate)
-
- optimizer = tf.train.SyncReplicasOptimizer(
- opt=optimizer,
- replicas_to_aggregate=FLAGS.replicas_to_aggregate,
- total_num_replicas=FLAGS.worker_replicas,
- variable_averages=variable_averages,
- variables_to_average=moving_average_variables)
-
- train_op = tf.contrib.training.create_train_op(
- total_loss, optimizer,
- update_ops=tf.get_collection(tf.GraphKeys.UPDATE_OPS))
-
- tf.summary.image('images', images[0:FLAGS.num_summary_images])
- if adv_examples is not None:
- tf.summary.image('adv_images', adv_examples[0:FLAGS.num_summary_images])
- tf.summary.scalar('total_loss', total_loss)
- tf.summary.scalar('learning_rate', learning_rate)
- tf.summary.scalar('current_epoch',
- tf.to_double(global_step) / steps_per_epoch)
-
- # Training
- is_chief = FLAGS.task == 0
-
- scaffold = tf.train.Scaffold(
- init_fn=_get_finetuning_init_fn(variable_averages))
- hooks = [
- tf.train.LoggingTensorHook({'total_loss': total_loss,
- 'global_step': global_step},
- every_n_iter=1),
- tf.train.NanTensorHook(total_loss),
- ]
- chief_only_hooks = [
- tf.train.SummarySaverHook(save_steps=FLAGS.save_summaries_steps,
- save_secs=FLAGS.save_summaries_secs,
- output_dir=FLAGS.output_dir,
- scaffold=scaffold),
- tf.train.CheckpointSaverHook(FLAGS.output_dir,
- save_steps=FLAGS.save_model_steps,
- scaffold=scaffold),
- ]
-
- if FLAGS.max_steps > 0:
- hooks.append(
- tf.train.StopAtStepHook(last_step=FLAGS.max_steps))
-
- # hook for sync replica training
- hooks.append(optimizer.make_session_run_hook(is_chief))
-
- with tf.train.MonitoredTrainingSession(
- master=FLAGS.master,
- is_chief=is_chief,
- checkpoint_dir=FLAGS.output_dir,
- scaffold=scaffold,
- hooks=hooks,
- chief_only_hooks=chief_only_hooks,
- save_checkpoint_secs=None,
- save_summaries_steps=None,
- save_summaries_secs=None) as session:
- while not session.should_stop():
- session.run([train_op])
-
-
-if __name__ == '__main__':
- app.run(main)
diff --git a/research/autoencoder/AdditiveGaussianNoiseAutoencoderRunner.py b/research/autoencoder/AdditiveGaussianNoiseAutoencoderRunner.py
deleted file mode 100644
index 8d8ee08654985250ac61415df96889b4a4cf5f1b..0000000000000000000000000000000000000000
--- a/research/autoencoder/AdditiveGaussianNoiseAutoencoderRunner.py
+++ /dev/null
@@ -1,58 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import sklearn.preprocessing as prep
-import tensorflow as tf
-from tensorflow.examples.tutorials.mnist import input_data
-
-from autoencoder_models.DenoisingAutoencoder import AdditiveGaussianNoiseAutoencoder
-
-mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
-
-
-def standard_scale(X_train, X_test):
- preprocessor = prep.StandardScaler().fit(X_train)
- X_train = preprocessor.transform(X_train)
- X_test = preprocessor.transform(X_test)
- return X_train, X_test
-
-
-def get_random_block_from_data(data, batch_size):
- start_index = np.random.randint(0, len(data) - batch_size)
- return data[start_index:(start_index + batch_size)]
-
-
-X_train, X_test = standard_scale(mnist.train.images, mnist.test.images)
-
-n_samples = int(mnist.train.num_examples)
-training_epochs = 20
-batch_size = 128
-display_step = 1
-
-autoencoder = AdditiveGaussianNoiseAutoencoder(
- n_input=784,
- n_hidden=200,
- transfer_function=tf.nn.softplus,
- optimizer=tf.train.AdamOptimizer(learning_rate = 0.001),
- scale=0.01)
-
-for epoch in range(training_epochs):
- avg_cost = 0.
- total_batch = int(n_samples / batch_size)
- # Loop over all batches
- for i in range(total_batch):
- batch_xs = get_random_block_from_data(X_train, batch_size)
-
- # Fit training using batch data
- cost = autoencoder.partial_fit(batch_xs)
- # Compute average loss
- avg_cost += cost / n_samples * batch_size
-
- # Display logs per epoch step
- if epoch % display_step == 0:
- print("Epoch:", '%d,' % (epoch + 1),
- "Cost:", "{:.9f}".format(avg_cost))
-
-print("Total cost: " + str(autoencoder.calc_total_cost(X_test)))
diff --git a/research/autoencoder/AutoencoderRunner.py b/research/autoencoder/AutoencoderRunner.py
deleted file mode 100644
index 7f1ab2ecd5a91c12960714ea79a864631e634f8c..0000000000000000000000000000000000000000
--- a/research/autoencoder/AutoencoderRunner.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import sklearn.preprocessing as prep
-import tensorflow as tf
-from tensorflow.examples.tutorials.mnist import input_data
-
-from autoencoder_models.Autoencoder import Autoencoder
-
-mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
-
-
-def standard_scale(X_train, X_test):
- preprocessor = prep.StandardScaler().fit(X_train)
- X_train = preprocessor.transform(X_train)
- X_test = preprocessor.transform(X_test)
- return X_train, X_test
-
-
-def get_random_block_from_data(data, batch_size):
- start_index = np.random.randint(0, len(data) - batch_size)
- return data[start_index:(start_index + batch_size)]
-
-
-X_train, X_test = standard_scale(mnist.train.images, mnist.test.images)
-
-n_samples = int(mnist.train.num_examples)
-training_epochs = 20
-batch_size = 128
-display_step = 1
-
-autoencoder = Autoencoder(n_layers=[784, 200],
- transfer_function = tf.nn.softplus,
- optimizer = tf.train.AdamOptimizer(learning_rate = 0.001))
-
-for epoch in range(training_epochs):
- avg_cost = 0.
- total_batch = int(n_samples / batch_size)
- # Loop over all batches
- for i in range(total_batch):
- batch_xs = get_random_block_from_data(X_train, batch_size)
-
- # Fit training using batch data
- cost = autoencoder.partial_fit(batch_xs)
- # Compute average loss
- avg_cost += cost / n_samples * batch_size
-
- # Display logs per epoch step
- if epoch % display_step == 0:
- print("Epoch:", '%d,' % (epoch + 1),
- "Cost:", "{:.9f}".format(avg_cost))
-
-print("Total cost: " + str(autoencoder.calc_total_cost(X_test)))
diff --git a/research/autoencoder/MaskingNoiseAutoencoderRunner.py b/research/autoencoder/MaskingNoiseAutoencoderRunner.py
deleted file mode 100644
index b776302e286ff740ba7b8e6f679a54b23944df12..0000000000000000000000000000000000000000
--- a/research/autoencoder/MaskingNoiseAutoencoderRunner.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import sklearn.preprocessing as prep
-import tensorflow as tf
-from tensorflow.examples.tutorials.mnist import input_data
-
-from autoencoder_models.DenoisingAutoencoder import MaskingNoiseAutoencoder
-
-mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
-
-
-def standard_scale(X_train, X_test):
- preprocessor = prep.StandardScaler().fit(X_train)
- X_train = preprocessor.transform(X_train)
- X_test = preprocessor.transform(X_test)
- return X_train, X_test
-
-
-def get_random_block_from_data(data, batch_size):
- start_index = np.random.randint(0, len(data) - batch_size)
- return data[start_index:(start_index + batch_size)]
-
-
-X_train, X_test = standard_scale(mnist.train.images, mnist.test.images)
-
-n_samples = int(mnist.train.num_examples)
-training_epochs = 100
-batch_size = 128
-display_step = 1
-
-autoencoder = MaskingNoiseAutoencoder(
- n_input=784,
- n_hidden=200,
- transfer_function=tf.nn.softplus,
- optimizer=tf.train.AdamOptimizer(learning_rate=0.001),
- dropout_probability=0.95)
-
-for epoch in range(training_epochs):
- avg_cost = 0.
- total_batch = int(n_samples / batch_size)
- for i in range(total_batch):
- batch_xs = get_random_block_from_data(X_train, batch_size)
-
- cost = autoencoder.partial_fit(batch_xs)
-
- avg_cost += cost / n_samples * batch_size
-
- if epoch % display_step == 0:
- print("Epoch:", '%d,' % (epoch + 1),
- "Cost:", "{:.9f}".format(avg_cost))
-
-print("Total cost: " + str(autoencoder.calc_total_cost(X_test)))
diff --git a/research/autoencoder/README.md b/research/autoencoder/README.md
deleted file mode 100644
index cba7b3b66f59ac9e3810ee1b98d67133296aea25..0000000000000000000000000000000000000000
--- a/research/autoencoder/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/research/autoencoder/VariationalAutoencoderRunner.py b/research/autoencoder/VariationalAutoencoderRunner.py
deleted file mode 100644
index f5ce0045f3c6dfdd357cd874f8ee24df0d8cb3d9..0000000000000000000000000000000000000000
--- a/research/autoencoder/VariationalAutoencoderRunner.py
+++ /dev/null
@@ -1,56 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import sklearn.preprocessing as prep
-import tensorflow as tf
-from tensorflow.examples.tutorials.mnist import input_data
-
-from autoencoder_models.VariationalAutoencoder import VariationalAutoencoder
-
-mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
-
-
-def min_max_scale(X_train, X_test):
- preprocessor = prep.MinMaxScaler().fit(X_train)
- X_train = preprocessor.transform(X_train)
- X_test = preprocessor.transform(X_test)
- return X_train, X_test
-
-
-def get_random_block_from_data(data, batch_size):
- start_index = np.random.randint(0, len(data) - batch_size)
- return data[start_index:(start_index + batch_size)]
-
-
-X_train, X_test = min_max_scale(mnist.train.images, mnist.test.images)
-
-n_samples = int(mnist.train.num_examples)
-training_epochs = 20
-batch_size = 128
-display_step = 1
-
-autoencoder = VariationalAutoencoder(
- n_input=784,
- n_hidden=200,
- optimizer=tf.train.AdamOptimizer(learning_rate = 0.001))
-
-for epoch in range(training_epochs):
- avg_cost = 0.
- total_batch = int(n_samples / batch_size)
- # Loop over all batches
- for i in range(total_batch):
- batch_xs = get_random_block_from_data(X_train, batch_size)
-
- # Fit training using batch data
- cost = autoencoder.partial_fit(batch_xs)
- # Compute average loss
- avg_cost += cost / n_samples * batch_size
-
- # Display logs per epoch step
- if epoch % display_step == 0:
- print("Epoch:", '%d,' % (epoch + 1),
- "Cost:", "{:.9f}".format(avg_cost))
-
-print("Total cost: " + str(autoencoder.calc_total_cost(X_test)))
diff --git a/research/autoencoder/__init__.py b/research/autoencoder/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/autoencoder/autoencoder_models/Autoencoder.py b/research/autoencoder/autoencoder_models/Autoencoder.py
deleted file mode 100644
index 788a14642306ece056fc53a85ba8c60d87d31826..0000000000000000000000000000000000000000
--- a/research/autoencoder/autoencoder_models/Autoencoder.py
+++ /dev/null
@@ -1,91 +0,0 @@
-import numpy as np
-import tensorflow as tf
-
-
-class Autoencoder(object):
-
- def __init__(self, n_layers, transfer_function=tf.nn.softplus, optimizer=tf.train.AdamOptimizer()):
- self.n_layers = n_layers
- self.transfer = transfer_function
-
- network_weights = self._initialize_weights()
- self.weights = network_weights
-
- # model
- self.x = tf.placeholder(tf.float32, [None, self.n_layers[0]])
- self.hidden_encode = []
- h = self.x
- for layer in range(len(self.n_layers)-1):
- h = self.transfer(
- tf.add(tf.matmul(h, self.weights['encode'][layer]['w']),
- self.weights['encode'][layer]['b']))
- self.hidden_encode.append(h)
-
- self.hidden_recon = []
- for layer in range(len(self.n_layers)-1):
- h = self.transfer(
- tf.add(tf.matmul(h, self.weights['recon'][layer]['w']),
- self.weights['recon'][layer]['b']))
- self.hidden_recon.append(h)
- self.reconstruction = self.hidden_recon[-1]
-
- # cost
- self.cost = 0.5 * tf.reduce_sum(tf.pow(tf.subtract(self.reconstruction, self.x), 2.0))
- self.optimizer = optimizer.minimize(self.cost)
-
- init = tf.global_variables_initializer()
- self.sess = tf.Session()
- self.sess.run(init)
-
-
- def _initialize_weights(self):
- all_weights = dict()
- initializer = tf.contrib.layers.xavier_initializer()
- # Encoding network weights
- encoder_weights = []
- for layer in range(len(self.n_layers)-1):
- w = tf.Variable(
- initializer((self.n_layers[layer], self.n_layers[layer + 1]),
- dtype=tf.float32))
- b = tf.Variable(
- tf.zeros([self.n_layers[layer + 1]], dtype=tf.float32))
- encoder_weights.append({'w': w, 'b': b})
- # Recon network weights
- recon_weights = []
- for layer in range(len(self.n_layers)-1, 0, -1):
- w = tf.Variable(
- initializer((self.n_layers[layer], self.n_layers[layer - 1]),
- dtype=tf.float32))
- b = tf.Variable(
- tf.zeros([self.n_layers[layer - 1]], dtype=tf.float32))
- recon_weights.append({'w': w, 'b': b})
- all_weights['encode'] = encoder_weights
- all_weights['recon'] = recon_weights
- return all_weights
-
- def partial_fit(self, X):
- cost, opt = self.sess.run((self.cost, self.optimizer), feed_dict={self.x: X})
- return cost
-
- def calc_total_cost(self, X):
- return self.sess.run(self.cost, feed_dict={self.x: X})
-
- def transform(self, X):
- return self.sess.run(self.hidden_encode[-1], feed_dict={self.x: X})
-
- def generate(self, hidden=None):
- if hidden is None:
- hidden = np.random.normal(size=self.weights['encode'][-1]['b'])
- return self.sess.run(self.reconstruction, feed_dict={self.hidden_encode[-1]: hidden})
-
- def reconstruct(self, X):
- return self.sess.run(self.reconstruction, feed_dict={self.x: X})
-
- def getWeights(self):
- raise NotImplementedError
- return self.sess.run(self.weights)
-
- def getBiases(self):
- raise NotImplementedError
- return self.sess.run(self.weights)
-
diff --git a/research/autoencoder/autoencoder_models/DenoisingAutoencoder.py b/research/autoencoder/autoencoder_models/DenoisingAutoencoder.py
deleted file mode 100644
index 22b5dcb44a4079b80bfcfc16e3dcda5b21ca8c1b..0000000000000000000000000000000000000000
--- a/research/autoencoder/autoencoder_models/DenoisingAutoencoder.py
+++ /dev/null
@@ -1,129 +0,0 @@
-import tensorflow as tf
-
-class AdditiveGaussianNoiseAutoencoder(object):
- def __init__(self, n_input, n_hidden, transfer_function = tf.nn.softplus, optimizer = tf.train.AdamOptimizer(),
- scale = 0.1):
- self.n_input = n_input
- self.n_hidden = n_hidden
- self.transfer = transfer_function
- self.scale = tf.placeholder(tf.float32)
- self.training_scale = scale
- network_weights = self._initialize_weights()
- self.weights = network_weights
-
- # model
- self.x = tf.placeholder(tf.float32, [None, self.n_input])
- self.hidden = self.transfer(tf.add(tf.matmul(self.x + scale * tf.random_normal((n_input,)),
- self.weights['w1']),
- self.weights['b1']))
- self.reconstruction = tf.add(tf.matmul(self.hidden, self.weights['w2']), self.weights['b2'])
-
- # cost
- self.cost = 0.5 * tf.reduce_sum(tf.pow(tf.subtract(self.reconstruction, self.x), 2.0))
- self.optimizer = optimizer.minimize(self.cost)
-
- init = tf.global_variables_initializer()
- self.sess = tf.Session()
- self.sess.run(init)
-
- def _initialize_weights(self):
- all_weights = dict()
- all_weights['w1'] = tf.get_variable("w1", shape=[self.n_input, self.n_hidden],
- initializer=tf.contrib.layers.xavier_initializer())
- all_weights['b1'] = tf.Variable(tf.zeros([self.n_hidden], dtype = tf.float32))
- all_weights['w2'] = tf.Variable(tf.zeros([self.n_hidden, self.n_input], dtype = tf.float32))
- all_weights['b2'] = tf.Variable(tf.zeros([self.n_input], dtype = tf.float32))
- return all_weights
-
- def partial_fit(self, X):
- cost, opt = self.sess.run((self.cost, self.optimizer), feed_dict = {self.x: X,
- self.scale: self.training_scale
- })
- return cost
-
- def calc_total_cost(self, X):
- return self.sess.run(self.cost, feed_dict = {self.x: X,
- self.scale: self.training_scale
- })
-
- def transform(self, X):
- return self.sess.run(self.hidden, feed_dict = {self.x: X,
- self.scale: self.training_scale
- })
-
- def generate(self, hidden=None):
- if hidden is None:
- hidden = self.sess.run(tf.random_normal([1, self.n_hidden]))
- return self.sess.run(self.reconstruction, feed_dict = {self.hidden: hidden})
-
- def reconstruct(self, X):
- return self.sess.run(self.reconstruction, feed_dict = {self.x: X,
- self.scale: self.training_scale
- })
-
- def getWeights(self):
- return self.sess.run(self.weights['w1'])
-
- def getBiases(self):
- return self.sess.run(self.weights['b1'])
-
-
-class MaskingNoiseAutoencoder(object):
- def __init__(self, n_input, n_hidden, transfer_function = tf.nn.softplus, optimizer = tf.train.AdamOptimizer(),
- dropout_probability = 0.95):
- self.n_input = n_input
- self.n_hidden = n_hidden
- self.transfer = transfer_function
- self.dropout_probability = dropout_probability
- self.keep_prob = tf.placeholder(tf.float32)
-
- network_weights = self._initialize_weights()
- self.weights = network_weights
-
- # model
- self.x = tf.placeholder(tf.float32, [None, self.n_input])
- self.hidden = self.transfer(tf.add(tf.matmul(tf.nn.dropout(self.x, self.keep_prob), self.weights['w1']),
- self.weights['b1']))
- self.reconstruction = tf.add(tf.matmul(self.hidden, self.weights['w2']), self.weights['b2'])
-
- # cost
- self.cost = 0.5 * tf.reduce_sum(tf.pow(tf.subtract(self.reconstruction, self.x), 2.0))
- self.optimizer = optimizer.minimize(self.cost)
-
- init = tf.global_variables_initializer()
- self.sess = tf.Session()
- self.sess.run(init)
-
- def _initialize_weights(self):
- all_weights = dict()
- all_weights['w1'] = tf.get_variable("w1", shape=[self.n_input, self.n_hidden],
- initializer=tf.contrib.layers.xavier_initializer())
- all_weights['b1'] = tf.Variable(tf.zeros([self.n_hidden], dtype = tf.float32))
- all_weights['w2'] = tf.Variable(tf.zeros([self.n_hidden, self.n_input], dtype = tf.float32))
- all_weights['b2'] = tf.Variable(tf.zeros([self.n_input], dtype = tf.float32))
- return all_weights
-
- def partial_fit(self, X):
- cost, opt = self.sess.run((self.cost, self.optimizer),
- feed_dict = {self.x: X, self.keep_prob: self.dropout_probability})
- return cost
-
- def calc_total_cost(self, X):
- return self.sess.run(self.cost, feed_dict = {self.x: X, self.keep_prob: 1.0})
-
- def transform(self, X):
- return self.sess.run(self.hidden, feed_dict = {self.x: X, self.keep_prob: 1.0})
-
- def generate(self, hidden=None):
- if hidden is None:
- hidden = self.sess.run(tf.random_normal([1, self.n_hidden]))
- return self.sess.run(self.reconstruction, feed_dict = {self.hidden: hidden})
-
- def reconstruct(self, X):
- return self.sess.run(self.reconstruction, feed_dict = {self.x: X, self.keep_prob: 1.0})
-
- def getWeights(self):
- return self.sess.run(self.weights['w1'])
-
- def getBiases(self):
- return self.sess.run(self.weights['b1'])
diff --git a/research/autoencoder/autoencoder_models/VariationalAutoencoder.py b/research/autoencoder/autoencoder_models/VariationalAutoencoder.py
deleted file mode 100644
index 3c2556ab89c2d32be0af5e61099aa12f91c1f176..0000000000000000000000000000000000000000
--- a/research/autoencoder/autoencoder_models/VariationalAutoencoder.py
+++ /dev/null
@@ -1,70 +0,0 @@
-import tensorflow as tf
-
-class VariationalAutoencoder(object):
-
- def __init__(self, n_input, n_hidden, optimizer = tf.train.AdamOptimizer()):
- self.n_input = n_input
- self.n_hidden = n_hidden
-
- network_weights = self._initialize_weights()
- self.weights = network_weights
-
- # model
- self.x = tf.placeholder(tf.float32, [None, self.n_input])
- self.z_mean = tf.add(tf.matmul(self.x, self.weights['w1']), self.weights['b1'])
- self.z_log_sigma_sq = tf.add(tf.matmul(self.x, self.weights['log_sigma_w1']), self.weights['log_sigma_b1'])
-
- # sample from gaussian distribution
- eps = tf.random_normal(tf.stack([tf.shape(self.x)[0], self.n_hidden]), 0, 1, dtype = tf.float32)
- self.z = tf.add(self.z_mean, tf.multiply(tf.sqrt(tf.exp(self.z_log_sigma_sq)), eps))
-
- self.reconstruction = tf.add(tf.matmul(self.z, self.weights['w2']), self.weights['b2'])
-
- # cost
- reconstr_loss = 0.5 * tf.reduce_sum(tf.pow(tf.subtract(self.reconstruction, self.x), 2.0), 1)
- latent_loss = -0.5 * tf.reduce_sum(1 + self.z_log_sigma_sq
- - tf.square(self.z_mean)
- - tf.exp(self.z_log_sigma_sq), 1)
- self.cost = tf.reduce_mean(reconstr_loss + latent_loss)
- self.optimizer = optimizer.minimize(self.cost)
-
- init = tf.global_variables_initializer()
- self.sess = tf.Session()
- self.sess.run(init)
-
- def _initialize_weights(self):
- all_weights = dict()
- all_weights['w1'] = tf.get_variable("w1", shape=[self.n_input, self.n_hidden],
- initializer=tf.contrib.layers.xavier_initializer())
- all_weights['log_sigma_w1'] = tf.get_variable("log_sigma_w1", shape=[self.n_input, self.n_hidden],
- initializer=tf.contrib.layers.xavier_initializer())
- all_weights['b1'] = tf.Variable(tf.zeros([self.n_hidden], dtype=tf.float32))
- all_weights['log_sigma_b1'] = tf.Variable(tf.zeros([self.n_hidden], dtype=tf.float32))
- all_weights['w2'] = tf.Variable(tf.zeros([self.n_hidden, self.n_input], dtype=tf.float32))
- all_weights['b2'] = tf.Variable(tf.zeros([self.n_input], dtype=tf.float32))
- return all_weights
-
- def partial_fit(self, X):
- cost, opt = self.sess.run((self.cost, self.optimizer), feed_dict={self.x: X})
- return cost
-
- def calc_total_cost(self, X):
- return self.sess.run(self.cost, feed_dict = {self.x: X})
-
- def transform(self, X):
- return self.sess.run(self.z_mean, feed_dict={self.x: X})
-
- def generate(self, hidden = None):
- if hidden is None:
- hidden = self.sess.run(tf.random_normal([1, self.n_hidden]))
- return self.sess.run(self.reconstruction, feed_dict={self.z: hidden})
-
- def reconstruct(self, X):
- return self.sess.run(self.reconstruction, feed_dict={self.x: X})
-
- def getWeights(self):
- return self.sess.run(self.weights['w1'])
-
- def getBiases(self):
- return self.sess.run(self.weights['b1'])
-
diff --git a/research/autoencoder/autoencoder_models/__init__.py b/research/autoencoder/autoencoder_models/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/brain_coder/README.md b/research/brain_coder/README.md
deleted file mode 100644
index 3e2a1656d8f145569266c19c64b41779ccbf308c..0000000000000000000000000000000000000000
--- a/research/brain_coder/README.md
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-# Brain Coder
-
-*Authors: Daniel Abolafia, Mohammad Norouzi, Quoc Le*
-
-Brain coder is a code synthesis experimental environment. We provide code that reproduces the results from our recent paper [Neural Program Synthesis with Priority Queue Training](https://arxiv.org/abs/1801.03526). See single_task/README.md for details on how to build and reproduce those experiments.
-
-## Installation
-
-First install dependencies seperately:
-
-* [bazel](https://docs.bazel.build/versions/master/install.html)
-* [TensorFlow](https://www.tensorflow.org/install/)
-* [scipy](https://www.scipy.org/install.html)
-* [absl-py](https://github.com/abseil/abseil-py)
-
-Note: even if you already have these dependencies installed, make sure they are
-up-to-date to avoid unnecessary debugging.
-
-
-## Building
-
-Use bazel from the top-level repo directory.
-
-For example:
-
-```bash
-bazel build single_task:run
-```
-
-View README.md files in subdirectories for more details.
diff --git a/research/brain_coder/WORKSPACE b/research/brain_coder/WORKSPACE
deleted file mode 100644
index 7c07b5325e71a1684fb38089adeaaa9f4f00a775..0000000000000000000000000000000000000000
--- a/research/brain_coder/WORKSPACE
+++ /dev/null
@@ -1,5 +0,0 @@
-git_repository(
- name = "subpar",
- remote = "https://github.com/google/subpar",
- tag = "1.0.0",
-)
diff --git a/research/brain_coder/common/BUILD b/research/brain_coder/common/BUILD
deleted file mode 100644
index b5f79c25096ca574d4a133f871343eedd985b25e..0000000000000000000000000000000000000000
--- a/research/brain_coder/common/BUILD
+++ /dev/null
@@ -1,106 +0,0 @@
-licenses(["notice"])
-
-package(default_visibility = [
- "//:__subpackages__",
-])
-
-py_library(
- name = "bf",
- srcs = ["bf.py"],
-)
-
-py_test(
- name = "bf_test",
- srcs = ["bf_test.py"],
- deps = [
- ":bf",
- # tensorflow dep
- ],
-)
-
-py_library(
- name = "config_lib",
- srcs = ["config_lib.py"],
-)
-
-py_test(
- name = "config_lib_test",
- srcs = ["config_lib_test.py"],
- deps = [
- ":config_lib",
- # tensorflow dep
- ],
-)
-
-py_library(
- name = "reward",
- srcs = ["reward.py"],
-)
-
-py_test(
- name = "reward_test",
- srcs = ["reward_test.py"],
- deps = [
- ":reward",
- # numpy dep
- # tensorflow dep
- ],
-)
-
-py_library(
- name = "rollout",
- srcs = ["rollout.py"],
- deps = [
- ":utils",
- # numpy dep
- # scipy dep
- ],
-)
-
-py_test(
- name = "rollout_test",
- srcs = ["rollout_test.py"],
- deps = [
- ":rollout",
- # numpy dep
- # tensorflow dep
- ],
-)
-
-py_library(
- name = "schedules",
- srcs = ["schedules.py"],
- deps = [":config_lib"],
-)
-
-py_test(
- name = "schedules_test",
- srcs = ["schedules_test.py"],
- deps = [
- ":config_lib",
- ":schedules",
- # numpy dep
- # tensorflow dep
- ],
-)
-
-py_library(
- name = "utils",
- srcs = ["utils.py"],
- deps = [
- # file dep
- # absl dep /logging
- # numpy dep
- # tensorflow dep
- ],
-)
-
-py_test(
- name = "utils_test",
- srcs = ["utils_test.py"],
- deps = [
- ":utils",
- # numpy dep
- # tensorflow dep
- ],
-)
diff --git a/research/brain_coder/common/bf.py b/research/brain_coder/common/bf.py
deleted file mode 100644
index f049c45258f7b78a25b5492108b2f8b37c8a55cd..0000000000000000000000000000000000000000
--- a/research/brain_coder/common/bf.py
+++ /dev/null
@@ -1,234 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""BrainF**k interpreter.
-
-Language info: https://en.wikipedia.org/wiki/Brainfuck
-
-Based on public implementation:
-https://github.com/pocmo/Python-Brainfuck/blob/master/brainfuck.py
-"""
-
-from collections import namedtuple
-import time
-
-
-EvalResult = namedtuple(
- 'EvalResult', ['output', 'success', 'failure_reason', 'steps', 'time',
- 'memory', 'program_trace'])
-
-
-ExecutionSnapshot = namedtuple(
- 'ExecutionSnapshot',
- ['codeptr', 'codechar', 'memptr', 'memval', 'memory', 'next_input',
- 'output_buffer'])
-
-
-class Status(object):
- SUCCESS = 'success'
- TIMEOUT = 'timeout'
- STEP_LIMIT = 'step-limit'
- SYNTAX_ERROR = 'syntax-error'
-
-
-CHARS = INT_TO_CHAR = ['>', '<', '+', '-', '[', ']', '.', ',']
-CHAR_TO_INT = dict([(c, i) for i, c in enumerate(INT_TO_CHAR)])
-
-
-class LookAheadIterator(object):
- """Same API as Python iterator, with additional peek method."""
-
- def __init__(self, iterable):
- self._it = iter(iterable)
- self._current_element = None
- self._done = False
- self._preload_next()
-
- def _preload_next(self):
- try:
- self._current_element = self._it.next()
- except StopIteration:
- self._done = True
-
- def next(self):
- if self._done:
- raise StopIteration
- element = self._current_element
- self._preload_next()
- return element
-
- def peek(self, default_value=None):
- if self._done:
- if default_value is None:
- raise StopIteration
- return default_value
- return self._current_element
-
-
-def buildbracemap(code):
- """Build jump map.
-
- Args:
- code: List or string or BF chars.
-
- Returns:
- bracemap: dict mapping open and close brace positions in the code to their
- destination jumps. Specifically, positions of matching open/close braces
- if they exist.
- correct_syntax: True if all braces match. False if there are unmatched
- braces in the code. Even if there are unmatched braces, a bracemap will
- be built, and unmatched braces will map to themselves.
- """
- bracestack, bracemap = [], {}
-
- correct_syntax = True
- for position, command in enumerate(code):
- if command == '[':
- bracestack.append(position)
- if command == ']':
- if not bracestack: # Unmatched closing brace.
- bracemap[position] = position # Don't jump to any position.
- correct_syntax = False
- continue
- start = bracestack.pop()
- bracemap[start] = position
- bracemap[position] = start
- if bracestack: # Unmatched opening braces.
- for pos in bracestack:
- bracemap[pos] = pos # Don't jump to any position.
- correct_syntax = False
- return bracemap, correct_syntax
-
-
-def evaluate(code, input_buffer=None, init_memory=None, base=256, timeout=1.0,
- max_steps=None, require_correct_syntax=True, output_memory=False,
- debug=False):
- """Execute BF code.
-
- Args:
- code: String or list of BF characters. Any character not in CHARS will be
- ignored.
- input_buffer: A list of ints which will be used as the program's input
- stream. Each read op "," will read an int from this list. 0's will be
- read once the end of the list is reached, or if no input buffer is
- given.
- init_memory: A list of ints. Memory for first k positions will be
- initialized to this list (where k = len(init_memory)). Memory positions
- are initialized to 0 by default.
- base: Integer base for the memory. When a memory value is incremented to
- `base` it will overflow to 0. When a memory value is decremented to -1
- it will underflow to `base` - 1.
- timeout: Time limit for program execution in seconds. Set to None to
- disable.
- max_steps: Execution step limit. An execution step is the execution of one
- operation (code character), even if that op has been executed before.
- Execution exits when this many steps are reached. Set to None to
- disable. Disabled by default.
- require_correct_syntax: If True, unmatched braces will cause `evaluate` to
- return without executing the code. The failure reason will be
- `Status.SYNTAX_ERROR`. If False, unmatched braces are ignored
- and execution will continue.
- output_memory: If True, the state of the memory at the end of execution is
- returned.
- debug: If True, then a full program trace will be returned.
-
- Returns:
- EvalResult namedtuple containing
- output: List of ints which were written out by the program with the "."
- operation.
- success: Boolean. Whether execution completed successfully.
- failure_reason: One of the attributes of `Status`. Gives extra info
- about why execution was not successful.
- steps: Number of execution steps the program ran for.
- time: Amount of time in seconds the program ran for.
- memory: If `output_memory` is True, a list of memory cells up to the last
- one written to. otherwise, None.
- """
- input_iter = (
- LookAheadIterator(input_buffer) if input_buffer is not None
- else LookAheadIterator([]))
-
- # Null memory value. This is the value of an empty memory. Also the value
- # returned by the read operation when the input buffer is empty, or the
- # end of the buffer is reached.
- null_value = 0
-
- code = list(code)
- bracemap, correct_syntax = buildbracemap(code) # will modify code list
- if require_correct_syntax and not correct_syntax:
- return EvalResult([], False, Status.SYNTAX_ERROR, 0, 0.0,
- [] if output_memory else None, [] if debug else None)
-
- output_buffer = []
-
- codeptr, cellptr = 0, 0
-
- cells = list(init_memory) if init_memory else [0]
-
- program_trace = [] if debug else None
- success = True
- reason = Status.SUCCESS
- start_time = time.time()
- steps = 0
- while codeptr < len(code):
- command = code[codeptr]
-
- if debug:
- # Add step to program trace.
- program_trace.append(ExecutionSnapshot(
- codeptr=codeptr, codechar=command, memptr=cellptr,
- memval=cells[cellptr], memory=list(cells),
- next_input=input_iter.peek(null_value),
- output_buffer=list(output_buffer)))
-
- if command == '>':
- cellptr += 1
- if cellptr == len(cells): cells.append(null_value)
-
- if command == '<':
- cellptr = 0 if cellptr <= 0 else cellptr - 1
-
- if command == '+':
- cells[cellptr] = cells[cellptr] + 1 if cells[cellptr] < (base - 1) else 0
-
- if command == '-':
- cells[cellptr] = cells[cellptr] - 1 if cells[cellptr] > 0 else (base - 1)
-
- if command == '[' and cells[cellptr] == 0: codeptr = bracemap[codeptr]
- if command == ']' and cells[cellptr] != 0: codeptr = bracemap[codeptr]
-
- if command == '.': output_buffer.append(cells[cellptr])
- if command == ',': cells[cellptr] = next(input_iter, null_value)
-
- codeptr += 1
- steps += 1
-
- if timeout is not None and time.time() - start_time > timeout:
- success = False
- reason = Status.TIMEOUT
- break
- if max_steps is not None and steps >= max_steps:
- success = False
- reason = Status.STEP_LIMIT
- break
-
- if debug:
- # Add step to program trace.
- command = code[codeptr] if codeptr < len(code) else ''
- program_trace.append(ExecutionSnapshot(
- codeptr=codeptr, codechar=command, memptr=cellptr,
- memval=cells[cellptr], memory=list(cells),
- next_input=input_iter.peek(null_value),
- output_buffer=list(output_buffer)))
-
- return EvalResult(
- output=output_buffer,
- success=success,
- failure_reason=reason,
- steps=steps,
- time=time.time() - start_time,
- memory=cells if output_memory else None,
- program_trace=program_trace)
-
-
diff --git a/research/brain_coder/common/bf_test.py b/research/brain_coder/common/bf_test.py
deleted file mode 100644
index 2cbf505601a96ec1fc819f1d01fe551f2fae4a5d..0000000000000000000000000000000000000000
--- a/research/brain_coder/common/bf_test.py
+++ /dev/null
@@ -1,137 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Tests for common.bf."""
-
-import tensorflow as tf
-
-from common import bf # brain coder
-
-
-class BfTest(tf.test.TestCase):
-
- def assertCorrectOutput(self, target_output, eval_result):
- self.assertEqual(target_output, eval_result.output)
- self.assertTrue(eval_result.success)
- self.assertEqual(bf.Status.SUCCESS, eval_result.failure_reason)
-
- def testBasicOps(self):
- self.assertCorrectOutput(
- [3, 1, 2],
- bf.evaluate('+++.--.+.'))
- self.assertCorrectOutput(
- [1, 1, 2],
- bf.evaluate('+.<.>++.'))
- self.assertCorrectOutput(
- [0],
- bf.evaluate('+,.'))
- self.assertCorrectOutput(
- [ord(char) for char in 'Hello World!\n'],
- bf.evaluate(
- '>++++++++[-<+++++++++>]<.>>+>-[+]++>++>+++[>[->+++<<+++>]<<]>-----'
- '.>->+++..+++.>-.<<+[>[+>+]>>]<--------------.>>.+++.------.-------'
- '-.>+.>+.'))
-
- def testBase(self):
- self.assertCorrectOutput(
- [1, 4],
- bf.evaluate('+.--.', base=5, input_buffer=[]))
-
- def testInputBuffer(self):
- self.assertCorrectOutput(
- [2, 3, 4],
- bf.evaluate('>,[>,]<[.<]', input_buffer=[4, 3, 2]))
-
- def testBadChars(self):
- self.assertCorrectOutput(
- [2, 3, 4],
- bf.evaluate('>,[>,]hello----.[[[[[>+.',
- input_buffer=[],
- base=10,
- require_correct_syntax=False))
-
- eval_result = bf.evaluate(
- '+++.]]]]>----.[[[[[>+.',
- input_buffer=[],
- base=10,
- require_correct_syntax=True)
- self.assertEqual([], eval_result.output)
- self.assertFalse(eval_result.success)
- self.assertEqual(bf.Status.SYNTAX_ERROR,
- eval_result.failure_reason)
-
- def testTimeout(self):
- er = bf.evaluate('+.[].', base=5, input_buffer=[], timeout=0.1)
- self.assertEqual(
- ([1], False, bf.Status.TIMEOUT),
- (er.output, er.success, er.failure_reason))
- self.assertTrue(0.07 < er.time < 0.21)
-
- er = bf.evaluate('+.[-].', base=5, input_buffer=[], timeout=0.1)
- self.assertEqual(
- ([1, 0], True, bf.Status.SUCCESS),
- (er.output, er.success, er.failure_reason))
- self.assertTrue(er.time < 0.15)
-
- def testMaxSteps(self):
- er = bf.evaluate('+.[].', base=5, input_buffer=[], timeout=None,
- max_steps=100)
- self.assertEqual(
- ([1], False, bf.Status.STEP_LIMIT, 100),
- (er.output, er.success, er.failure_reason, er.steps))
-
- er = bf.evaluate('+.[-].', base=5, input_buffer=[], timeout=None,
- max_steps=100)
- self.assertEqual(
- ([1, 0], True, bf.Status.SUCCESS),
- (er.output, er.success, er.failure_reason))
- self.assertTrue(er.steps < 100)
-
- def testOutputMemory(self):
- er = bf.evaluate('+>++>+++>++++.', base=256, input_buffer=[],
- output_memory=True)
- self.assertEqual(
- ([4], True, bf.Status.SUCCESS),
- (er.output, er.success, er.failure_reason))
- self.assertEqual([1, 2, 3, 4], er.memory)
-
- def testProgramTrace(self):
- es = bf.ExecutionSnapshot
- er = bf.evaluate(',[.>,].', base=256, input_buffer=[2, 1], debug=True)
- self.assertEqual(
- [es(codeptr=0, codechar=',', memptr=0, memval=0, memory=[0],
- next_input=2, output_buffer=[]),
- es(codeptr=1, codechar='[', memptr=0, memval=2, memory=[2],
- next_input=1, output_buffer=[]),
- es(codeptr=2, codechar='.', memptr=0, memval=2, memory=[2],
- next_input=1, output_buffer=[]),
- es(codeptr=3, codechar='>', memptr=0, memval=2, memory=[2],
- next_input=1, output_buffer=[2]),
- es(codeptr=4, codechar=',', memptr=1, memval=0, memory=[2, 0],
- next_input=1, output_buffer=[2]),
- es(codeptr=5, codechar=']', memptr=1, memval=1, memory=[2, 1],
- next_input=0, output_buffer=[2]),
- es(codeptr=2, codechar='.', memptr=1, memval=1, memory=[2, 1],
- next_input=0, output_buffer=[2]),
- es(codeptr=3, codechar='>', memptr=1, memval=1, memory=[2, 1],
- next_input=0, output_buffer=[2, 1]),
- es(codeptr=4, codechar=',', memptr=2, memval=0, memory=[2, 1, 0],
- next_input=0, output_buffer=[2, 1]),
- es(codeptr=5, codechar=']', memptr=2, memval=0, memory=[2, 1, 0],
- next_input=0, output_buffer=[2, 1]),
- es(codeptr=6, codechar='.', memptr=2, memval=0, memory=[2, 1, 0],
- next_input=0, output_buffer=[2, 1]),
- es(codeptr=7, codechar='', memptr=2, memval=0, memory=[2, 1, 0],
- next_input=0, output_buffer=[2, 1, 0])],
- er.program_trace)
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/brain_coder/common/config_lib.py b/research/brain_coder/common/config_lib.py
deleted file mode 100644
index 733fa202f2e500f964beff2111cb7445fa66a9e1..0000000000000000000000000000000000000000
--- a/research/brain_coder/common/config_lib.py
+++ /dev/null
@@ -1,337 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Objects for storing configuration and passing config into binaries.
-
-Config class stores settings and hyperparameters for models, data, and anything
-else that may be specific to a particular run.
-"""
-
-import ast
-import itertools
-from six.moves import xrange
-
-
-class Config(dict):
- """Stores model configuration, hyperparameters, or dataset parameters."""
-
- def __getattr__(self, attr):
- return self[attr]
-
- def __setattr__(self, attr, value):
- self[attr] = value
-
- def pretty_str(self, new_lines=True, indent=2, final_indent=0):
- prefix = (' ' * indent) if new_lines else ''
- final_prefix = (' ' * final_indent) if new_lines else ''
- kv = ['%s%s=%s' % (prefix, k,
- (repr(v) if not isinstance(v, Config)
- else v.pretty_str(new_lines=new_lines,
- indent=indent+2,
- final_indent=indent)))
- for k, v in self.items()]
- if new_lines:
- return 'Config(\n%s\n%s)' % (',\n'.join(kv), final_prefix)
- else:
- return 'Config(%s)' % ', '.join(kv)
-
- def _update_iterator(self, *args, **kwargs):
- """Convert mixed input into an iterator over (key, value) tuples.
-
- Follows the dict.update call signature.
-
- Args:
- *args: (Optional) Pass a dict or iterable of (key, value) 2-tuples as
- an unnamed argument. Only one unnamed argument allowed.
- **kwargs: (Optional) Pass (key, value) pairs as named arguments, where the
- argument name is the key and the argument value is the value.
-
- Returns:
- An iterator over (key, value) tuples given in the input.
-
- Raises:
- TypeError: If more than one unnamed argument is given.
- """
- if len(args) > 1:
- raise TypeError('Expected at most 1 unnamed arguments, got %d'
- % len(args))
- obj = args[0] if args else dict()
- if isinstance(obj, dict):
- return itertools.chain(obj.items(), kwargs.items())
- # Assume obj is an iterable of 2-tuples.
- return itertools.chain(obj, kwargs.items())
-
- def make_default(self, keys=None):
- """Convert OneOf objects into their default configs.
-
- Recursively calls into Config objects.
-
- Args:
- keys: Iterable of key names to check. If None, all keys in self will be
- used.
- """
- if keys is None:
- keys = self.keys()
- for k in keys:
- # Replace OneOf with its default value.
- if isinstance(self[k], OneOf):
- self[k] = self[k].default()
- # Recursively call into all Config objects, even those that came from
- # OneOf objects in the previous code line (for nested OneOf objects).
- if isinstance(self[k], Config):
- self[k].make_default()
-
- def update(self, *args, **kwargs):
- """Same as dict.update except nested Config objects are updated.
-
- Args:
- *args: (Optional) Pass a dict or list of (key, value) 2-tuples as unnamed
- argument.
- **kwargs: (Optional) Pass (key, value) pairs as named arguments, where the
- argument name is the key and the argument value is the value.
- """
- key_set = set(self.keys())
- for k, v in self._update_iterator(*args, **kwargs):
- if k in key_set:
- key_set.remove(k) # This key is updated so exclude from make_default.
- if k in self and isinstance(self[k], Config) and isinstance(v, dict):
- self[k].update(v)
- elif k in self and isinstance(self[k], OneOf) and isinstance(v, dict):
- # Replace OneOf with the chosen config.
- self[k] = self[k].update(v)
- else:
- self[k] = v
- self.make_default(key_set)
-
- def strict_update(self, *args, **kwargs):
- """Same as Config.update except keys and types are not allowed to change.
-
- If a given key is not already in this instance, an exception is raised. If a
- given value does not have the same type as the existing value for the same
- key, an exception is raised. Use this method to catch config mistakes.
-
- Args:
- *args: (Optional) Pass a dict or list of (key, value) 2-tuples as unnamed
- argument.
- **kwargs: (Optional) Pass (key, value) pairs as named arguments, where the
- argument name is the key and the argument value is the value.
-
- Raises:
- TypeError: If more than one unnamed argument is given.
- TypeError: If new value type does not match existing type.
- KeyError: If a given key is not already defined in this instance.
- """
- key_set = set(self.keys())
- for k, v in self._update_iterator(*args, **kwargs):
- if k in self:
- key_set.remove(k) # This key is updated so exclude from make_default.
- if isinstance(self[k], Config):
- if not isinstance(v, dict):
- raise TypeError('dict required for Config value, got %s' % type(v))
- self[k].strict_update(v)
- elif isinstance(self[k], OneOf):
- if not isinstance(v, dict):
- raise TypeError('dict required for OneOf value, got %s' % type(v))
- # Replace OneOf with the chosen config.
- self[k] = self[k].strict_update(v)
- else:
- if not isinstance(v, type(self[k])):
- raise TypeError('Expecting type %s for key %s, got type %s'
- % (type(self[k]), k, type(v)))
- self[k] = v
- else:
- raise KeyError(
- 'Key %s does not exist. New key creation not allowed in '
- 'strict_update.' % k)
- self.make_default(key_set)
-
- @staticmethod
- def from_str(config_str):
- """Inverse of Config.__str__."""
- parsed = ast.literal_eval(config_str)
- assert isinstance(parsed, dict)
-
- def _make_config(dictionary):
- for k, v in dictionary.items():
- if isinstance(v, dict):
- dictionary[k] = _make_config(v)
- return Config(**dictionary)
- return _make_config(parsed)
-
- @staticmethod
- def parse(key_val_string):
- """Parse hyperparameter string into Config object.
-
- Format is 'key=val,key=val,...'
- Values can be any python literal, or another Config object encoded as
- 'c(key=val,key=val,...)'.
- c(...) expressions can be arbitrarily nested.
-
- Example:
- 'a=1,b=3e-5,c=[1,2,3],d="hello world",e={"a":1,"b":2},f=c(x=1,y=[10,20])'
-
- Args:
- key_val_string: The hyperparameter string.
-
- Returns:
- Config object parsed from the input string.
- """
- if not key_val_string.strip():
- return Config()
- def _pair_to_kv(pair):
- split_index = pair.find('=')
- key, val = pair[:split_index].strip(), pair[split_index+1:].strip()
- if val.startswith('c(') and val.endswith(')'):
- val = Config.parse(val[2:-1])
- else:
- val = ast.literal_eval(val)
- return key, val
- return Config(**dict([_pair_to_kv(pair)
- for pair in _comma_iterator(key_val_string)]))
-
-
-class OneOf(object):
- """Stores branching config.
-
- In some cases there may be options which each have their own set of config
- params. For example, if specifying config for an environment, each environment
- can have custom config options. OneOf is a way to organize branching config.
-
- Usage example:
- one_of = OneOf(
- [Config(a=1, b=2),
- Config(a=2, c='hello'),
- Config(a=3, d=10, e=-10)],
- a=1)
- config = one_of.strict_update(Config(a=3, d=20))
- config == {'a': 3, 'd': 20, 'e': -10}
- """
-
- def __init__(self, choices, **kwargs):
- """Constructor.
-
- Usage: OneOf([Config(...), Config(...), ...], attribute=default_value)
-
- Args:
- choices: An iterable of Config objects. When update/strict_update is
- called on this OneOf, one of these Config will be selected.
- **kwargs: Give exactly one config attribute to branch on. The value of
- this attribute during update/strict_update will determine which
- Config is used.
-
- Raises:
- ValueError: If kwargs does not contain exactly one entry. Should give one
- named argument which is used as the attribute to condition on.
- """
- if len(kwargs) != 1:
- raise ValueError(
- 'Incorrect usage. Must give exactly one named argument. The argument '
- 'name is the config attribute to condition on, and the argument '
- 'value is the default choice. Got %d named arguments.' % len(kwargs))
- key, default_value = kwargs.items()[0]
- self.key = key
- self.default_value = default_value
-
- # Make sure each choice is a Config object.
- for config in choices:
- if not isinstance(config, Config):
- raise TypeError('choices must be a list of Config objects. Got %s.'
- % type(config))
-
- # Map value for key to the config with that value.
- self.value_map = {config[key]: config for config in choices}
- self.default_config = self.value_map[self.default_value]
-
- # Make sure there are no duplicate values.
- if len(self.value_map) != len(choices):
- raise ValueError('Multiple choices given for the same value of %s.' % key)
-
- # Check that the default value is valid.
- if self.default_value not in self.value_map:
- raise ValueError(
- 'Default value is not an available choice. Got %s=%s. Choices are %s.'
- % (key, self.default_value, self.value_map.keys()))
-
- def default(self):
- return self.default_config
-
- def update(self, other):
- """Choose a config and update it.
-
- If `other` is a Config, one of the config choices is selected and updated.
- Otherwise `other` is returned.
-
- Args:
- other: Will update chosen config with this value by calling `update` on
- the config.
-
- Returns:
- The chosen config after updating it, or `other` if no config could be
- selected.
- """
- if not isinstance(other, Config):
- return other
- if self.key not in other or other[self.key] not in self.value_map:
- return other
- target = self.value_map[other[self.key]]
- target.update(other)
- return target
-
- def strict_update(self, config):
- """Choose a config and update it.
-
- `config` must be a Config object. `config` must have the key used to select
- among the config choices, and that key must have a value which one of the
- config choices has.
-
- Args:
- config: A Config object. the chosen config will be update by calling
- `strict_update`.
-
- Returns:
- The chosen config after updating it.
-
- Raises:
- TypeError: If `config` is not a Config instance.
- ValueError: If `config` does not have the branching key in its key set.
- ValueError: If the value of the config's branching key is not one of the
- valid choices.
- """
- if not isinstance(config, Config):
- raise TypeError('Expecting Config instance, got %s.' % type(config))
- if self.key not in config:
- raise ValueError(
- 'Branching key %s required but not found in %s' % (self.key, config))
- if config[self.key] not in self.value_map:
- raise ValueError(
- 'Value %s for key %s is not a possible choice. Choices are %s.'
- % (config[self.key], self.key, self.value_map.keys()))
- target = self.value_map[config[self.key]]
- target.strict_update(config)
- return target
-
-
-def _next_comma(string, start_index):
- """Finds the position of the next comma not used in a literal collection."""
- paren_count = 0
- for i in xrange(start_index, len(string)):
- c = string[i]
- if c == '(' or c == '[' or c == '{':
- paren_count += 1
- elif c == ')' or c == ']' or c == '}':
- paren_count -= 1
- if paren_count == 0 and c == ',':
- return i
- return -1
-
-
-def _comma_iterator(string):
- index = 0
- while 1:
- next_index = _next_comma(string, index)
- if next_index == -1:
- yield string[index:]
- return
- yield string[index:next_index]
- index = next_index + 1
diff --git a/research/brain_coder/common/config_lib_test.py b/research/brain_coder/common/config_lib_test.py
deleted file mode 100644
index cdc96f92d2428f06e780930979662fdfda92e3f5..0000000000000000000000000000000000000000
--- a/research/brain_coder/common/config_lib_test.py
+++ /dev/null
@@ -1,425 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Tests for common.config_lib."""
-
-import tensorflow as tf
-
-from common import config_lib # brain coder
-
-
-class ConfigLibTest(tf.test.TestCase):
-
- def testConfig(self):
- config = config_lib.Config(hello='world', foo='bar', num=123, f=56.7)
- self.assertEqual('world', config.hello)
- self.assertEqual('bar', config['foo'])
- config.hello = 'everyone'
- config['bar'] = 9000
- self.assertEqual('everyone', config['hello'])
- self.assertEqual(9000, config.bar)
- self.assertEqual(5, len(config))
-
- def testConfigUpdate(self):
- config = config_lib.Config(a=1, b=2, c=3)
- config.update({'b': 10, 'd': 4})
- self.assertEqual({'a': 1, 'b': 10, 'c': 3, 'd': 4}, config)
-
- config = config_lib.Config(a=1, b=2, c=3)
- config.update(b=10, d=4)
- self.assertEqual({'a': 1, 'b': 10, 'c': 3, 'd': 4}, config)
-
- config = config_lib.Config(a=1, b=2, c=3)
- config.update({'e': 5}, b=10, d=4)
- self.assertEqual({'a': 1, 'b': 10, 'c': 3, 'd': 4, 'e': 5}, config)
-
- config = config_lib.Config(
- a=1,
- b=2,
- x=config_lib.Config(
- l='a',
- y=config_lib.Config(m=1, n=2),
- z=config_lib.Config(
- q=config_lib.Config(a=10, b=20),
- r=config_lib.Config(s=1, t=2))))
- config.update(x={'y': {'m': 10}, 'z': {'r': {'s': 5}}})
- self.assertEqual(
- config_lib.Config(
- a=1, b=2,
- x=config_lib.Config(
- l='a',
- y=config_lib.Config(m=10, n=2),
- z=config_lib.Config(
- q=config_lib.Config(a=10, b=20),
- r=config_lib.Config(s=5, t=2)))),
- config)
-
- config = config_lib.Config(
- foo='bar',
- num=100,
- x=config_lib.Config(a=1, b=2, c=config_lib.Config(h=10, i=20, j=30)),
- y=config_lib.Config(qrs=5, tuv=10),
- d={'a': 1, 'b': 2},
- l=[1, 2, 3])
- config.update(
- config_lib.Config(
- foo='hat',
- num=50.5,
- x={'a': 5, 'z': -10},
- y=config_lib.Config(wxyz=-1)),
- d={'a': 10, 'c': 20},
- l=[3, 4, 5, 6])
- self.assertEqual(
- config_lib.Config(
- foo='hat',
- num=50.5,
- x=config_lib.Config(a=5, b=2, z=-10,
- c=config_lib.Config(h=10, i=20, j=30)),
- y=config_lib.Config(qrs=5, tuv=10, wxyz=-1),
- d={'a': 10, 'c': 20},
- l=[3, 4, 5, 6]),
- config)
- self.assertTrue(isinstance(config.x, config_lib.Config))
- self.assertTrue(isinstance(config.x.c, config_lib.Config))
- self.assertTrue(isinstance(config.y, config_lib.Config))
-
- config = config_lib.Config(
- foo='bar',
- num=100,
- x=config_lib.Config(a=1, b=2, c=config_lib.Config(h=10, i=20, j=30)),
- y=config_lib.Config(qrs=5, tuv=10),
- d={'a': 1, 'b': 2},
- l=[1, 2, 3])
- config.update(
- config_lib.Config(
- foo=1234,
- num='hello',
- x={'a': 5, 'z': -10, 'c': {'h': -5, 'k': 40}},
- y=[1, 2, 3, 4],
- d='stuff',
- l={'a': 1, 'b': 2}))
- self.assertEqual(
- config_lib.Config(
- foo=1234,
- num='hello',
- x=config_lib.Config(a=5, b=2, z=-10,
- c=config_lib.Config(h=-5, i=20, j=30, k=40)),
- y=[1, 2, 3, 4],
- d='stuff',
- l={'a': 1, 'b': 2}),
- config)
- self.assertTrue(isinstance(config.x, config_lib.Config))
- self.assertTrue(isinstance(config.x.c, config_lib.Config))
- self.assertTrue(isinstance(config.y, list))
-
- def testConfigStrictUpdate(self):
- config = config_lib.Config(a=1, b=2, c=3)
- config.strict_update({'b': 10, 'c': 20})
- self.assertEqual({'a': 1, 'b': 10, 'c': 20}, config)
-
- config = config_lib.Config(a=1, b=2, c=3)
- config.strict_update(b=10, c=20)
- self.assertEqual({'a': 1, 'b': 10, 'c': 20}, config)
-
- config = config_lib.Config(a=1, b=2, c=3, d=4)
- config.strict_update({'d': 100}, b=10, a=20)
- self.assertEqual({'a': 20, 'b': 10, 'c': 3, 'd': 100}, config)
-
- config = config_lib.Config(
- a=1,
- b=2,
- x=config_lib.Config(
- l='a',
- y=config_lib.Config(m=1, n=2),
- z=config_lib.Config(
- q=config_lib.Config(a=10, b=20),
- r=config_lib.Config(s=1, t=2))))
- config.strict_update(x={'y': {'m': 10}, 'z': {'r': {'s': 5}}})
- self.assertEqual(
- config_lib.Config(
- a=1, b=2,
- x=config_lib.Config(
- l='a',
- y=config_lib.Config(m=10, n=2),
- z=config_lib.Config(
- q=config_lib.Config(a=10, b=20),
- r=config_lib.Config(s=5, t=2)))),
- config)
-
- config = config_lib.Config(
- foo='bar',
- num=100,
- x=config_lib.Config(a=1, b=2, c=config_lib.Config(h=10, i=20, j=30)),
- y=config_lib.Config(qrs=5, tuv=10),
- d={'a': 1, 'b': 2},
- l=[1, 2, 3])
- config.strict_update(
- config_lib.Config(
- foo='hat',
- num=50,
- x={'a': 5, 'c': {'h': 100}},
- y=config_lib.Config(tuv=-1)),
- d={'a': 10, 'c': 20},
- l=[3, 4, 5, 6])
- self.assertEqual(
- config_lib.Config(
- foo='hat',
- num=50,
- x=config_lib.Config(a=5, b=2,
- c=config_lib.Config(h=100, i=20, j=30)),
- y=config_lib.Config(qrs=5, tuv=-1),
- d={'a': 10, 'c': 20},
- l=[3, 4, 5, 6]),
- config)
-
- def testConfigStrictUpdateFail(self):
- config = config_lib.Config(a=1, b=2, c=3, x=config_lib.Config(a=1, b=2))
- with self.assertRaises(KeyError):
- config.strict_update({'b': 10, 'c': 20, 'd': 50})
- with self.assertRaises(KeyError):
- config.strict_update(b=10, d=50)
- with self.assertRaises(KeyError):
- config.strict_update(x={'c': 3})
- with self.assertRaises(TypeError):
- config.strict_update(a='string')
- with self.assertRaises(TypeError):
- config.strict_update(x={'a': 'string'})
- with self.assertRaises(TypeError):
- config.strict_update(x=[1, 2, 3])
-
- def testConfigFromStr(self):
- config = config_lib.Config.from_str("{'c': {'d': 5}, 'b': 2, 'a': 1}")
- self.assertEqual(
- {'c': {'d': 5}, 'b': 2, 'a': 1}, config)
- self.assertTrue(isinstance(config, config_lib.Config))
- self.assertTrue(isinstance(config.c, config_lib.Config))
-
- def testConfigParse(self):
- config = config_lib.Config.parse(
- 'hello="world",num=1234.5,lst=[10,20.5,True,"hi",("a","b","c")],'
- 'dct={9:10,"stuff":"qwerty","subdict":{1:True,2:False}},'
- 'subconfig=c(a=1,b=[1,2,[3,4]],c=c(f="f",g="g"))')
- self.assertEqual(
- {'hello': 'world', 'num': 1234.5,
- 'lst': [10, 20.5, True, 'hi', ('a', 'b', 'c')],
- 'dct': {9: 10, 'stuff': 'qwerty', 'subdict': {1: True, 2: False}},
- 'subconfig': {'a': 1, 'b': [1, 2, [3, 4]], 'c': {'f': 'f', 'g': 'g'}}},
- config)
- self.assertTrue(isinstance(config, config_lib.Config))
- self.assertTrue(isinstance(config.subconfig, config_lib.Config))
- self.assertTrue(isinstance(config.subconfig.c, config_lib.Config))
- self.assertFalse(isinstance(config.dct, config_lib.Config))
- self.assertFalse(isinstance(config.dct['subdict'], config_lib.Config))
- self.assertTrue(isinstance(config.lst[4], tuple))
-
- def testConfigParseErrors(self):
- with self.assertRaises(SyntaxError):
- config_lib.Config.parse('a=[1,2,b="hello"')
- with self.assertRaises(SyntaxError):
- config_lib.Config.parse('a=1,b=c(x="a",y="b"')
- with self.assertRaises(SyntaxError):
- config_lib.Config.parse('a=1,b=c(x="a")y="b"')
- with self.assertRaises(SyntaxError):
- config_lib.Config.parse('a=1,b=c(x="a"),y="b",')
-
- def testOneOf(self):
- def make_config():
- return config_lib.Config(
- data=config_lib.OneOf(
- [config_lib.Config(task=1, a='hello'),
- config_lib.Config(task=2, a='world', b='stuff'),
- config_lib.Config(task=3, c=1234)],
- task=2),
- model=config_lib.Config(stuff=1))
-
- config = make_config()
- config.update(config_lib.Config.parse(
- 'model=c(stuff=2),data=c(task=1,a="hi")'))
- self.assertEqual(
- config_lib.Config(
- data=config_lib.Config(task=1, a='hi'),
- model=config_lib.Config(stuff=2)),
- config)
-
- config = make_config()
- config.update(config_lib.Config.parse(
- 'model=c(stuff=2),data=c(task=2,a="hi")'))
- self.assertEqual(
- config_lib.Config(
- data=config_lib.Config(task=2, a='hi', b='stuff'),
- model=config_lib.Config(stuff=2)),
- config)
-
- config = make_config()
- config.update(config_lib.Config.parse(
- 'model=c(stuff=2),data=c(task=3)'))
- self.assertEqual(
- config_lib.Config(
- data=config_lib.Config(task=3, c=1234),
- model=config_lib.Config(stuff=2)),
- config)
-
- config = make_config()
- config.update(config_lib.Config.parse(
- 'model=c(stuff=2)'))
- self.assertEqual(
- config_lib.Config(
- data=config_lib.Config(task=2, a='world', b='stuff'),
- model=config_lib.Config(stuff=2)),
- config)
-
- config = make_config()
- config.update(config_lib.Config.parse(
- 'model=c(stuff=2),data=c(task=4,d=9999)'))
- self.assertEqual(
- config_lib.Config(
- data=config_lib.Config(task=4, d=9999),
- model=config_lib.Config(stuff=2)),
- config)
-
- config = make_config()
- config.update(config_lib.Config.parse(
- 'model=c(stuff=2),data=5'))
- self.assertEqual(
- config_lib.Config(
- data=5,
- model=config_lib.Config(stuff=2)),
- config)
-
- def testOneOfStrict(self):
- def make_config():
- return config_lib.Config(
- data=config_lib.OneOf(
- [config_lib.Config(task=1, a='hello'),
- config_lib.Config(task=2, a='world', b='stuff'),
- config_lib.Config(task=3, c=1234)],
- task=2),
- model=config_lib.Config(stuff=1))
-
- config = make_config()
- config.strict_update(config_lib.Config.parse(
- 'model=c(stuff=2),data=c(task=1,a="hi")'))
- self.assertEqual(
- config_lib.Config(
- data=config_lib.Config(task=1, a='hi'),
- model=config_lib.Config(stuff=2)),
- config)
-
- config = make_config()
- config.strict_update(config_lib.Config.parse(
- 'model=c(stuff=2),data=c(task=2,a="hi")'))
- self.assertEqual(
- config_lib.Config(
- data=config_lib.Config(task=2, a='hi', b='stuff'),
- model=config_lib.Config(stuff=2)),
- config)
-
- config = make_config()
- config.strict_update(config_lib.Config.parse(
- 'model=c(stuff=2),data=c(task=3)'))
- self.assertEqual(
- config_lib.Config(
- data=config_lib.Config(task=3, c=1234),
- model=config_lib.Config(stuff=2)),
- config)
-
- config = make_config()
- config.strict_update(config_lib.Config.parse(
- 'model=c(stuff=2)'))
- self.assertEqual(
- config_lib.Config(
- data=config_lib.Config(task=2, a='world', b='stuff'),
- model=config_lib.Config(stuff=2)),
- config)
-
- def testNestedOneOf(self):
- def make_config():
- return config_lib.Config(
- data=config_lib.OneOf(
- [config_lib.Config(task=1, a='hello'),
- config_lib.Config(
- task=2,
- a=config_lib.OneOf(
- [config_lib.Config(x=1, y=2),
- config_lib.Config(x=-1, y=1000, z=4)],
- x=1)),
- config_lib.Config(task=3, c=1234)],
- task=2),
- model=config_lib.Config(stuff=1))
-
- config = make_config()
- config.update(config_lib.Config.parse(
- 'model=c(stuff=2),data=c(task=2,a=c(x=-1,z=8))'))
- self.assertEqual(
- config_lib.Config(
- data=config_lib.Config(
- task=2,
- a=config_lib.Config(x=-1, y=1000, z=8)),
- model=config_lib.Config(stuff=2)),
- config)
-
- config = make_config()
- config.strict_update(config_lib.Config.parse(
- 'model=c(stuff=2),data=c(task=2,a=c(x=-1,z=8))'))
- self.assertEqual(
- config_lib.Config(
- data=config_lib.Config(
- task=2,
- a=config_lib.Config(x=-1, y=1000, z=8)),
- model=config_lib.Config(stuff=2)),
- config)
-
- config = make_config()
- config.update(config_lib.Config.parse('model=c(stuff=2)'))
- self.assertEqual(
- config_lib.Config(
- data=config_lib.Config(
- task=2,
- a=config_lib.Config(x=1, y=2)),
- model=config_lib.Config(stuff=2)),
- config)
-
- config = make_config()
- config.strict_update(config_lib.Config.parse('model=c(stuff=2)'))
- self.assertEqual(
- config_lib.Config(
- data=config_lib.Config(
- task=2,
- a=config_lib.Config(x=1, y=2)),
- model=config_lib.Config(stuff=2)),
- config)
-
- def testOneOfStrictErrors(self):
- def make_config():
- return config_lib.Config(
- data=config_lib.OneOf(
- [config_lib.Config(task=1, a='hello'),
- config_lib.Config(task=2, a='world', b='stuff'),
- config_lib.Config(task=3, c=1234)],
- task=2),
- model=config_lib.Config(stuff=1))
-
- config = make_config()
- with self.assertRaises(TypeError):
- config.strict_update(config_lib.Config.parse(
- 'model=c(stuff=2),data=[1,2,3]'))
-
- config = make_config()
- with self.assertRaises(KeyError):
- config.strict_update(config_lib.Config.parse(
- 'model=c(stuff=2),data=c(task=3,c=5678,d=9999)'))
-
- config = make_config()
- with self.assertRaises(ValueError):
- config.strict_update(config_lib.Config.parse(
- 'model=c(stuff=2),data=c(task=4,d=9999)'))
-
- config = make_config()
- with self.assertRaises(TypeError):
- config.strict_update(config_lib.Config.parse(
- 'model=c(stuff=2),data=5'))
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/brain_coder/common/reward.py b/research/brain_coder/common/reward.py
deleted file mode 100644
index 87e01c9c52e1ee22f2745dce12bc5e2726711ff7..0000000000000000000000000000000000000000
--- a/research/brain_coder/common/reward.py
+++ /dev/null
@@ -1,390 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Reward functions, distance functions, and reward managers."""
-
-from abc import ABCMeta
-from abc import abstractmethod
-from math import log
-
-
-# All sequences here are assumed to be lists of ints bounded
-# between 0 and `base`-1 (inclusive).
-
-
-#################################
-### Scalar Distance Functions ###
-#################################
-
-
-def abs_diff(a, b, base=0):
- """Absolute value of difference between scalars.
-
- abs_diff is symmetric, i.e. `a` and `b` are interchangeable.
-
- Args:
- a: First argument. An int.
- b: Seconds argument. An int.
- base: Dummy argument so that the argument signature matches other scalar
- diff functions. abs_diff is the same in all bases.
-
- Returns:
- abs(a - b).
- """
- del base # Unused.
- return abs(a - b)
-
-
-def mod_abs_diff(a, b, base):
- """Shortest distance between `a` and `b` in the modular integers base `base`.
-
- The smallest distance between a and b is returned.
- Example: mod_abs_diff(1, 99, 100) ==> 2. It is not 98.
-
- mod_abs_diff is symmetric, i.e. `a` and `b` are interchangeable.
-
- Args:
- a: First argument. An int.
- b: Seconds argument. An int.
- base: The modulo base. A positive int.
-
- Returns:
- Shortest distance.
- """
- diff = abs(a - b)
- if diff >= base:
- diff %= base
- return min(diff, (-diff) + base)
-
-
-###############################
-### List Distance Functions ###
-###############################
-
-
-def absolute_distance(pred, target, base, scalar_diff_fn=abs_diff):
- """Asymmetric list distance function.
-
- List distance is the sum of element-wise distances, like Hamming distance, but
- where `pred` can be longer or shorter than `target`. For each position in both
- `pred` and `target`, distance between those elements is computed with
- `scalar_diff_fn`. For missing or extra elements in `pred`, the maximum
- distance is assigned, which is equal to `base`.
-
- Distance is 0 when `pred` and `target` are identical, and will be a positive
- integer when they are not.
-
- Args:
- pred: Prediction list. Distance from this list is computed.
- target: Target list. Distance to this list is computed.
- base: The integer base to use. For example, a list of chars would use base
- 256.
- scalar_diff_fn: Element-wise distance function.
-
- Returns:
- List distance between `pred` and `target`.
- """
- d = 0
- for i, target_t in enumerate(target):
- if i >= len(pred):
- d += base # A missing slot is worth the max distance.
- else:
- # Add element-wise distance for this slot.
- d += scalar_diff_fn(pred[i], target_t, base)
- if len(pred) > len(target):
- # Each extra slot is worth the max distance.
- d += (len(pred) - len(target)) * base
- return d
-
-
-def log_absolute_distance(pred, target, base):
- """Asymmetric list distance function that uses log distance.
-
- A list distance which computes sum of element-wise distances, similar to
- `absolute_distance`. Unlike `absolute_distance`, this scales the resulting
- distance to be a float.
-
- Element-wise distance are log-scale. Distance between two list changes
- relatively less for elements that are far apart, but changes a lot (goes to 0
- faster) when values get close together.
-
- Args:
- pred: List of ints. Computes distance from this list to the target.
- target: List of ints. This is the "correct" list which the prediction list
- is trying to match.
- base: Integer base.
-
- Returns:
- Float distance normalized so that when `pred` is at most as long as `target`
- the distance is between 0.0 and 1.0. Distance grows unboundedly large
- as `pred` grows past `target` in length.
- """
- if not target:
- length_normalizer = 1.0
- if not pred:
- # Distance between [] and [] is 0.0 since they are equal.
- return 0.0
- else:
- length_normalizer = float(len(target))
- # max_dist is the maximum element-wise distance, before taking log and
- # scaling. Since we use `mod_abs_diff`, it would be (base // 2), but we add
- # 1 to it so that missing or extra positions get the maximum penalty.
- max_dist = base // 2 + 1
-
- # The log-distance will be scaled by a factor.
- # Note: +1 is added to the numerator and denominator to avoid log(0). This
- # only has a translational effect, i.e. log(dist + 1) / log(max_dist + 1).
- factor = log(max_dist + 1)
-
- d = 0.0 # Total distance to be computed.
- for i, target_t in enumerate(target):
- if i >= len(pred):
- # Assign the max element-wise distance for missing positions. This is 1.0
- # after scaling.
- d += 1.0
- else:
- # Add the log-dist divided by a scaling factor.
- d += log(mod_abs_diff(pred[i], target_t, base) + 1) / factor
- if len(pred) > len(target):
- # Add the max element-wise distance for each extra position.
- # Since max dist after scaling is 1, this is just the difference in list
- # lengths.
- d += (len(pred) - len(target))
- return d / length_normalizer # Normalize again by the target length.
-
-
-########################
-### Reward Functions ###
-########################
-
-# Reward functions assign reward based on program output.
-# Warning: only use these functions as the terminal rewards in episodes, i.e.
-# for the "final" programs.
-
-
-def absolute_distance_reward(pred, target, base, scalar_diff_fn=abs_diff):
- """Reward function based on absolute_distance function.
-
- Maximum reward, 1.0, is given when the lists are equal. Reward is scaled
- so that 0.0 reward is given when `pred` is the empty list (assuming `target`
- is not empty). Reward can go negative when `pred` is longer than `target`.
-
- This is an asymmetric reward function, so which list is the prediction and
- which is the target matters.
-
- Args:
- pred: Prediction sequence. This should be the sequence outputted by the
- generated code. List of ints n, where 0 <= n < base.
- target: Target sequence. The correct sequence that the generated code needs
- to output. List of ints n, where 0 <= n < base.
- base: Base of the computation.
- scalar_diff_fn: Element-wise distance function.
-
- Returns:
- Reward computed based on `pred` and `target`. A float.
- """
- unit_dist = float(base * len(target))
- if unit_dist == 0:
- unit_dist = base
- dist = absolute_distance(pred, target, base, scalar_diff_fn=scalar_diff_fn)
- return (unit_dist - dist) / unit_dist
-
-
-def absolute_mod_distance_reward(pred, target, base):
- """Same as `absolute_distance_reward` but `mod_abs_diff` scalar diff is used.
-
- Args:
- pred: Prediction sequence. This should be the sequence outputted by the
- generated code. List of ints n, where 0 <= n < base.
- target: Target sequence. The correct sequence that the generated code needs
- to output. List of ints n, where 0 <= n < base.
- base: Base of the computation.
-
- Returns:
- Reward computed based on `pred` and `target`. A float.
- """
- return absolute_distance_reward(pred, target, base, mod_abs_diff)
-
-
-def absolute_log_distance_reward(pred, target, base):
- """Compute reward using `log_absolute_distance`.
-
- Maximum reward, 1.0, is given when the lists are equal. Reward is scaled
- so that 0.0 reward is given when `pred` is the empty list (assuming `target`
- is not empty). Reward can go negative when `pred` is longer than `target`.
-
- This is an asymmetric reward function, so which list is the prediction and
- which is the target matters.
-
- This reward function has the nice property that much more reward is given
- for getting the correct value (at each position) than for there being any
- value at all. For example, in base 100, lets say pred = [1] * 1000
- and target = [10] * 1000. A lot of reward would be given for being 80%
- accurate (worst element-wise distance is 50, distances here are 9) using
- `absolute_distance`. `log_absolute_distance` on the other hand will give
- greater and greater reward increments the closer each predicted value gets to
- the target. That makes the reward given for accuracy somewhat independant of
- the base.
-
- Args:
- pred: Prediction sequence. This should be the sequence outputted by the
- generated code. List of ints n, where 0 <= n < base.
- target: Target sequence. The correct sequence that the generated code needs
- to output. List of ints n, where 0 <= n < base.
- base: Base of the computation.
-
- Returns:
- Reward computed based on `pred` and `target`. A float.
- """
- return 1.0 - log_absolute_distance(pred, target, base)
-
-
-#######################
-### Reward Managers ###
-#######################
-
-# Reward managers assign reward to many code attempts throughout an episode.
-
-
-class RewardManager(object):
- """Reward managers administer reward across an episode.
-
- Reward managers are used for "editor" environments. These are environments
- where the agent has some way to edit its code over time, and run its code
- many time in the same episode, so that it can make incremental improvements.
-
- Reward managers are instantiated with a target sequence, which is the known
- correct program output. The manager is called on the output from a proposed
- code, and returns reward. If many proposal outputs are tried, reward may be
- some stateful function that takes previous tries into account. This is done,
- in part, so that an agent cannot accumulate unbounded reward just by trying
- junk programs as often as possible. So reward managers should not give the
- same reward twice if the next proposal is not better than the last.
- """
- __metaclass__ = ABCMeta
-
- def __init__(self, target, base, distance_fn=absolute_distance):
- self._target = list(target)
- self._base = base
- self._distance_fn = distance_fn
-
- @abstractmethod
- def __call__(self, sequence):
- """Call this reward manager like a function to get reward.
-
- Calls to reward manager are stateful, and will take previous sequences
- into account. Repeated calls with the same sequence may produce different
- rewards.
-
- Args:
- sequence: List of integers (each between 0 and base - 1). This is the
- proposal sequence. Reward will be computed based on the distance
- from this sequence to the target (distance function and target are
- given in the constructor), as well as previous sequences tried during
- the lifetime of this object.
-
- Returns:
- Float value. The reward received from this call.
- """
- return 0.0
-
-
-class DeltaRewardManager(RewardManager):
- """Simple reward manager that assigns reward for the net change in distance.
-
- Given some (possibly asymmetric) list distance function, gives reward for
- relative changes in prediction distance to the target.
-
- For example, if on the first call the distance is 3.0, the change in distance
- is -3 (from starting distance of 0). That relative change will be scaled to
- produce a negative reward for this step. On the next call, the distance is 2.0
- which is a +1 change, and that will be scaled to give a positive reward.
- If the final call has distance 0 (the target is achieved), that is another
- positive change of +2. The total reward across all 3 calls is then 0, which is
- the highest posible episode total.
-
- Reward is scaled so that the maximum element-wise distance is worth 1.0.
- Maximum total episode reward attainable is 0.
- """
-
- def __init__(self, target, base, distance_fn=absolute_distance):
- super(DeltaRewardManager, self).__init__(target, base, distance_fn)
- self._last_diff = 0
-
- def _diff(self, seq):
- return self._distance_fn(seq, self._target, self._base)
-
- def _delta_reward(self, seq):
- # Reward is relative to previous sequence diff.
- # Reward is scaled so that maximum token difference is worth 1.0.
- # Reward = (last_diff - this_diff) / self.base.
- # Reward is positive if this sequence is closer to the target than the
- # previous sequence, and negative if this sequence is further away.
- diff = self._diff(seq)
- reward = (self._last_diff - diff) / float(self._base)
- self._last_diff = diff
- return reward
-
- def __call__(self, seq):
- return self._delta_reward(seq)
-
-
-class FloorRewardManager(RewardManager):
- """Assigns positive reward for each step taken closer to the target.
-
- Given some (possibly asymmetric) list distance function, gives reward for
- whenever a new episode minimum distance is reached. No reward is given if
- the distance regresses to a higher value, so that the sum of rewards
- for the episode is positive.
-
- Reward is scaled so that the maximum element-wise distance is worth 1.0.
- Maximum total episode reward attainable is len(target).
-
- If the prediction sequence is longer than the target, a reward of -1 is given.
- Subsequence predictions which are also longer get 0 reward. The -1 penalty
- will be canceled out with a +1 reward when a prediction is given which is at
- most the length of the target.
- """
-
- def __init__(self, target, base, distance_fn=absolute_distance):
- super(FloorRewardManager, self).__init__(target, base, distance_fn)
- self._last_diff = 0
- self._min_diff = self._max_diff()
- self._too_long_penality_given = False
-
- def _max_diff(self):
- return self._distance_fn([], self._target, self._base)
-
- def _diff(self, seq):
- return self._distance_fn(seq, self._target, self._base)
-
- def _delta_reward(self, seq):
- # Reward is only given if this sequence is closer to the target than any
- # previous sequence.
- # Reward is scaled so that maximum token difference is worth 1.0
- # Reward = (min_diff - this_diff) / self.base
- # Reward is always positive.
- diff = self._diff(seq)
- if diff < self._min_diff:
- reward = (self._min_diff - diff) / float(self._base)
- self._min_diff = diff
- else:
- reward = 0.0
- return reward
-
- def __call__(self, seq):
- if len(seq) > len(self._target): # Output is too long.
- if not self._too_long_penality_given:
- self._too_long_penality_given = True
- reward = -1.0
- else:
- reward = 0.0 # Don't give this penalty more than once.
- return reward
-
- reward = self._delta_reward(seq)
- if self._too_long_penality_given:
- reward += 1.0 # Return the subtracted reward.
- self._too_long_penality_given = False
- return reward
-
diff --git a/research/brain_coder/common/reward_test.py b/research/brain_coder/common/reward_test.py
deleted file mode 100644
index 38a1d4ace38cbc945362e52adb90cc9dd62f1be7..0000000000000000000000000000000000000000
--- a/research/brain_coder/common/reward_test.py
+++ /dev/null
@@ -1,311 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Tests for common.reward."""
-
-from math import log
-import numpy as np
-import tensorflow as tf
-
-from common import reward # brain coder
-
-
-class RewardTest(tf.test.TestCase):
-
- def testAbsDiff(self):
- self.assertEqual(5, reward.abs_diff(15, 20))
- self.assertEqual(5, reward.abs_diff(20, 15))
-
- def testModAbsDiff(self):
- self.assertEqual(5, reward.mod_abs_diff(15, 20, 25))
- self.assertEqual(5, reward.mod_abs_diff(20, 15, 25))
- self.assertEqual(2, reward.mod_abs_diff(1, 24, 25))
- self.assertEqual(2, reward.mod_abs_diff(24, 1, 25))
-
- self.assertEqual(0, reward.mod_abs_diff(0, 0, 5))
- self.assertEqual(1, reward.mod_abs_diff(0, 1, 5))
- self.assertEqual(2, reward.mod_abs_diff(0, 2, 5))
- self.assertEqual(2, reward.mod_abs_diff(0, 3, 5))
- self.assertEqual(1, reward.mod_abs_diff(0, 4, 5))
-
- self.assertEqual(0, reward.mod_abs_diff(-1, 4, 5))
- self.assertEqual(1, reward.mod_abs_diff(-5, 4, 5))
- self.assertEqual(1, reward.mod_abs_diff(-7, 4, 5))
- self.assertEqual(1, reward.mod_abs_diff(13, 4, 5))
- self.assertEqual(1, reward.mod_abs_diff(15, 4, 5))
-
- def testAbsoluteDistance_AbsDiffMethod(self):
- self.assertEqual(
- 4,
- reward.absolute_distance([0], [4], 5, scalar_diff_fn=reward.abs_diff))
- self.assertEqual(
- 0,
- reward.absolute_distance([4], [4], 5, scalar_diff_fn=reward.abs_diff))
- self.assertEqual(
- 0,
- reward.absolute_distance([], [], 5, scalar_diff_fn=reward.abs_diff))
- self.assertEqual(
- 5,
- reward.absolute_distance([1], [], 5, scalar_diff_fn=reward.abs_diff))
- self.assertEqual(
- 5,
- reward.absolute_distance([], [1], 5, scalar_diff_fn=reward.abs_diff))
- self.assertEqual(
- 0,
- reward.absolute_distance([1, 2, 3], [1, 2, 3], 5,
- scalar_diff_fn=reward.abs_diff))
- self.assertEqual(
- 1,
- reward.absolute_distance([1, 2, 4], [1, 2, 3], 5,
- scalar_diff_fn=reward.abs_diff))
- self.assertEqual(
- 1,
- reward.absolute_distance([1, 2, 2], [1, 2, 3], 5,
- scalar_diff_fn=reward.abs_diff))
- self.assertEqual(
- 5,
- reward.absolute_distance([1, 2], [1, 2, 3], 5,
- scalar_diff_fn=reward.abs_diff))
- self.assertEqual(
- 5,
- reward.absolute_distance([1, 2, 3, 4], [1, 2, 3], 5,
- scalar_diff_fn=reward.abs_diff))
- self.assertEqual(
- 6,
- reward.absolute_distance([4, 4, 4], [1, 2, 3], 5,
- scalar_diff_fn=reward.abs_diff))
-
- def testAbsoluteDistance_ModDiffMethod(self):
- self.assertEqual(
- 1,
- reward.absolute_distance([0], [4], 5,
- scalar_diff_fn=reward.mod_abs_diff))
- self.assertEqual(
- 0,
- reward.absolute_distance([4], [4], 5,
- scalar_diff_fn=reward.mod_abs_diff))
- self.assertEqual(
- 0,
- reward.absolute_distance([], [], 5,
- scalar_diff_fn=reward.mod_abs_diff))
- self.assertEqual(
- 5,
- reward.absolute_distance([1], [], 5,
- scalar_diff_fn=reward.mod_abs_diff))
- self.assertEqual(
- 5,
- reward.absolute_distance([], [1], 5,
- scalar_diff_fn=reward.mod_abs_diff))
- self.assertEqual(
- 0,
- reward.absolute_distance([1, 2, 3], [1, 2, 3], 5,
- scalar_diff_fn=reward.mod_abs_diff))
- self.assertEqual(
- 1,
- reward.absolute_distance([1, 2, 4], [1, 2, 3], 5,
- scalar_diff_fn=reward.mod_abs_diff))
- self.assertEqual(
- 1,
- reward.absolute_distance([1, 2, 2], [1, 2, 3], 5,
- scalar_diff_fn=reward.mod_abs_diff))
- self.assertEqual(
- 5,
- reward.absolute_distance([1, 2], [1, 2, 3], 5,
- scalar_diff_fn=reward.mod_abs_diff))
- self.assertEqual(
- 5,
- reward.absolute_distance([1, 2, 3, 4], [1, 2, 3], 5,
- scalar_diff_fn=reward.mod_abs_diff))
- self.assertEqual(
- 5,
- reward.absolute_distance([4, 4, 4], [1, 2, 3], 5,
- scalar_diff_fn=reward.mod_abs_diff))
-
- def testLogAbsoluteDistance(self):
- def log_diff(diff, base):
- return log(diff + 1) / log(base // 2 + 2)
-
- self.assertEqual(
- log_diff(1, 5),
- reward.log_absolute_distance([0], [4], 5))
- self.assertEqual(
- log_diff(2, 5),
- reward.log_absolute_distance([1], [4], 5))
- self.assertEqual(
- log_diff(2, 5),
- reward.log_absolute_distance([2], [4], 5))
- self.assertEqual(
- log_diff(1, 5),
- reward.log_absolute_distance([3], [4], 5))
- self.assertEqual(
- log_diff(3, 5), # max_dist = base // 2 + 1 = 3
- reward.log_absolute_distance([], [4], 5))
- self.assertEqual(
- 0 + log_diff(3, 5), # max_dist = base // 2 + 1 = 3
- reward.log_absolute_distance([4, 4], [4], 5))
- self.assertEqual(
- 0,
- reward.log_absolute_distance([4], [4], 5))
- self.assertEqual(
- 0,
- reward.log_absolute_distance([], [], 5))
- self.assertEqual(
- 1,
- reward.log_absolute_distance([1], [], 5))
- self.assertEqual(
- 1,
- reward.log_absolute_distance([], [1], 5))
-
- self.assertEqual(
- 0,
- reward.log_absolute_distance([1, 2, 3], [1, 2, 3], 5))
- self.assertEqual(
- log_diff(1, 5) / 3, # divided by target length.
- reward.log_absolute_distance([1, 2, 4], [1, 2, 3], 5))
- self.assertEqual(
- log_diff(1, 5) / 3,
- reward.log_absolute_distance([1, 2, 2], [1, 2, 3], 5))
- self.assertEqual(
- log_diff(3, 5) / 3, # max_dist
- reward.log_absolute_distance([1, 2], [1, 2, 3], 5))
- self.assertEqual(
- log_diff(3, 5) / 3, # max_dist
- reward.log_absolute_distance([1, 2, 3, 4], [1, 2, 3], 5))
- # Add log differences for each position.
- self.assertEqual(
- (log_diff(2, 5) + log_diff(2, 5) + log_diff(1, 5)) / 3,
- reward.log_absolute_distance([4, 4, 4], [1, 2, 3], 5))
-
- def testAbsoluteDistanceReward(self):
- self.assertEqual(
- 1,
- reward.absolute_distance_reward([1, 2, 3], [1, 2, 3], 5))
- self.assertEqual(
- 1 - 1 / (5 * 3.), # 1 - distance / (base * target_len)
- reward.absolute_distance_reward([1, 2, 4], [1, 2, 3], 5))
- self.assertEqual(
- 1 - 1 / (5 * 3.),
- reward.absolute_distance_reward([1, 2, 2], [1, 2, 3], 5))
- self.assertTrue(np.isclose(
- 1 - 5 / (5 * 3.),
- reward.absolute_distance_reward([1, 2], [1, 2, 3], 5)))
- self.assertTrue(np.isclose(
- 1 - 5 / (5 * 3.),
- reward.absolute_distance_reward([1, 2, 3, 4], [1, 2, 3], 5)))
- # Add log differences for each position.
- self.assertEqual(
- 1 - (3 + 2 + 1) / (5 * 3.),
- reward.absolute_distance_reward([4, 4, 4], [1, 2, 3], 5))
- self.assertEqual(
- 1,
- reward.absolute_distance_reward([], [], 5))
-
- def testAbsoluteModDistanceReward(self):
- self.assertEqual(
- 1,
- reward.absolute_mod_distance_reward([1, 2, 3], [1, 2, 3], 5))
- self.assertEqual(
- 1 - 1 / (5 * 3.), # 1 - distance / (base * target_len)
- reward.absolute_mod_distance_reward([1, 2, 4], [1, 2, 3], 5))
- self.assertEqual(
- 1 - 1 / (5 * 3.),
- reward.absolute_mod_distance_reward([1, 2, 2], [1, 2, 3], 5))
- self.assertTrue(np.isclose(
- 1 - 5 / (5 * 3.),
- reward.absolute_mod_distance_reward([1, 2], [1, 2, 3], 5)))
- self.assertTrue(np.isclose(
- 1 - 5 / (5 * 3.),
- reward.absolute_mod_distance_reward([1, 2, 3, 4], [1, 2, 3], 5)))
- # Add log differences for each position.
- self.assertTrue(np.isclose(
- 1 - (2 + 2 + 1) / (5 * 3.),
- reward.absolute_mod_distance_reward([4, 4, 4], [1, 2, 3], 5)))
- self.assertTrue(np.isclose(
- 1 - (1 + 2 + 2) / (5 * 3.),
- reward.absolute_mod_distance_reward([0, 1, 2], [4, 4, 4], 5)))
- self.assertEqual(
- 1,
- reward.absolute_mod_distance_reward([], [], 5))
-
- def testAbsoluteLogDistanceReward(self):
- def log_diff(diff, base):
- return log(diff + 1) / log(base // 2 + 2)
-
- self.assertEqual(
- 1,
- reward.absolute_log_distance_reward([1, 2, 3], [1, 2, 3], 5))
- self.assertEqual(
- 1 - log_diff(1, 5) / 3, # divided by target length.
- reward.absolute_log_distance_reward([1, 2, 4], [1, 2, 3], 5))
- self.assertEqual(
- 1 - log_diff(1, 5) / 3,
- reward.absolute_log_distance_reward([1, 2, 2], [1, 2, 3], 5))
- self.assertEqual(
- 1 - log_diff(3, 5) / 3, # max_dist
- reward.absolute_log_distance_reward([1, 2], [1, 2, 3], 5))
- self.assertEqual(
- 1 - log_diff(3, 5) / 3, # max_dist
- reward.absolute_log_distance_reward([1, 2, 3, 4], [1, 2, 3], 5))
- # Add log differences for each position.
- self.assertEqual(
- 1 - (log_diff(2, 5) + log_diff(2, 5) + log_diff(1, 5)) / 3,
- reward.absolute_log_distance_reward([4, 4, 4], [1, 2, 3], 5))
- self.assertEqual(
- 1 - (log_diff(1, 5) + log_diff(2, 5) + log_diff(2, 5)) / 3,
- reward.absolute_log_distance_reward([0, 1, 2], [4, 4, 4], 5))
- self.assertEqual(
- 1,
- reward.absolute_log_distance_reward([], [], 5))
-
- def testDeltaRewardManager(self):
- reward_manager = reward.DeltaRewardManager(
- [1, 2, 3, 4], base=5, distance_fn=reward.absolute_distance)
- self.assertEqual(-3, reward_manager([1]))
- self.assertEqual(0, reward_manager([1]))
- self.assertEqual(4 / 5., reward_manager([1, 3]))
- self.assertEqual(-4 / 5, reward_manager([1]))
- self.assertEqual(3, reward_manager([1, 2, 3, 4]))
- self.assertEqual(-1, reward_manager([1, 2, 3]))
- self.assertEqual(0, reward_manager([1, 2, 3, 4, 3]))
- self.assertEqual(-1, reward_manager([1, 2, 3, 4, 3, 2]))
- self.assertEqual(2, reward_manager([1, 2, 3, 4]))
- self.assertEqual(0, reward_manager([1, 2, 3, 4]))
- self.assertEqual(0, reward_manager([1, 2, 3, 4]))
-
- def testFloorRewardMananger(self):
- reward_manager = reward.FloorRewardManager(
- [1, 2, 3, 4], base=5, distance_fn=reward.absolute_distance)
- self.assertEqual(1, reward_manager([1]))
- self.assertEqual(0, reward_manager([1]))
- self.assertEqual(4 / 5., reward_manager([1, 3]))
- self.assertEqual(0, reward_manager([1]))
- self.assertEqual(1 / 5., reward_manager([1, 2]))
- self.assertEqual(0, reward_manager([0, 1]))
- self.assertEqual(0, reward_manager([]))
- self.assertEqual(0, reward_manager([1, 2]))
- self.assertEqual(2, reward_manager([1, 2, 3, 4]))
- self.assertEqual(0, reward_manager([1, 2, 3]))
- self.assertEqual(-1, reward_manager([1, 2, 3, 4, 3]))
- self.assertEqual(0, reward_manager([1, 2, 3, 4, 3, 2]))
- self.assertEqual(1, reward_manager([1, 2, 3, 4]))
- self.assertEqual(0, reward_manager([1, 2, 3, 4]))
- self.assertEqual(0, reward_manager([1, 2, 3, 4]))
-
- reward_manager = reward.FloorRewardManager(
- [1, 2, 3, 4], base=5, distance_fn=reward.absolute_distance)
- self.assertEqual(1, reward_manager([1]))
- self.assertEqual(-1, reward_manager([1, 0, 0, 0, 0, 0]))
- self.assertEqual(0, reward_manager([1, 2, 3, 4, 0, 0]))
- self.assertEqual(0, reward_manager([1, 2, 3, 4, 0]))
- self.assertEqual(1, reward_manager([]))
- self.assertEqual(0, reward_manager([]))
- self.assertEqual(0, reward_manager([1]))
- self.assertEqual(1, reward_manager([1, 2]))
- self.assertEqual(-1, reward_manager([1, 2, 3, 4, 0, 0]))
- self.assertEqual(0, reward_manager([1, 1, 1, 1, 1]))
- self.assertEqual(1 + 2, reward_manager([1, 2, 3, 4]))
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/brain_coder/common/rollout.py b/research/brain_coder/common/rollout.py
deleted file mode 100644
index e377aa662db640dfa907de83d32875cc096c4295..0000000000000000000000000000000000000000
--- a/research/brain_coder/common/rollout.py
+++ /dev/null
@@ -1,306 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Utilities related to computing training batches from episode rollouts.
-
-Implementations here are based on code from Open AI:
-https://github.com/openai/universe-starter-agent/blob/master/a3c.py.
-"""
-
-from collections import namedtuple
-import numpy as np
-import scipy.signal
-
-from common import utils # brain coder
-
-
-class Rollout(object):
- """Holds a rollout for an episode.
-
- A rollout is a record of the states observed in some environment and actions
- taken by the agent to arrive at those states. Other information includes
- rewards received after each action, values estimated for each state, whether
- the rollout concluded the episide, and total reward received. Everything
- should be given in time order.
-
- At each time t, the agent sees state s_t, takes action a_t, and then receives
- reward r_t. The agent may optionally estimate a state value V(s_t) for each
- state.
-
- For an episode of length T:
- states = [s_0, ..., s_(T-1)]
- actions = [a_0, ..., a_(T-1)]
- rewards = [r_0, ..., r_(T-1)]
- values = [V(s_0), ..., V(s_(T-1))]
-
- Note that there is an extra state s_T observed after taking action a_(T-1),
- but this is not included in the rollout.
-
- Rollouts have an `terminated` attribute which is True when the rollout is
- "finalized", i.e. it holds a full episode. terminated will be False when
- time steps are still being added to it.
- """
-
- def __init__(self):
- self.states = []
- self.actions = []
- self.rewards = []
- self.values = []
- self.total_reward = 0.0
- self.terminated = False
-
- def add(self, state, action, reward, value=0.0, terminated=False):
- """Add the next timestep to this rollout.
-
- Args:
- state: The state observed at the start of this timestep.
- action: The action taken after observing the given state.
- reward: The reward received for taking the given action.
- value: The value estimated for the given state.
- terminated: Whether this timestep ends the episode.
-
- Raises:
- ValueError: If this.terminated is already True, meaning that the episode
- has already ended.
- """
- if self.terminated:
- raise ValueError(
- 'Trying to add timestep to an already terminal rollout.')
- self.states += [state]
- self.actions += [action]
- self.rewards += [reward]
- self.values += [value]
- self.terminated = terminated
- self.total_reward += reward
-
- def add_many(self, states, actions, rewards, values=None, terminated=False):
- """Add many timesteps to this rollout.
-
- Arguments are the same as `add`, but are lists of equal size.
-
- Args:
- states: The states observed.
- actions: The actions taken.
- rewards: The rewards received.
- values: The values estimated for the given states.
- terminated: Whether this sequence ends the episode.
-
- Raises:
- ValueError: If the lengths of all the input lists are not equal.
- ValueError: If this.terminated is already True, meaning that the episode
- has already ended.
- """
- if len(states) != len(actions):
- raise ValueError(
- 'Number of states and actions must be the same. Got %d states and '
- '%d actions' % (len(states), len(actions)))
- if len(states) != len(rewards):
- raise ValueError(
- 'Number of states and rewards must be the same. Got %d states and '
- '%d rewards' % (len(states), len(rewards)))
- if values is not None and len(states) != len(values):
- raise ValueError(
- 'Number of states and values must be the same. Got %d states and '
- '%d values' % (len(states), len(values)))
- if self.terminated:
- raise ValueError(
- 'Trying to add timesteps to an already terminal rollout.')
- self.states += states
- self.actions += actions
- self.rewards += rewards
- self.values += values if values is not None else [0.0] * len(states)
- self.terminated = terminated
- self.total_reward += sum(rewards)
-
- def extend(self, other):
- """Append another rollout to this rollout."""
- assert not self.terminated
- self.states.extend(other.states)
- self.actions.extend(other.actions)
- self.rewards.extend(other.rewards)
- self.values.extend(other.values)
- self.terminated = other.terminated
- self.total_reward += other.total_reward
-
-
-def discount(x, gamma):
- """Returns discounted sums for each value in x, with discount factor gamma.
-
- This can be used to compute the return (discounted sum of rewards) at each
- timestep given a sequence of rewards. See the definitions for return and
- REINFORCE in section 3 of https://arxiv.org/pdf/1602.01783.pdf.
-
- Let g^k mean gamma ** k.
- For list [x_0, ..., x_N], the following list of discounted sums is computed:
- [x_0 + g^1 * x_1 + g^2 * x_2 + ... g^N * x_N,
- x_1 + g^1 * x_2 + g^2 * x_3 + ... g^(N-1) * x_N,
- x_2 + g^1 * x_3 + g^2 * x_4 + ... g^(N-2) * x_N,
- ...,
- x_(N-1) + g^1 * x_N,
- x_N]
-
- Args:
- x: List of numbers [x_0, ..., x_N].
- gamma: Float between 0 and 1 (inclusive). This is the discount factor.
-
- Returns:
- List of discounted sums.
- """
- return scipy.signal.lfilter([1], [1, -gamma], x[::-1], axis=0)[::-1]
-
-
-def discounted_advantage_and_rewards(rewards, values, gamma, lambda_=1.0):
- """Compute advantages and returns (discounted sum of rewards).
-
- For an episode of length T, rewards = [r_0, ..., r_(T-1)].
- Each reward r_t is observed after taking action a_t at state s_t. A final
- state s_T is observed but no reward is given at this state since no action
- a_T is taken (otherwise there would be a new state s_(T+1)).
-
- `rewards` and `values` are for a single episode. Return R_t is the discounted
- sum of future rewards starting at time t, where `gamma` is the discount
- factor.
- R_t = r_t + gamma * r_(t+1) + gamma**2 * r_(t+2) + ...
- + gamma**(T-1-t) * r_(T-1)
-
- Advantage A(a_t, s_t) is approximated by computing A(a_t, s_t) = R_t - V(s_t)
- where V(s_t) is an approximation of the value at that state, given in the
- `values` list. Returns R_t are needed for all REINFORCE algorithms. Advantage
- is used for the advantage actor critic variant of REINFORCE.
- See algorithm S3 in https://arxiv.org/pdf/1602.01783.pdf.
-
- Additionally another parameter `lambda_` controls the bias-variance tradeoff.
- See "Generalized Advantage Estimation": https://arxiv.org/abs/1506.02438.
- lambda_ = 1 reduces to regular advantage.
- 0 <= lambda_ < 1 trades off variance for bias, with lambda_ = 0 being the
- most biased.
-
- Bootstrapping is also supported. If an episode does not end in a terminal
- state (either because the episode was ended early, or the environment does not
- have end states), the true return cannot be computed from the rewards alone.
- However, it can be estimated by computing the value (an approximation of
- return) of the last state s_T. Thus the `values` list will have an extra item:
- values = [V(s_0), ..., V(s_(T-1)), V(s_T)].
-
- Args:
- rewards: List of observed rewards [r_0, ..., r_(T-1)].
- values: List of estimated values [V(s_0), ..., V(s_(T-1))] with an optional
- extra V(s_T) item.
- gamma: Discount factor. Number between 0 and 1. 1 means no discount.
- If not 1, gamma is typically near 1, like 0.99.
- lambda_: Bias-variance tradeoff factor. Between 0 and 1.
-
- Returns:
- empirical_values: Returns at each timestep.
- generalized_advantage: Avantages at each timestep.
-
- Raises:
- ValueError: If shapes of `rewards` and `values` are not rank 1.
- ValueError: If len(values) not in (len(rewards), len(rewards) + 1).
- """
- rewards = np.asarray(rewards, dtype=np.float32)
- values = np.asarray(values, dtype=np.float32)
- if rewards.ndim != 1:
- raise ValueError('Single episode only. rewards must be rank 1.')
- if values.ndim != 1:
- raise ValueError('Single episode only. values must be rank 1.')
- if len(values) == len(rewards):
- # No bootstrapping.
- values = np.append(values, 0)
- empirical_values = discount(rewards, gamma)
- elif len(values) == len(rewards) + 1:
- # With bootstrapping.
- # Last value is for the terminal state (final state after last action was
- # taken).
- empirical_values = discount(np.append(rewards, values[-1]), gamma)[:-1]
- else:
- raise ValueError('values should contain the same number of items or one '
- 'more item than rewards')
- delta = rewards + gamma * values[1:] - values[:-1]
- generalized_advantage = discount(delta, gamma * lambda_)
-
- # empirical_values is the discounted sum of rewards into the future.
- # generalized_advantage is the target for each policy update.
- return empirical_values, generalized_advantage
-
-
-"""Batch holds a minibatch of episodes.
-
-Let bi = batch_index, i.e. the index of each episode in the minibatch.
-Let t = time.
-
-Attributes:
- states: States for each timestep in each episode. Indexed by states[bi, t].
- actions: Actions for each timestep in each episode. Indexed by actions[bi, t].
- discounted_adv: Advantages (computed by discounted_advantage_and_rewards)
- for each timestep in each episode. Indexed by discounted_adv[bi, t].
- discounted_r: Returns (discounted sum of rewards computed by
- discounted_advantage_and_rewards) for each timestep in each episode.
- Indexed by discounted_r[bi, t].
- total_rewards: Total reward for each episode, i.e. sum of rewards across all
- timesteps (not discounted). Indexed by total_rewards[bi].
- episode_lengths: Number of timesteps in each episode. If an episode has
- N actions, N rewards, and N states, then its length is N. Indexed by
- episode_lengths[bi].
- batch_size: Number of episodes in this minibatch. An integer.
- max_time: Maximum episode length in the batch. An integer.
-""" # pylint: disable=pointless-string-statement
-Batch = namedtuple(
- 'Batch',
- ['states', 'actions', 'discounted_adv', 'discounted_r', 'total_rewards',
- 'episode_lengths', 'batch_size', 'max_time'])
-
-
-def process_rollouts(rollouts, gamma, lambda_=1.0):
- """Convert a batch of rollouts into tensors ready to be fed into a model.
-
- Lists from each episode are stacked into 2D tensors and padded with 0s up to
- the maximum timestep in the batch.
-
- Args:
- rollouts: A list of Rollout instances.
- gamma: The discount factor. A number between 0 and 1 (inclusive). See gamma
- argument in discounted_advantage_and_rewards.
- lambda_: See lambda_ argument in discounted_advantage_and_rewards.
-
- Returns:
- Batch instance. states, actions, discounted_adv, and discounted_r are
- numpy arrays with shape (batch_size, max_episode_length). episode_lengths
- is a list of ints. total_rewards is a list of floats (total reward in each
- episode). batch_size and max_time are ints.
-
- Raises:
- ValueError: If any of the rollouts are not terminal.
- """
- for ro in rollouts:
- if not ro.terminated:
- raise ValueError('Can only process terminal rollouts.')
-
- episode_lengths = [len(ro.states) for ro in rollouts]
- batch_size = len(rollouts)
- max_time = max(episode_lengths)
-
- states = utils.stack_pad([ro.states for ro in rollouts], 0, max_time)
- actions = utils.stack_pad([ro.actions for ro in rollouts], 0, max_time)
-
- discounted_rewards = [None] * batch_size
- discounted_adv = [None] * batch_size
- for i, ro in enumerate(rollouts):
- disc_r, disc_adv = discounted_advantage_and_rewards(
- ro.rewards, ro.values, gamma, lambda_)
- discounted_rewards[i] = disc_r
- discounted_adv[i] = disc_adv
- discounted_rewards = utils.stack_pad(discounted_rewards, 0, max_time)
- discounted_adv = utils.stack_pad(discounted_adv, 0, max_time)
-
- total_rewards = [sum(ro.rewards) for ro in rollouts]
-
- return Batch(states=states,
- actions=actions,
- discounted_adv=discounted_adv,
- discounted_r=discounted_rewards,
- total_rewards=total_rewards,
- episode_lengths=episode_lengths,
- batch_size=batch_size,
- max_time=max_time)
diff --git a/research/brain_coder/common/rollout_test.py b/research/brain_coder/common/rollout_test.py
deleted file mode 100644
index 5be4cb0fafd8a2e94004c17b41e189d989a3a851..0000000000000000000000000000000000000000
--- a/research/brain_coder/common/rollout_test.py
+++ /dev/null
@@ -1,129 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Tests for common.rollout."""
-
-import numpy as np
-import tensorflow as tf
-
-from common import rollout as rollout_lib # brain coder
-
-
-class RolloutTest(tf.test.TestCase):
-
- def MakeRollout(self, states, actions, rewards, values=None, terminated=True):
- rollout = rollout_lib.Rollout()
- rollout.add_many(
- states=states, actions=actions, rewards=rewards, values=values,
- terminated=terminated)
- return rollout
-
- def testDiscount(self):
- discounted = np.array([1.0 / 2 ** n for n in range(4, -1, -1)])
- discounted[:2] += [1.0 / 2 ** n for n in range(1, -1, -1)]
-
- self.assertTrue(np.array_equal(
- rollout_lib.discount([0.0, 1.0, 0.0, 0.0, 1.0], 0.50),
- discounted))
- self.assertTrue(np.array_equal(
- rollout_lib.discount(np.array([0.0, 1.0, 0.0, 0.0, 1.0]), 0.50),
- discounted))
-
- def testDiscountedAdvantageAndRewards(self):
- # lambda=1, No bootstrapping.
- values = [0.1, 0.5, 0.5, 0.25]
- (empirical_values,
- generalized_advantage) = rollout_lib.discounted_advantage_and_rewards(
- [0.0, 0.0, 0.0, 1.0],
- values,
- gamma=0.75,
- lambda_=1.0)
- expected_discounted_r = (
- np.array([1.0 * 0.75 ** n for n in range(3, -1, -1)]))
- expected_adv = expected_discounted_r - values
- self.assertTrue(np.array_equal(empirical_values, expected_discounted_r))
- self.assertTrue(np.allclose(generalized_advantage, expected_adv))
-
- # lambda=1, With bootstrapping.
- values = [0.1, 0.5, 0.5, 0.25, 0.75]
- (empirical_values,
- generalized_advantage) = rollout_lib.discounted_advantage_and_rewards(
- [0.0, 0.0, 0.0, 1.0],
- values,
- gamma=0.75,
- lambda_=1.0)
- expected_discounted_r = (
- np.array([0.75 * 0.75 ** n for n in range(4, 0, -1)])
- + np.array([1.0 * 0.75 ** n for n in range(3, -1, -1)]))
- expected_adv = expected_discounted_r - values[:-1]
- self.assertTrue(np.array_equal(empirical_values, expected_discounted_r))
- self.assertTrue(np.allclose(generalized_advantage, expected_adv))
-
- # lambda=0.5, With bootstrapping.
- values = [0.1, 0.5, 0.5, 0.25, 0.75]
- rewards = [0.0, 0.0, 0.0, 1.0]
- l = 0.5 # lambda
- g = 0.75 # gamma
- (empirical_values,
- generalized_advantage) = rollout_lib.discounted_advantage_and_rewards(
- rewards,
- values,
- gamma=g,
- lambda_=l)
- expected_discounted_r = (
- np.array([0.75 * g ** n for n in range(4, 0, -1)])
- + np.array([1.0 * g ** n for n in range(3, -1, -1)]))
- expected_adv = [0.0] * len(values)
- for t in range(3, -1, -1):
- delta_t = rewards[t] + g * values[t + 1] - values[t]
- expected_adv[t] = delta_t + g * l * expected_adv[t + 1]
- expected_adv = expected_adv[:-1]
- self.assertTrue(np.array_equal(empirical_values, expected_discounted_r))
- self.assertTrue(np.allclose(generalized_advantage, expected_adv))
-
- def testProcessRollouts(self):
- g = 0.95
- rollouts = [
- self.MakeRollout(
- states=[3, 6, 9],
- actions=[1, 2, 3],
- rewards=[1.0, -1.0, 0.5],
- values=[0.5, 0.5, 0.1]),
- self.MakeRollout(
- states=[10],
- actions=[5],
- rewards=[1.0],
- values=[0.5])]
- batch = rollout_lib.process_rollouts(rollouts, gamma=g)
-
- self.assertEqual(2, batch.batch_size)
- self.assertEqual(3, batch.max_time)
- self.assertEqual([3, 1], batch.episode_lengths)
- self.assertEqual([0.5, 1.0], batch.total_rewards)
- self.assertEqual(
- [[3, 6, 9], [10, 0, 0]],
- batch.states.tolist())
- self.assertEqual(
- [[1, 2, 3], [5, 0, 0]],
- batch.actions.tolist())
-
- rew1, rew2 = rollouts[0].rewards, rollouts[1].rewards
- expected_discounted_rewards = [
- [rew1[0] + g * rew1[1] + g * g * rew1[2],
- rew1[1] + g * rew1[2],
- rew1[2]],
- [rew2[0], 0.0, 0.0]]
- expected_advantages = [
- [dr - v
- for dr, v
- in zip(expected_discounted_rewards[0], rollouts[0].values)],
- [expected_discounted_rewards[1][0] - rollouts[1].values[0], 0.0, 0.0]]
- self.assertTrue(
- np.allclose(expected_discounted_rewards, batch.discounted_r))
- self.assertTrue(
- np.allclose(expected_advantages, batch.discounted_adv))
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/brain_coder/common/schedules.py b/research/brain_coder/common/schedules.py
deleted file mode 100644
index fff2481e536d65f154ad2d9dc3972657d860abf8..0000000000000000000000000000000000000000
--- a/research/brain_coder/common/schedules.py
+++ /dev/null
@@ -1,301 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Schedule functions for controlling hparams over time."""
-
-from abc import ABCMeta
-from abc import abstractmethod
-import math
-
-from common import config_lib # brain coder
-
-
-class Schedule(object):
- """Schedule is a function which sets a hyperparameter's value over time.
-
- For example, a schedule can be used to decay an hparams, or oscillate it over
- time.
-
- This object is constructed with an instance of config_lib.Config (will be
- specific to each class implementation). For example if this is a decay
- schedule, the config may specify the rate of decay and decay start time. Then
- the object instance is called like a function, mapping global step (an integer
- counting how many calls to the train op have been made) to the hparam value.
-
- Properties of a schedule function f(t):
- 0) Domain of t is the non-negative integers (t may be 0).
- 1) Range of f is the reals.
- 2) Schedule functions can assume that they will be called in time order. This
- allows schedules to be stateful.
- 3) Schedule functions should be deterministic. Two schedule instances with the
- same config must always give the same value for each t, and regardless of
- what t's it was previously called on. Users may call f(t) on arbitrary
- (positive) time jumps. Essentially, multiple schedule instances used in
- replica training will behave the same.
- 4) Duplicate successive calls on the same time are allowed.
- """
- __metaclass__ = ABCMeta
-
- @abstractmethod
- def __init__(self, config):
- """Construct this schedule with a config specific to each class impl.
-
- Args:
- config: An instance of config_lib.Config.
- """
- pass
-
- @abstractmethod
- def __call__(self, global_step):
- """Map `global_step` to a value.
-
- `global_step` is an integer counting how many calls to the train op have
- been made across all replicas (hence why it is global). Implementations
- may assume calls to be made in time order, i.e. `global_step` now >=
- previous `global_step` values.
-
- Args:
- global_step: Non-negative integer.
-
- Returns:
- Hparam value at this step. A number.
- """
- pass
-
-
-class ConstSchedule(Schedule):
- """Constant function.
-
- config:
- const: Constant value at every step.
-
- f(t) = const.
- """
-
- def __init__(self, config):
- super(ConstSchedule, self).__init__(config)
- self.const = config.const
-
- def __call__(self, global_step):
- return self.const
-
-
-class LinearDecaySchedule(Schedule):
- """Linear decay function.
-
- config:
- initial: Decay starts from this value.
- final: Decay ends at this value.
- start_time: Step when decay starts. Constant before it.
- end_time: When decay ends. Constant after it.
-
- f(t) is a linear function when start_time <= t <= end_time, with slope of
- (final - initial) / (end_time - start_time). f(t) = initial
- when t <= start_time. f(t) = final when t >= end_time.
-
- If start_time == end_time, this becomes a step function.
- """
-
- def __init__(self, config):
- super(LinearDecaySchedule, self).__init__(config)
- self.initial = config.initial
- self.final = config.final
- self.start_time = config.start_time
- self.end_time = config.end_time
-
- if self.end_time < self.start_time:
- raise ValueError('start_time must be before end_time.')
-
- # Linear interpolation.
- self._time_diff = float(self.end_time - self.start_time)
- self._diff = float(self.final - self.initial)
- self._slope = (
- self._diff / self._time_diff if self._time_diff > 0 else float('inf'))
-
- def __call__(self, global_step):
- if global_step <= self.start_time:
- return self.initial
- if global_step > self.end_time:
- return self.final
- return self.initial + (global_step - self.start_time) * self._slope
-
-
-class ExponentialDecaySchedule(Schedule):
- """Exponential decay function.
-
- See https://en.wikipedia.org/wiki/Exponential_decay.
-
- Use this decay function to decay over orders of magnitude. For example, to
- decay learning rate from 1e-2 to 1e-6. Exponential decay will decay the
- exponent linearly.
-
- config:
- initial: Decay starts from this value.
- final: Decay ends at this value.
- start_time: Step when decay starts. Constant before it.
- end_time: When decay ends. Constant after it.
-
- f(t) is an exponential decay function when start_time <= t <= end_time. The
- decay rate and amplitude are chosen so that f(t) = initial when
- t = start_time, and f(t) = final when t = end_time. f(t) is constant for
- t < start_time or t > end_time. initial and final must be positive values.
-
- If start_time == end_time, this becomes a step function.
- """
-
- def __init__(self, config):
- super(ExponentialDecaySchedule, self).__init__(config)
- self.initial = config.initial
- self.final = config.final
- self.start_time = config.start_time
- self.end_time = config.end_time
-
- if self.initial <= 0 or self.final <= 0:
- raise ValueError('initial and final must be positive numbers.')
-
- # Linear interpolation in log space.
- self._linear_fn = LinearDecaySchedule(
- config_lib.Config(
- initial=math.log(self.initial),
- final=math.log(self.final),
- start_time=self.start_time,
- end_time=self.end_time))
-
- def __call__(self, global_step):
- return math.exp(self._linear_fn(global_step))
-
-
-class SmootherstepDecaySchedule(Schedule):
- """Smootherstep decay function.
-
- A sigmoidal like transition from initial to final values. A smoother
- transition than linear and exponential decays, hence the name.
- See https://en.wikipedia.org/wiki/Smoothstep.
-
- config:
- initial: Decay starts from this value.
- final: Decay ends at this value.
- start_time: Step when decay starts. Constant before it.
- end_time: When decay ends. Constant after it.
-
- f(t) is fully defined here:
- https://en.wikipedia.org/wiki/Smoothstep#Variations.
-
- f(t) is smooth, as in its first-derivative exists everywhere.
- """
-
- def __init__(self, config):
- super(SmootherstepDecaySchedule, self).__init__(config)
- self.initial = config.initial
- self.final = config.final
- self.start_time = config.start_time
- self.end_time = config.end_time
-
- if self.end_time < self.start_time:
- raise ValueError('start_time must be before end_time.')
-
- self._time_diff = float(self.end_time - self.start_time)
- self._diff = float(self.final - self.initial)
-
- def __call__(self, global_step):
- if global_step <= self.start_time:
- return self.initial
- if global_step > self.end_time:
- return self.final
- x = (global_step - self.start_time) / self._time_diff
-
- # Smootherstep
- return self.initial + x * x * x * (x * (x * 6 - 15) + 10) * self._diff
-
-
-class HardOscillatorSchedule(Schedule):
- """Hard oscillator function.
-
- config:
- high: Max value of the oscillator. Value at constant plateaus.
- low: Min value of the oscillator. Value at constant valleys.
- start_time: Global step when oscillation starts. Constant before this.
- period: Width of one oscillation, i.e. number of steps over which the
- oscillation takes place.
- transition_fraction: Fraction of the period spent transitioning between high
- and low values. 50% of this time is spent rising, and 50% of this time
- is spent falling. 50% of the remaining time is spent constant at the
- high value, and 50% of the remaining time is spent constant at the low
- value. transition_fraction = 1.0 means the entire period is spent
- rising and falling. transition_fraction = 0.0 means no time is spent
- rising and falling, i.e. the function jumps instantaneously between
- high and low.
-
- f(t) = high when t < start_time.
- f(t) is periodic when t >= start_time, with f(t + period) = f(t).
- f(t) is linear with positive slope when rising, and negative slope when
- falling. At the start of the period t0, f(t0) = high and begins to descend.
- At the middle of the period f is low and is constant until the ascension
- begins. f then rises from low to high and is constant again until the period
- repeats.
-
- Note: when transition_fraction is 0, f starts the period low and ends high.
- """
-
- def __init__(self, config):
- super(HardOscillatorSchedule, self).__init__(config)
- self.high = config.high
- self.low = config.low
- self.start_time = config.start_time
- self.period = float(config.period)
- self.transition_fraction = config.transition_fraction
- self.half_transition_fraction = config.transition_fraction / 2.0
-
- if self.transition_fraction < 0 or self.transition_fraction > 1.0:
- raise ValueError('transition_fraction must be between 0 and 1.0')
- if self.period <= 0:
- raise ValueError('period must be positive')
-
- self._slope = (
- float(self.high - self.low) / self.half_transition_fraction
- if self.half_transition_fraction > 0 else float('inf'))
-
- def __call__(self, global_step):
- if global_step < self.start_time:
- return self.high
- period_pos = ((global_step - self.start_time) / self.period) % 1.0
- if period_pos >= 0.5:
- # ascending
- period_pos -= 0.5
- if period_pos < self.half_transition_fraction:
- return self.low + period_pos * self._slope
- else:
- return self.high
- else:
- # descending
- if period_pos < self.half_transition_fraction:
- return self.high - period_pos * self._slope
- else:
- return self.low
-
-
-_NAME_TO_CONFIG = {
- 'const': ConstSchedule,
- 'linear_decay': LinearDecaySchedule,
- 'exp_decay': ExponentialDecaySchedule,
- 'smooth_decay': SmootherstepDecaySchedule,
- 'hard_osc': HardOscillatorSchedule,
-}
-
-
-def make_schedule(config):
- """Schedule factory.
-
- Given `config` containing a `fn` property, a Schedule implementation is
- instantiated with `config`. See `_NAME_TO_CONFIG` for `fn` options.
-
- Args:
- config: Config with a `fn` option that specifies which Schedule
- implementation to use. `config` is passed into the constructor.
-
- Returns:
- A Schedule impl instance.
- """
- schedule_class = _NAME_TO_CONFIG[config.fn]
- return schedule_class(config)
diff --git a/research/brain_coder/common/schedules_test.py b/research/brain_coder/common/schedules_test.py
deleted file mode 100644
index b17022f45a833fb3aa219fd06225f77fbd1b1055..0000000000000000000000000000000000000000
--- a/research/brain_coder/common/schedules_test.py
+++ /dev/null
@@ -1,139 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Tests for common.schedules."""
-
-from math import exp
-from math import sqrt
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-from common import config_lib # brain coder
-from common import schedules # brain coder
-
-
-class SchedulesTest(tf.test.TestCase):
-
- def ScheduleTestHelper(self, config, schedule_subtype, io_values):
- """Run common checks for schedules.
-
- Args:
- config: Config object which is passed into schedules.make_schedule.
- schedule_subtype: The expected schedule type to be instantiated.
- io_values: List of (input, output) pairs. Must be in ascending input
- order. No duplicate inputs.
- """
-
- # Check that make_schedule makes the correct type.
- f = schedules.make_schedule(config)
- self.assertTrue(isinstance(f, schedule_subtype))
-
- # Check that multiple instances returned from make_schedule behave the same.
- fns = [schedules.make_schedule(config) for _ in xrange(3)]
-
- # Check that all the inputs map to the right outputs.
- for i, o in io_values:
- for f in fns:
- f_out = f(i)
- self.assertTrue(
- np.isclose(o, f_out),
- 'Wrong value at input %d. Expected %s, got %s' % (i, o, f_out))
-
- # Check that a subset of the io_values are still correct.
- f = schedules.make_schedule(config)
- subseq = [io_values[i**2] for i in xrange(int(sqrt(len(io_values))))]
- if subseq[-1] != io_values[-1]:
- subseq.append(io_values[-1])
- for i, o in subseq:
- f_out = f(i)
- self.assertTrue(
- np.isclose(o, f_out),
- 'Wrong value at input %d. Expected %s, got %s' % (i, o, f_out))
-
- # Check duplicate calls.
- f = schedules.make_schedule(config)
- for i, o in io_values:
- for _ in xrange(3):
- f_out = f(i)
- self.assertTrue(
- np.isclose(o, f_out),
- 'Duplicate calls at input %d are not equal. Expected %s, got %s'
- % (i, o, f_out))
-
- def testConstSchedule(self):
- self.ScheduleTestHelper(
- config_lib.Config(fn='const', const=5),
- schedules.ConstSchedule,
- [(0, 5), (1, 5), (10, 5), (20, 5), (100, 5), (1000000, 5)])
-
- def testLinearDecaySchedule(self):
- self.ScheduleTestHelper(
- config_lib.Config(fn='linear_decay', initial=2, final=0, start_time=10,
- end_time=20),
- schedules.LinearDecaySchedule,
- [(0, 2), (1, 2), (10, 2), (11, 1.8), (15, 1), (19, 0.2), (20, 0),
- (100000, 0)])
-
- # Test step function.
- self.ScheduleTestHelper(
- config_lib.Config(fn='linear_decay', initial=2, final=0, start_time=10,
- end_time=10),
- schedules.LinearDecaySchedule,
- [(0, 2), (1, 2), (10, 2), (11, 0), (15, 0)])
-
- def testExponentialDecaySchedule(self):
- self.ScheduleTestHelper(
- config_lib.Config(fn='exp_decay', initial=exp(-1), final=exp(-6),
- start_time=10, end_time=20),
- schedules.ExponentialDecaySchedule,
- [(0, exp(-1)), (1, exp(-1)), (10, exp(-1)), (11, exp(-1/2. - 1)),
- (15, exp(-5/2. - 1)), (19, exp(-9/2. - 1)), (20, exp(-6)),
- (100000, exp(-6))])
-
- # Test step function.
- self.ScheduleTestHelper(
- config_lib.Config(fn='exp_decay', initial=exp(-1), final=exp(-6),
- start_time=10, end_time=10),
- schedules.ExponentialDecaySchedule,
- [(0, exp(-1)), (1, exp(-1)), (10, exp(-1)), (11, exp(-6)),
- (15, exp(-6))])
-
- def testSmootherstepDecaySchedule(self):
- self.ScheduleTestHelper(
- config_lib.Config(fn='smooth_decay', initial=2, final=0, start_time=10,
- end_time=20),
- schedules.SmootherstepDecaySchedule,
- [(0, 2), (1, 2), (10, 2), (11, 1.98288), (15, 1), (19, 0.01712),
- (20, 0), (100000, 0)])
-
- # Test step function.
- self.ScheduleTestHelper(
- config_lib.Config(fn='smooth_decay', initial=2, final=0, start_time=10,
- end_time=10),
- schedules.SmootherstepDecaySchedule,
- [(0, 2), (1, 2), (10, 2), (11, 0), (15, 0)])
-
- def testHardOscillatorSchedule(self):
- self.ScheduleTestHelper(
- config_lib.Config(fn='hard_osc', high=2, low=0, start_time=100,
- period=10, transition_fraction=0.5),
- schedules.HardOscillatorSchedule,
- [(0, 2), (1, 2), (10, 2), (100, 2), (101, 1.2), (102, 0.4), (103, 0),
- (104, 0), (105, 0), (106, 0.8), (107, 1.6), (108, 2), (109, 2),
- (110, 2), (111, 1.2), (112, 0.4), (115, 0), (116, 0.8), (119, 2),
- (120, 2), (100001, 1.2), (100002, 0.4), (100005, 0), (100006, 0.8),
- (100010, 2)])
-
- # Test instantaneous step.
- self.ScheduleTestHelper(
- config_lib.Config(fn='hard_osc', high=2, low=0, start_time=100,
- period=10, transition_fraction=0),
- schedules.HardOscillatorSchedule,
- [(0, 2), (1, 2), (10, 2), (99, 2), (100, 0), (104, 0), (105, 2),
- (106, 2), (109, 2), (110, 0)])
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/brain_coder/common/utils.py b/research/brain_coder/common/utils.py
deleted file mode 100644
index fa5f1c50768986ee10eee6120a0bca392b1d9d0e..0000000000000000000000000000000000000000
--- a/research/brain_coder/common/utils.py
+++ /dev/null
@@ -1,558 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Configuration class."""
-
-import bisect
-from collections import deque
-import cPickle
-import heapq
-import random
-
-from absl import logging
-import numpy as np
-import six
-from six.moves import xrange
-import tensorflow as tf
-
-
-def tuple_to_record(tuple_, record_type):
- return record_type(**dict(zip(record_type.__slots__, tuple_)))
-
-
-def make_record(type_name, attributes, defaults=None):
- """Factory for mutable record classes.
-
- A record acts just like a collections.namedtuple except slots are writable.
- One exception is that record classes are not equivalent to tuples or other
- record classes of the same length.
-
- Note, each call to `make_record` produces a unique type. Two calls will make
- different types even if `type_name` is the same each time.
-
- Args:
- type_name: Name of the record type to create.
- attributes: List of names of each record attribute. The order of the list
- is preserved.
- defaults: (optional) default values for attributes. A dict mapping attribute
- names to values.
-
- Returns:
- A new record type.
-
- Raises:
- ValueError: If,
- `defaults` is not a dict,
- `attributes` contains duplicate names,
- `defaults` keys are not contained in `attributes`.
- """
- if defaults is None:
- defaults = {}
- if not isinstance(defaults, dict):
- raise ValueError('defaults must be a dict.')
- attr_set = set(attributes)
- if len(attr_set) < len(attributes):
- raise ValueError('No duplicate attributes allowed.')
- if not set(defaults.keys()).issubset(attr_set):
- raise ValueError('Default attributes must be given in the attributes list.')
-
- class RecordClass(object):
- """A record type.
-
- Acts like mutable tuple with named slots.
- """
- __slots__ = list(attributes)
- _defaults = dict(defaults)
-
- def __init__(self, *args, **kwargs):
- if len(args) > len(self.__slots__):
- raise ValueError('Too many arguments. %s has length %d.'
- % (type(self).__name__, len(self.__slots__)))
- for attr, val in self._defaults.items():
- setattr(self, attr, val)
- for i, arg in enumerate(args):
- setattr(self, self.__slots__[i], arg)
- for attr, val in kwargs.items():
- setattr(self, attr, val)
- for attr in self.__slots__:
- if not hasattr(self, attr):
- raise ValueError('Required attr "%s" is not set.' % attr)
-
- def __len__(self):
- return len(self.__slots__)
-
- def __iter__(self):
- for attr in self.__slots__:
- yield getattr(self, attr)
-
- def __getitem__(self, index):
- return getattr(self, self.__slots__[index])
-
- def __setitem__(self, index, value):
- return setattr(self, self.__slots__[index], value)
-
- def __eq__(self, other):
- # Types must be equal as well as values.
- return (isinstance(other, type(self))
- and all(a == b for a, b in zip(self, other)))
-
- def __str__(self):
- return '%s(%s)' % (
- type(self).__name__,
- ', '.join(attr + '=' + str(getattr(self, attr))
- for attr in self.__slots__))
-
- def __repr__(self):
- return str(self)
-
- RecordClass.__name__ = type_name
- return RecordClass
-
-
-# Making minibatches.
-def stack_pad(tensors, pad_axes=None, pad_to_lengths=None, dtype=np.float32,
- pad_value=0):
- """Stack tensors along 0-th dim and pad them to be the same shape.
-
- Args:
- tensors: Any list of iterables (python list, numpy array, etc). Can be 1D
- or multi-D iterables.
- pad_axes: An int or list of ints. Axes to pad along.
- pad_to_lengths: Length in each dimension. If pad_axes was an int, this is an
- int or None. If pad_axes was a list of ints, this is a list of mixed int
- and None types with the same length, or None. A None length means the
- maximum length among the given tensors is used.
- dtype: Type of output numpy array. Defaults to np.float32.
- pad_value: Value to use for padding. Defaults to 0.
-
- Returns:
- Numpy array containing the tensors stacked along the 0-th dimension and
- padded along the specified dimensions.
-
- Raises:
- ValueError: If the tensors do not have equal shapes along non-padded
- dimensions.
- """
- tensors = [np.asarray(t) for t in tensors]
- max_lengths = [max(l) for l in zip(*[t.shape for t in tensors])]
- same_axes = dict(enumerate(max_lengths))
- if pad_axes is None:
- pad_axes = []
- if isinstance(pad_axes, six.integer_types):
- if pad_to_lengths is not None:
- max_lengths[pad_axes] = pad_to_lengths
- del same_axes[pad_axes]
- else:
- if pad_to_lengths is None:
- pad_to_lengths = [None] * len(pad_axes)
- for i, l in zip(pad_axes, pad_to_lengths):
- if l is not None:
- max_lengths[i] = l
- del same_axes[i]
- same_axes_items = same_axes.items()
- dest = np.full([len(tensors)] + max_lengths, pad_value, dtype=dtype)
- for i, t in enumerate(tensors):
- for j, l in same_axes_items:
- if t.shape[j] != l:
- raise ValueError(
- 'Tensor at index %d does not have size %d along axis %d'
- % (i, l, j))
- dest[[i] + [slice(0, d) for d in t.shape]] = t
- return dest
-
-
-class RandomQueue(deque):
-
- def __init__(self, capacity):
- super(RandomQueue, self).__init__([], capacity)
- self.capacity = capacity
-
- def random_sample(self, sample_size):
- idx = np.random.choice(len(self), sample_size)
- return [self[i] for i in idx]
-
- def push(self, item):
- # Append to right. Oldest element will be popped from left.
- self.append(item)
-
-
-class MPQItemContainer(object):
- """Class for holding an item with its score.
-
- Defines a comparison function for use in the heap-queue.
- """
-
- def __init__(self, score, item, extra_data):
- self.item = item
- self.score = score
- self.extra_data = extra_data
-
- def __cmp__(self, other):
- assert isinstance(other, type(self))
- return cmp(self.score, other.score)
-
- def __iter__(self):
- """Allows unpacking like a tuple."""
- yield self.score
- yield self.item
- yield self.extra_data
-
- def __repr__(self):
- """String representation of this item.
-
- `extra_data` is not included in the representation. We are assuming that
- `extra_data` is not easily interpreted by a human (if it was, it should be
- hashable, like a string or tuple).
-
- Returns:
- String representation of `self`.
- """
- return str((self.score, self.item))
-
- def __str__(self):
- return repr(self)
-
-
-class MaxUniquePriorityQueue(object):
- """A maximum priority queue where duplicates are not added.
-
- The top items by score remain in the queue. When the capacity is reached,
- the lowest scored item in the queue will be dropped.
-
- This implementation differs from a typical priority queue, in that the minimum
- score is popped, instead of the maximum. Largest scores remain stuck in the
- queue. This is useful for accumulating the best known items from a population.
-
- The items used to determine uniqueness must be hashable, but additional
- non-hashable data may be stored with each item.
- """
-
- def __init__(self, capacity):
- self.capacity = capacity
- self.heap = []
- self.unique_items = set()
-
- def push(self, score, item, extra_data=None):
- """Push an item onto the queue.
-
- If the queue is at capacity, the item with the smallest score will be
- dropped. Note that it is assumed each item has exactly one score. The same
- item with a different score will still be dropped.
-
- Args:
- score: Number used to prioritize items in the queue. Largest scores are
- kept in the queue.
- item: A hashable item to be stored. Duplicates of this item will not be
- added to the queue.
- extra_data: An extra (possible not hashable) data to store with the item.
- """
- if item in self.unique_items:
- return
- if len(self.heap) >= self.capacity:
- _, popped_item, _ = heapq.heappushpop(
- self.heap, MPQItemContainer(score, item, extra_data))
- self.unique_items.add(item)
- self.unique_items.remove(popped_item)
- else:
- heapq.heappush(self.heap, MPQItemContainer(score, item, extra_data))
- self.unique_items.add(item)
-
- def pop(self):
- """Pop the item with the lowest score.
-
- Returns:
- score: Item's score.
- item: The item that was popped.
- extra_data: Any extra data stored with the item.
- """
- if not self.heap:
- return ()
- score, item, extra_data = heapq.heappop(self.heap)
- self.unique_items.remove(item)
- return score, item, extra_data
-
- def get_max(self):
- """Peek at the item with the highest score.
-
- Returns:
- Same as `pop`.
- """
- if not self.heap:
- return ()
- score, item, extra_data = heapq.nlargest(1, self.heap)[0]
- return score, item, extra_data
-
- def get_min(self):
- """Peek at the item with the lowest score.
-
- Returns:
- Same as `pop`.
- """
- if not self.heap:
- return ()
- score, item, extra_data = heapq.nsmallest(1, self.heap)[0]
- return score, item, extra_data
-
- def random_sample(self, sample_size):
- """Randomly select items from the queue.
-
- This does not modify the queue.
-
- Items are drawn from a uniform distribution, and not weighted by score.
-
- Args:
- sample_size: Number of random samples to draw. The same item can be
- sampled multiple times.
-
- Returns:
- List of sampled items (of length `sample_size`). Each element in the list
- is a tuple: (item, extra_data).
- """
- idx = np.random.choice(len(self.heap), sample_size)
- return [(self.heap[i].item, self.heap[i].extra_data) for i in idx]
-
- def iter_in_order(self):
- """Iterate over items in the queue from largest score to smallest.
-
- Yields:
- item: Hashable item.
- extra_data: Extra data stored with the item.
- """
- for _, item, extra_data in heapq.nlargest(len(self.heap), self.heap):
- yield item, extra_data
-
- def __len__(self):
- return len(self.heap)
-
- def __iter__(self):
- for _, item, _ in self.heap:
- yield item
-
- def __repr__(self):
- return '[' + ', '.join(repr(c) for c in self.heap) + ']'
-
- def __str__(self):
- return repr(self)
-
-
-class RouletteWheel(object):
- """Randomly samples stored objects proportionally to their given weights.
-
- Stores objects and weights. Acts like a roulette wheel where each object is
- given a slice of the roulette disk proportional to its weight.
-
- This can be used as a replay buffer where past experiences are sampled
- proportionally to their weights. A good choice of "weight" for reinforcement
- learning is exp(reward / temperature) where temperature -> inf makes the
- distribution more uniform and temperature -> 0 makes the distribution more
- peaky.
-
- To prevent experiences from being overweighted by appearing in the replay
- buffer multiple times, a "unique mode" is supported where duplicate
- experiences are ignored. In unique mode, weights can be quickly retrieved from
- keys.
- """
-
- def __init__(self, unique_mode=False, save_file=None):
- """Construct empty RouletteWheel.
-
- If `save_file` is not None, and the file already exists on disk, whatever
- is in the file will be loaded into this instance. This allows jobs using
- RouletteWheel to resume after preemption.
-
- Args:
- unique_mode: If True, puts this RouletteWheel into unique mode, where
- objects are added with hashable keys, so that duplicates are ignored.
- save_file: Optional file path to save to. Must be a string containing
- an absolute path to a file, or None. File will be Python pickle
- format.
- """
- self.unique_mode = unique_mode
- self.objects = []
- self.weights = []
- self.partial_sums = []
- if self.unique_mode:
- self.keys_to_weights = {}
- self.save_file = save_file
- self.save_to_disk_buffer = []
-
- if save_file is not None and tf.gfile.Exists(save_file):
- # Load from disk.
- with tf.gfile.OpenFast(save_file, 'r') as f:
- count = 0
- while 1:
- try:
- obj, weight, key = cPickle.load(f)
- except EOFError:
- break
- else:
- self.add(obj, weight, key)
- count += 1
- logging.info('Loaded %d samples from disk.', count)
- # Clear buffer since these items are already on disk.
- self.save_to_disk_buffer = []
-
- def __iter__(self):
- return iter(zip(self.objects, self.weights))
-
- def __len__(self):
- return len(self.objects)
-
- def is_empty(self):
- """Returns whether there is anything in the roulette wheel."""
- return not self.partial_sums
-
- @property
- def total_weight(self):
- """Total cumulative weight across all objects."""
- if self.partial_sums:
- return self.partial_sums[-1]
- return 0.0
-
- def has_key(self, key):
- if self.unique_mode:
- RuntimeError('has_key method can only be called in unique mode.')
- return key in self.keys_to_weights
-
- def get_weight(self, key):
- if self.unique_mode:
- RuntimeError('get_weight method can only be called in unique mode.')
- return self.keys_to_weights[key]
-
- def add(self, obj, weight, key=None):
- """Add one object and its weight to the roulette wheel.
-
- Args:
- obj: Any object to be stored.
- weight: A non-negative float. The given object will be drawn with
- probability proportional to this weight when sampling.
- key: This argument is only used when in unique mode. To allow `obj` to
- be an unhashable type, like list, a separate hashable key is given.
- Each `key` should be unique to each `obj`. `key` is used to check if
- `obj` has been added to the roulette wheel before.
-
- Returns:
- True if the object was added, False if it was not added due to it being
- a duplicate (this only happens in unique mode).
-
- Raises:
- ValueError: If `weight` is negative.
- ValueError: If `key` is not given when in unique mode, or if `key` is
- given when not in unique mode.
- """
- if weight < 0:
- raise ValueError('Weight must be non-negative')
- if self.unique_mode:
- if key is None:
- raise ValueError(
- 'Hashable key required for objects when unique mode is enabled.')
- if key in self.keys_to_weights:
- # Weight updates are not allowed. Ignore the given value of `weight`.
- return False
- self.keys_to_weights[key] = weight
- elif key is not None:
- raise ValueError(
- 'key argument should not be used when unique mode is disabled.')
- self.objects.append(obj)
- self.weights.append(weight)
- self.partial_sums.append(self.total_weight + weight)
- if self.save_file is not None:
- # Record new item in buffer.
- self.save_to_disk_buffer.append((obj, weight, key))
- return True
-
- def add_many(self, objs, weights, keys=None):
- """Add many object and their weights to the roulette wheel.
-
- Arguments are the same as the `add` method, except each is a list. Lists
- must all be the same length.
-
- Args:
- objs: List of objects to be stored.
- weights: List of non-negative floats. See `add` method.
- keys: List of hashable keys. This argument is only used when in unique
- mode. See `add` method.
-
- Returns:
- Number of objects added. This number will be less than the number of
- objects provided if we are in unique mode and some keys are already
- in the roulette wheel.
-
- Raises:
- ValueError: If `keys` argument is provided when unique_mode == False, or
- is not provided when unique_mode == True.
- ValueError: If any of the lists are not the same length.
- ValueError: If any of the weights are negative.
- """
- if keys is not None and not self.unique_mode:
- raise ValueError('Not in unique mode. Do not provide keys.')
- elif keys is None and self.unique_mode:
- raise ValueError('In unique mode. You must provide hashable keys.')
- if keys and len(objs) != len(keys):
- raise ValueError('Number of objects does not equal number of keys.')
- if len(objs) != len(weights):
- raise ValueError('Number of objects does not equal number of weights.')
- return sum([self.add(obj, weights[i], key=keys[i] if keys else None)
- for i, obj in enumerate(objs)])
-
- def sample(self):
- """Spin the roulette wheel.
-
- Randomly select an object with probability proportional to its weight.
-
- Returns:
- object: The selected object.
- weight: The weight of the selected object.
-
- Raises:
- RuntimeError: If the roulette wheel is empty.
- """
- if self.is_empty():
- raise RuntimeError('Trying to sample from empty roulette wheel.')
- spin = random.random() * self.total_weight
-
- # Binary search.
- i = bisect.bisect_right(self.partial_sums, spin)
- if i == len(self.partial_sums):
- # This should not happen since random.random() will always be strictly
- # less than 1.0, and the last partial sum equals self.total_weight().
- # However it may happen due to rounding error. In that case it is easy to
- # handle this, just select the last object.
- i -= 1
-
- return self.objects[i], self.weights[i]
-
- def sample_many(self, count):
- """Spin the roulette wheel `count` times and return the results."""
- if self.is_empty():
- raise RuntimeError('Trying to sample from empty roulette wheel.')
- return [self.sample() for _ in xrange(count)]
-
- def incremental_save(self, log_info=False):
- """Write new entries to disk.
-
- This performs an append operation on the `save_file` given in the
- constructor. Any entries added since the last call to `incremental_save`
- will be appended to the file.
-
- If a new RouletteWheel is constructed with the same `save_file`, all the
- entries written there will be automatically loaded into the instance.
- This is useful when a job resumes after preemption.
-
- Args:
- log_info: If True, info about this operation will be logged.
-
- Raises:
- RuntimeError: If `save_file` given in the constructor is None.
- """
- if self.save_file is None:
- raise RuntimeError('Cannot call incremental_save. `save_file` is None.')
- if log_info:
- logging.info('Saving %d new samples to disk.',
- len(self.save_to_disk_buffer))
- with tf.gfile.OpenFast(self.save_file, 'a') as f:
- for entry in self.save_to_disk_buffer:
- cPickle.dump(entry, f)
- # Clear the buffer.
- self.save_to_disk_buffer = []
diff --git a/research/brain_coder/common/utils_test.py b/research/brain_coder/common/utils_test.py
deleted file mode 100644
index 569c2877d17bf7707616029cdd2a5eac55df7f60..0000000000000000000000000000000000000000
--- a/research/brain_coder/common/utils_test.py
+++ /dev/null
@@ -1,382 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Tests for common.utils.
-"""
-
-from collections import Counter
-import random
-import tempfile
-import numpy as np
-import tensorflow as tf
-
-from common import utils # brain coder
-
-
-class UtilsTest(tf.test.TestCase):
-
- def testStackPad(self):
- # 1D.
- tensors = [[1, 2, 3], [4, 5, 6, 7, 8], [9]]
- result = utils.stack_pad(tensors, pad_axes=0, pad_to_lengths=6)
- self.assertTrue(np.array_equal(
- result,
- np.asarray([[1, 2, 3, 0, 0, 0],
- [4, 5, 6, 7, 8, 0],
- [9, 0, 0, 0, 0, 0]], dtype=np.float32)))
-
- # 3D.
- tensors = [[[[1, 2, 3], [4, 5, 6]]],
- [[[7, 8, 9], [0, 1, 2]], [[3, 4, 5], [6, 7, 8]]],
- [[[0, 1, 2]], [[3, 4, 5]]]]
- result = utils.stack_pad(tensors, pad_axes=[0, 1], pad_to_lengths=[2, 2])
- self.assertTrue(np.array_equal(
- result,
- np.asarray([[[[1, 2, 3], [4, 5, 6]],
- [[0, 0, 0], [0, 0, 0]]],
- [[[7, 8, 9], [0, 1, 2]],
- [[3, 4, 5], [6, 7, 8]]],
- [[[0, 1, 2], [0, 0, 0]],
- [[3, 4, 5], [0, 0, 0]]]], dtype=np.float32)))
-
- def testStackPadNoAxes(self):
- # 2D.
- tensors = [[[1, 2, 3], [4, 5, 6]],
- [[7, 8, 9], [1, 2, 3]],
- [[4, 5, 6], [7, 8, 9]]]
- result = utils.stack_pad(tensors)
- self.assertTrue(np.array_equal(
- result,
- np.asarray(tensors)))
-
- def testStackPadNoneLength(self):
- # 1D.
- tensors = [[1, 2, 3], [4, 5, 6, 7, 8], [9]]
- result = utils.stack_pad(tensors, pad_axes=0, pad_to_lengths=None)
- self.assertTrue(np.array_equal(
- result,
- np.asarray([[1, 2, 3, 0, 0],
- [4, 5, 6, 7, 8],
- [9, 0, 0, 0, 0]], dtype=np.float32)))
-
- # 3D.
- tensors = [[[[1, 2, 3], [4, 5, 6]]],
- [[[7, 8, 9], [0, 1, 2]], [[3, 4, 5], [6, 7, 8]]],
- [[[0, 1, 2]], [[3, 4, 5]]]]
- result = utils.stack_pad(tensors, pad_axes=[0, 1], pad_to_lengths=None)
- self.assertTrue(np.array_equal(
- result,
- np.asarray([[[[1, 2, 3], [4, 5, 6]],
- [[0, 0, 0], [0, 0, 0]]],
- [[[7, 8, 9], [0, 1, 2]],
- [[3, 4, 5], [6, 7, 8]]],
- [[[0, 1, 2], [0, 0, 0]],
- [[3, 4, 5], [0, 0, 0]]]], dtype=np.float32)))
-
- # 3D with partial pad_to_lengths.
- tensors = [[[[1, 2, 3], [4, 5, 6]]],
- [[[7, 8, 9], [0, 1, 2]], [[3, 4, 5], [6, 7, 8]]],
- [[[0, 1, 2]], [[3, 4, 5]]]]
- result = utils.stack_pad(tensors, pad_axes=[0, 1], pad_to_lengths=[None, 3])
- self.assertTrue(np.array_equal(
- result,
- np.asarray([[[[1, 2, 3], [4, 5, 6], [0, 0, 0]],
- [[0, 0, 0], [0, 0, 0], [0, 0, 0]]],
- [[[7, 8, 9], [0, 1, 2], [0, 0, 0]],
- [[3, 4, 5], [6, 7, 8], [0, 0, 0]]],
- [[[0, 1, 2], [0, 0, 0], [0, 0, 0]],
- [[3, 4, 5], [0, 0, 0], [0, 0, 0]]]], dtype=np.float32)))
-
- def testStackPadValueError(self):
- # 3D.
- tensors = [[[[1, 2, 3], [4, 5, 6]]],
- [[[7, 8, 9], [0, 1, 2]], [[3, 4, 5], [6, 7, 8]]],
- [[[0, 1, 2]], [[3, 4, 5]]],
- [[[1, 2, 3, 4]]]]
-
- # Not all tensors have the same shape along axis 2.
- with self.assertRaises(ValueError):
- utils.stack_pad(tensors, pad_axes=[0, 1], pad_to_lengths=[2, 2])
-
- def testRecord(self):
- my_record = utils.make_record('my_record', ['a', 'b', 'c'], {'b': 55})
- inst = my_record(a=1, b=2, c=3)
- self.assertEqual(1, inst.a)
- self.assertEqual(2, inst.b)
- self.assertEqual(3, inst.c)
- self.assertEqual(1, inst[0])
- self.assertEqual(2, inst[1])
- self.assertEqual(3, inst[2])
- self.assertEqual([1, 2, 3], list(iter(inst)))
- self.assertEqual(3, len(inst))
-
- inst.b = 999
- self.assertEqual(999, inst.b)
- self.assertEqual(999, inst[1])
-
- inst2 = my_record(1, 999, 3)
- self.assertTrue(inst == inst2)
- inst2[1] = 3
- self.assertFalse(inst == inst2)
-
- inst3 = my_record(a=1, c=3)
- inst.b = 55
- self.assertEqual(inst, inst3)
-
- def testRecordUnique(self):
- record1 = utils.make_record('record1', ['a', 'b', 'c'])
- record2 = utils.make_record('record2', ['a', 'b', 'c'])
- self.assertNotEqual(record1(1, 2, 3), record2(1, 2, 3))
- self.assertEqual(record1(1, 2, 3), record1(1, 2, 3))
-
- def testTupleToRecord(self):
- my_record = utils.make_record('my_record', ['a', 'b', 'c'])
- inst = utils.tuple_to_record((5, 6, 7), my_record)
- self.assertEqual(my_record(5, 6, 7), inst)
-
- def testRecordErrors(self):
- my_record = utils.make_record('my_record', ['a', 'b', 'c'], {'b': 10})
-
- with self.assertRaises(ValueError):
- my_record(c=5) # Did not provide required argument 'a'.
- with self.assertRaises(ValueError):
- my_record(1, 2, 3, 4) # Too many arguments.
-
- def testRandomQueue(self):
- np.random.seed(567890)
- queue = utils.RandomQueue(5)
- queue.push(5)
- queue.push(6)
- queue.push(7)
- queue.push(8)
- queue.push(9)
- queue.push(10)
- self.assertTrue(5 not in queue)
- sample = queue.random_sample(1000)
- self.assertEqual(1000, len(sample))
- self.assertEqual([6, 7, 8, 9, 10], sorted(np.unique(sample).tolist()))
-
- def testMaxUniquePriorityQueue(self):
- queue = utils.MaxUniquePriorityQueue(5)
- queue.push(1.0, 'string 1')
- queue.push(-0.5, 'string 2')
- queue.push(0.5, 'string 3')
- self.assertEqual((-0.5, 'string 2', None), queue.pop())
- queue.push(0.1, 'string 4')
- queue.push(1.5, 'string 5')
- queue.push(0.0, 'string 6')
- queue.push(0.2, 'string 7')
- self.assertEqual((1.5, 'string 5', None), queue.get_max())
- self.assertEqual((0.1, 'string 4', None), queue.get_min())
- self.assertEqual(
- [('string 5', None), ('string 1', None), ('string 3', None),
- ('string 7', None), ('string 4', None)],
- list(queue.iter_in_order()))
-
- def testMaxUniquePriorityQueue_Duplicates(self):
- queue = utils.MaxUniquePriorityQueue(5)
- queue.push(0.0, 'string 1')
- queue.push(0.0, 'string 2')
- queue.push(0.0, 'string 3')
- self.assertEqual((0.0, 'string 1', None), queue.pop())
- self.assertEqual((0.0, 'string 2', None), queue.pop())
- self.assertEqual((0.0, 'string 3', None), queue.pop())
- self.assertEqual(0, len(queue))
- queue.push(0.1, 'string 4')
- queue.push(1.5, 'string 5')
- queue.push(0.3, 'string 6')
- queue.push(0.2, 'string 7')
- queue.push(0.0, 'string 8')
- queue.push(1.5, 'string 5')
- queue.push(1.5, 'string 5')
- self.assertEqual((1.5, 'string 5', None), queue.get_max())
- self.assertEqual((0.0, 'string 8', None), queue.get_min())
- self.assertEqual(
- [('string 5', None), ('string 6', None), ('string 7', None),
- ('string 4', None), ('string 8', None)],
- list(queue.iter_in_order()))
-
- def testMaxUniquePriorityQueue_ExtraData(self):
- queue = utils.MaxUniquePriorityQueue(5)
- queue.push(1.0, 'string 1', [1, 2, 3])
- queue.push(0.5, 'string 2', [4, 5, 6])
- queue.push(0.5, 'string 3', [7, 8, 9])
- queue.push(0.5, 'string 2', [10, 11, 12])
- self.assertEqual((0.5, 'string 2', [4, 5, 6]), queue.pop())
- self.assertEqual((0.5, 'string 3', [7, 8, 9]), queue.pop())
- self.assertEqual((1.0, 'string 1', [1, 2, 3]), queue.pop())
- self.assertEqual(0, len(queue))
- queue.push(0.5, 'string 2', [10, 11, 12])
- self.assertEqual((0.5, 'string 2', [10, 11, 12]), queue.pop())
-
- def testRouletteWheel(self):
- random.seed(12345678987654321)
- r = utils.RouletteWheel()
- self.assertTrue(r.is_empty())
- with self.assertRaises(RuntimeError):
- r.sample() # Cannot sample when empty.
- self.assertEqual(0, r.total_weight)
- self.assertEqual(True, r.add('a', 0.1))
- self.assertFalse(r.is_empty())
- self.assertEqual(0.1, r.total_weight)
- self.assertEqual(True, r.add('b', 0.01))
- self.assertEqual(0.11, r.total_weight)
- self.assertEqual(True, r.add('c', 0.5))
- self.assertEqual(True, r.add('d', 0.1))
- self.assertEqual(True, r.add('e', 0.05))
- self.assertEqual(True, r.add('f', 0.03))
- self.assertEqual(True, r.add('g', 0.001))
- self.assertEqual(0.791, r.total_weight)
- self.assertFalse(r.is_empty())
-
- # Check that sampling is correct.
- obj, weight = r.sample()
- self.assertTrue(isinstance(weight, float), 'Type: %s' % type(weight))
- self.assertTrue((obj, weight) in r)
- for obj, weight in r.sample_many(100):
- self.assertTrue(isinstance(weight, float), 'Type: %s' % type(weight))
- self.assertTrue((obj, weight) in r)
-
- # Check that sampling distribution is correct.
- n = 1000000
- c = Counter(r.sample_many(n))
- for obj, w in r:
- estimated_w = c[(obj, w)] / float(n) * r.total_weight
- self.assertTrue(
- np.isclose(w, estimated_w, atol=1e-3),
- 'Expected %s, got %s, for object %s' % (w, estimated_w, obj))
-
- def testRouletteWheel_AddMany(self):
- random.seed(12345678987654321)
- r = utils.RouletteWheel()
- self.assertTrue(r.is_empty())
- with self.assertRaises(RuntimeError):
- r.sample() # Cannot sample when empty.
- self.assertEqual(0, r.total_weight)
- count = r.add_many(
- ['a', 'b', 'c', 'd', 'e', 'f', 'g'],
- [0.1, 0.01, 0.5, 0.1, 0.05, 0.03, 0.001])
- self.assertEqual(7, count)
- self.assertFalse(r.is_empty())
- self.assertEqual(0.791, r.total_weight)
-
- # Adding no items is allowed.
- count = r.add_many([], [])
- self.assertEqual(0, count)
- self.assertFalse(r.is_empty())
- self.assertEqual(0.791, r.total_weight)
-
- # Check that sampling is correct.
- obj, weight = r.sample()
- self.assertTrue(isinstance(weight, float), 'Type: %s' % type(weight))
- self.assertTrue((obj, weight) in r)
- for obj, weight in r.sample_many(100):
- self.assertTrue(isinstance(weight, float), 'Type: %s' % type(weight))
- self.assertTrue((obj, weight) in r)
-
- # Check that sampling distribution is correct.
- n = 1000000
- c = Counter(r.sample_many(n))
- for obj, w in r:
- estimated_w = c[(obj, w)] / float(n) * r.total_weight
- self.assertTrue(
- np.isclose(w, estimated_w, atol=1e-3),
- 'Expected %s, got %s, for object %s' % (w, estimated_w, obj))
-
- def testRouletteWheel_AddZeroWeights(self):
- r = utils.RouletteWheel()
- self.assertEqual(True, r.add('a', 0))
- self.assertFalse(r.is_empty())
- self.assertEqual(4, r.add_many(['b', 'c', 'd', 'e'], [0, 0.1, 0, 0]))
- self.assertEqual(
- [('a', 0.0), ('b', 0.0), ('c', 0.1), ('d', 0.0), ('e', 0.0)],
- list(r))
-
- def testRouletteWheel_UniqueMode(self):
- random.seed(12345678987654321)
- r = utils.RouletteWheel(unique_mode=True)
- self.assertEqual(True, r.add([1, 2, 3], 1, 'a'))
- self.assertEqual(True, r.add([4, 5], 0.5, 'b'))
- self.assertEqual(False, r.add([1, 2, 3], 1.5, 'a'))
- self.assertEqual(
- [([1, 2, 3], 1.0), ([4, 5], 0.5)],
- list(r))
- self.assertEqual(1.5, r.total_weight)
- self.assertEqual(
- 2,
- r.add_many(
- [[5, 6, 2, 3], [1, 2, 3], [8], [1, 2, 3]],
- [0.1, 0.2, 0.1, 2.0],
- ['c', 'a', 'd', 'a']))
- self.assertEqual(
- [([1, 2, 3], 1.0), ([4, 5], 0.5), ([5, 6, 2, 3], 0.1), ([8], 0.1)],
- list(r))
- self.assertTrue(np.isclose(1.7, r.total_weight))
- self.assertEqual(0, r.add_many([], [], [])) # Adding no items is allowed.
- with self.assertRaises(ValueError):
- # Key not given.
- r.add([7, 8, 9], 2.0)
- with self.assertRaises(ValueError):
- # Keys not given.
- r.add_many([[7, 8, 9], [10]], [2.0, 2.0])
- self.assertEqual(True, r.has_key('a'))
- self.assertEqual(True, r.has_key('b'))
- self.assertEqual(False, r.has_key('z'))
- self.assertEqual(1.0, r.get_weight('a'))
- self.assertEqual(0.5, r.get_weight('b'))
-
- r = utils.RouletteWheel(unique_mode=False)
- self.assertEqual(True, r.add([1, 2, 3], 1))
- self.assertEqual(True, r.add([4, 5], 0.5))
- self.assertEqual(True, r.add([1, 2, 3], 1.5))
- self.assertEqual(
- [([1, 2, 3], 1.0), ([4, 5], 0.5), ([1, 2, 3], 1.5)],
- list(r))
- self.assertEqual(3, r.total_weight)
- self.assertEqual(
- 4,
- r.add_many(
- [[5, 6, 2, 3], [1, 2, 3], [8], [1, 2, 3]],
- [0.1, 0.2, 0.1, 0.2]))
- self.assertEqual(
- [([1, 2, 3], 1.0), ([4, 5], 0.5), ([1, 2, 3], 1.5),
- ([5, 6, 2, 3], 0.1), ([1, 2, 3], 0.2), ([8], 0.1), ([1, 2, 3], 0.2)],
- list(r))
- self.assertTrue(np.isclose(3.6, r.total_weight))
- with self.assertRaises(ValueError):
- # Key is given.
- r.add([7, 8, 9], 2.0, 'a')
- with self.assertRaises(ValueError):
- # Keys are given.
- r.add_many([[7, 8, 9], [10]], [2.0, 2.0], ['a', 'b'])
-
- def testRouletteWheel_IncrementalSave(self):
- f = tempfile.NamedTemporaryFile()
- r = utils.RouletteWheel(unique_mode=True, save_file=f.name)
- entries = [
- ([1, 2, 3], 0.1, 'a'),
- ([4, 5], 0.2, 'b'),
- ([6], 0.3, 'c'),
- ([7, 8, 9, 10], 0.25, 'd'),
- ([-1, -2], 0.15, 'e'),
- ([-3, -4, -5], 0.5, 'f')]
-
- self.assertTrue(r.is_empty())
- for i in range(0, len(entries), 2):
- r.add(*entries[i])
- r.add(*entries[i + 1])
- r.incremental_save()
-
- r2 = utils.RouletteWheel(unique_mode=True, save_file=f.name)
- self.assertEqual(i + 2, len(r2))
- count = 0
- for j, (obj, weight) in enumerate(r2):
- self.assertEqual(entries[j][0], obj)
- self.assertEqual(entries[j][1], weight)
- self.assertEqual(weight, r2.get_weight(entries[j][2]))
- count += 1
- self.assertEqual(i + 2, count)
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/brain_coder/single_task/BUILD b/research/brain_coder/single_task/BUILD
deleted file mode 100644
index 47e91b12b8ba40a2a9916a89375fbb773758d7cf..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/BUILD
+++ /dev/null
@@ -1,244 +0,0 @@
-licenses(["notice"])
-
-package(default_visibility = [
- "//learning/brain/research/neural_coder:__subpackages__",
-])
-
-load("@subpar//:subpar.bzl", "par_binary")
-
-par_binary(
- name = "run",
- srcs = ["run.py"],
- deps = [
- ":defaults",
- ":ga_train",
- ":pg_train",
- # absl dep :app
- # absl dep /flags
- # absl dep /logging
- ],
-)
-
-par_binary(
- name = "tune",
- srcs = ["tune.py"],
- deps = [
- ":defaults",
- ":run",
- # file dep
- # absl dep :app
- # absl dep /flags
- # absl dep /logging
- # numpy dep
- # tensorflow dep
- ],
-)
-
-py_library(
- name = "ga_train",
- srcs = ["ga_train.py"],
- deps = [
- ":data",
- ":defaults",
- ":ga_lib",
- ":results_lib",
- # file dep
- # absl dep /flags
- # absl dep /logging
- # numpy dep
- # tensorflow dep
- "//common:utils", # project
- ],
-)
-
-py_library(
- name = "ga_lib",
- srcs = ["ga_lib.py"],
- deps = [
- ":misc",
- # absl dep /flags
- # absl dep /logging
- # numpy dep
- "//common:bf", # project
- "//common:utils", # project
- ],
-)
-
-py_test(
- name = "ga_train_test",
- srcs = ["ga_train_test.py"],
- deps = [
- ":defaults",
- ":run",
- # absl dep /flags
- # tensorflow dep
- ],
-)
-
-py_library(
- name = "pg_train",
- srcs = ["pg_train.py"],
- deps = [
- ":data",
- ":defaults",
- ":pg_agent",
- ":results_lib",
- # file dep
- # absl dep /flags
- # absl dep /logging
- # tensorflow dep
- # tensorflow internal dep # build_cleaner: keep
- ],
-)
-
-py_library(
- name = "pg_agent",
- srcs = ["pg_agent.py"],
- deps = [
- ":misc",
- # file dep
- # absl dep /logging
- # numpy dep
- # tensorflow dep
- "//common:rollout", # project
- "//common:utils", # project
- ],
-)
-
-py_test(
- name = "pg_agent_test",
- srcs = ["pg_agent_test.py"],
- deps = [
- ":data",
- ":defaults",
- ":misc",
- ":pg_agent",
- ":pg_train",
- # absl dep /logging
- # numpy dep
- # tensorflow dep
- "//common:utils", # project
- ],
-)
-
-py_library(
- name = "defaults",
- srcs = ["defaults.py"],
- deps = [
- # absl dep /logging
- "//common:config_lib", # project
- ],
-)
-
-py_library(
- name = "misc",
- srcs = ["misc.py"],
-)
-
-py_library(
- name = "data",
- srcs = ["data.py"],
- deps = [
- ":code_tasks",
- # absl dep /logging
- ],
-)
-
-py_library(
- name = "code_tasks",
- srcs = ["code_tasks.py"],
- deps = [
- ":misc",
- ":test_tasks",
- # absl dep /logging
- # numpy dep
- "//common:bf", # project
- "//common:reward", # project
- ],
-)
-
-py_test(
- name = "code_tasks_test",
- srcs = ["code_tasks_test.py"],
- deps = [
- ":code_tasks",
- ":defaults",
- # numpy dep
- # tensorflow dep
- ],
-)
-
-py_library(
- name = "test_tasks",
- srcs = ["test_tasks.py"],
- deps = [
- ":misc",
- "//common:reward", # project
- ],
-)
-
-py_test(
- name = "test_tasks_test",
- srcs = ["test_tasks_test.py"],
- deps = [
- ":misc",
- ":test_tasks",
- # numpy dep
- # tensorflow dep
- ],
-)
-
-py_test(
- name = "pg_train_test",
- size = "large",
- srcs = ["pg_train_test.py"],
- deps = [
- ":defaults",
- ":run",
- # absl dep /logging
- # tensorflow dep
- ],
-)
-
-py_library(
- name = "results_lib",
- srcs = ["results_lib.py"],
- deps = [
- # file dep
- # tensorflow dep
- ],
-)
-
-py_test(
- name = "results_lib_test",
- srcs = ["results_lib_test.py"],
- deps = [
- ":results_lib",
- # tensorflow dep
- ],
-)
-
-par_binary(
- name = "aggregate_experiment_results",
- srcs = ["aggregate_experiment_results.py"],
- deps = [
- ":misc",
- ":results_lib",
- # file dep
- # absl dep :app
- # absl dep /flags
- # numpy dep
- # tensorflow dep
- ],
-)
-
-par_binary(
- name = "aggregate_tuning_results",
- srcs = ["aggregate_tuning_results.py"],
- deps = [
- # file dep
- # absl dep :app
- # absl dep /flags
- # tensorflow dep
- ],
-)
diff --git a/research/brain_coder/single_task/README.md b/research/brain_coder/single_task/README.md
deleted file mode 100644
index 69eaabcc6ccabada838a0a2a3f12fd7eed69744c..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/README.md
+++ /dev/null
@@ -1,192 +0,0 @@
-# Experiments for ICLR 2018 paper.
-
-[Neural Program Synthesis with Priority Queue Training](https://arxiv.org/abs/1801.03526).
-
-Runs policy gradient (REINFORCE), priority queue training, genetic algorithm,
-and uniform random search.
-
-Run all examples below out of your top-level repo directory, i.e. where your git
-clone resides.
-
-
-## Just tell me how to run something and see results
-```bash
-# These tasks are the fastest to learn. 'echo' and 'count-down' are very
-# easy. run_eval_tasks.py will do most of the work to run all the jobs.
-# Should take between 10 and 30 minutes.
-
-# How many repetitions each experiment will run. In the paper, we use 25. Less
-# reps means faster experiments, but noisier results.
-REPS=25
-
-# Extra description in the job names for these experiments. Use this description
-# to distinguish between multiple runs of the same experiment.
-DESC="demo"
-
-# The tasks to run.
-TASKS="reverse echo-second-seq"
-
-# The model types and max NPE.
-EXPS=( pg-20M topk-20M ga-20M rand-20M )
-
-# Where training data is saved. This is chosen by launch_training.sh. Custom
-# implementations of launch_training.sh may use different locations.
-MODELS_DIR="/tmp/models"
-
-# Run run_eval_tasks.py for each experiment name in EXPS.
-for exp in "${EXPS[@]}"
-do
- ./single_task/run_eval_tasks.py \
- --exp "$exp" --tasks $TASKS --desc "$DESC" --reps $REPS
-done
-
-# During training or after completion, run this to aggregate results into a
-# table. This is also useful for seeing how much progress has been made.
-# Make sure the arguments here match the settings used above.
-# Note: This can take a few minutes because it reads from every experiment
-# directory.
-bazel run single_task:aggregate_experiment_results -- \
- --models_dir="$MODELS_DIR" \
- --max_npe="20M" \
- --task_list="$TASKS" \
- --model_types="[('pg', '$DESC'), ('topk', '$DESC'), ('ga', '$DESC'),
- ('rand', '$DESC')]" \
- --csv_file="/tmp/results_table.csv"
-```
-
-
-## Reproduce tuning results in paper
-```bash
-bazel build -c opt single_task:tune.par
-
-# PG and TopK Tuning.
-MAX_NPE=5000000
-CONFIG="
-env=c(task_cycle=['reverse-tune','remove-tune']),
-agent=c(
- algorithm='pg',
- grad_clip_threshold=50.0,param_init_factor=0.5,entropy_beta=0.05,lr=1e-5,
- optimizer='rmsprop',ema_baseline_decay=0.99,topk_loss_hparam=0.0,topk=0,
- replay_temperature=1.0,alpha=0.0,eos_token=False),
-timestep_limit=50,batch_size=64"
-
-./single_task/launch_tuning.sh \
- --job_name="iclr_pg_gridsearch.reverse-remove" \
- --config="$CONFIG" \
- --max_npe="$MAX_NPE" \
- --num_workers_per_tuner=1 \
- --num_ps_per_tuner=0 \
- --num_tuners=1 \
- --num_repetitions=50 \
- --hparam_space_type="pg" \
- --stop_on_success=true
-./single_task/launch_tuning.sh \
- --job_name="iclr_pg_topk_gridsearch.reverse-remove" \
- --config="$CONFIG" \
- --max_npe="$MAX_NPE" \
- --num_workers_per_tuner=1 \
- --num_ps_per_tuner=0 \
- --num_tuners=1 \
- --num_repetitions=50 \
- --hparam_space_type="pg-topk" \
- --fixed_hparams="topk=10" \
- --stop_on_success=true
-./single_task/launch_tuning.sh \
- --job_name="iclr_topk_gridsearch.reverse-remove" \
- --config="$CONFIG" \
- --max_npe="$MAX_NPE" \
- --num_workers_per_tuner=1 \
- --num_ps_per_tuner=0 \
- --num_tuners=1 \
- --num_repetitions=50 \
- --hparam_space_type="topk" \
- --fixed_hparams="topk=10" \
- --stop_on_success=true
-
-# GA Tuning.
-CONFIG="
-env=c(task_cycle=['reverse-tune','remove-char-tune']),
-agent=c(algorithm='ga'),
-timestep_limit=50"
-./single_task/launch_tuning.sh \
- --job_name="iclr_ga_gridsearch.reverse-remove" \
- --config="$CONFIG" \
- --max_npe="$MAX_NPE" \
- --num_workers_per_tuner=25 \
- --num_ps_per_tuner=0 \
- --num_tuners=1 \
- --num_repetitions=50 \
- --hparam_space_type="ga" \
- --stop_on_success=true
-
-# Aggregate tuning results. Run after tuning jobs complete.
-bazel run -c opt single_task:aggregate_tuning_results -- \
- --tuning_dir="$MODELS_DIR/iclr_pg_gridsearch.reverse-remove"
-bazel run -c opt single_task:aggregate_tuning_results -- \
- --tuning_dir="$MODELS_DIR/iclr_pg_topk_gridsearch.reverse-remove"
-bazel run -c opt single_task:aggregate_tuning_results -- \
- --tuning_dir="$MODELS_DIR/iclr_topk_gridsearch.reverse-remove"
-bazel run -c opt single_task:aggregate_tuning_results -- \
- --tuning_dir="$MODELS_DIR/iclr_ga_gridsearch.reverse-remove"
-```
-
-## Reproduce eval results in paper
-```bash
-DESC="v0" # Description for each experiment. "Version 0" is a good default.
-EXPS=( pg-5M topk-5M ga-5M rand-5M pg-20M topk-20M ga-20M rand-20M )
-for exp in "${EXPS[@]}"
-do
- ./single_task/run_eval_tasks.py \
- --exp "$exp" --iclr_tasks --desc "$DESC"
-done
-```
-
-## Run single experiment
-```bash
-EXP="topk-20M" # Learning algorithm + max-NPE
-TASK="reverse" # Coding task
-DESC="v0" # Description for each experiment. "Version 0" is a good default.
-./single_task/run_eval_tasks.py \
- --exp "$EXP" --task "$TASK" --desc "$DESC"
-```
-
-## Fetch eval results into a table
-```bash
-# These arguments should match the settings you used to run the experiments.
-MODELS_DIR="/tmp/models"
-MAX_NPE="20M"
-DESC="v0" # Same description used in the experiments.
-# MODEL_TYPES specifies each model type and the description used in their
-# experiments.
-MODEL_TYPES="[('pg', '$DESC'), ('topk', '$DESC'),
- ('ga', '$DESC'), ('rand', '$DESC')]"
-TASKS="" # Empty string will default to all ICLR tasks.
-# To specify custom task list, give task names separated by spaces. Example:
-# TASKS="reverse remove-char"
-bazel run single_task:aggregate_experiment_results -- \
- --models_dir="$MODELS_DIR" \
- --max_npe="$MAX_NPE" \
- --task_list="$TASKS" \
- --model_types="$MODEL_TYPES" \
- --csv_file="/tmp/results_table.csv"
-```
-
-## Reproduce shortest code examples in paper
-```bash
-# Maximum NPE is higher here. We only do 1 repetition, and the algorithm needs
-# time to simplify its solution.
-MODELS_DIR="/tmp/models"
-NPE="500M"
-DESC="short-code"
-./single_task/run_eval_tasks.py \
- --exp "simpl-$NPE" --desc "$DESC" --iclr_tasks --reps 1
-
-# Aggregate best code strings. Run after training completes.
-TASKS="" # Empty string. Will default to all ICLR tasks.
-bazel run single_task:aggregate_experiment_results -- \
- --models_dir="$MODELS_DIR" \
- --max_npe="$NPE" \
- --task_list="$TASKS" \
- --model_types="[('topk', '$DESC')]" \
- --data=code
-```
diff --git a/research/brain_coder/single_task/aggregate_experiment_results.py b/research/brain_coder/single_task/aggregate_experiment_results.py
deleted file mode 100644
index f106253004b3bbe1ff32443c41b8999b1c9e96f6..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/aggregate_experiment_results.py
+++ /dev/null
@@ -1,380 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-r"""This script crawls experiment directories for results and aggregates them.
-
-Usage example:
-
-MODELS_DIR="/tmp/models"
-bazel run single_task:aggregate_experiment_results -- \
- --models_dir="$MODELS_DIR" \
- --max_npe="20M" \
- --task_list="add echo" \
- --model_types="[('topk', 'v0'), ('ga', 'v0')]" \
- --csv_file=/tmp/results_table.csv
-"""
-
-import ast
-from collections import namedtuple
-import csv
-import os
-import re
-import StringIO
-import sys
-
-from absl import app
-from absl import flags
-import numpy as np
-import tensorflow as tf
-
-from single_task import misc # brain coder
-from single_task import results_lib # brain coder
-
-DEFAULT_MODELS = [('pg', 'v0'), ('topk', 'v0'), ('ga', 'v0'), ('rand', 'v0')]
-DEFAULT_TASKS = [
- 'reverse', 'remove-char', 'count-char', 'add', 'bool-logic', 'print-hello',
- 'echo-twice', 'echo-thrice', 'copy-reverse', 'zero-cascade', 'cascade',
- 'shift-left', 'shift-right', 'riffle', 'unriffle', 'middle-char',
- 'remove-last', 'remove-last-two', 'echo-alternating', 'echo-half', 'length',
- 'echo-second-seq', 'echo-nth-seq', 'substring', 'divide-2', 'dedup']
-
-FLAGS = flags.FLAGS
-flags.DEFINE_string(
- 'models_dir', '',
- 'Absolute path where results folders are found.')
-flags.DEFINE_string(
- 'exp_prefix', 'bf_rl_iclr',
- 'Prefix for all experiment folders.')
-flags.DEFINE_string(
- 'max_npe', '5M',
- 'String representation of max NPE of the experiments.')
-flags.DEFINE_spaceseplist(
- 'task_list', DEFAULT_TASKS,
- 'List of task names separated by spaces. If empty string, defaults to '
- '`DEFAULT_TASKS`. These are the rows of the results table.')
-flags.DEFINE_string(
- 'model_types', str(DEFAULT_MODELS),
- 'String representation of a python list of 2-tuples, each a model_type + '
- 'job description pair. Descriptions allow you to choose among different '
- 'runs of the same experiment. These are the columns of the results table.')
-flags.DEFINE_string(
- 'csv_file', '/tmp/results_table.csv',
- 'Where to write results table. Format is CSV.')
-flags.DEFINE_enum(
- 'data', 'success_rates', ['success_rates', 'code'],
- 'What type of data to aggregate.')
-
-
-def make_csv_string(table):
- """Convert 2D list to CSV string."""
- s = StringIO.StringIO()
- writer = csv.writer(s)
- writer.writerows(table)
- value = s.getvalue()
- s.close()
- return value
-
-
-def process_results(metrics):
- """Extract useful information from given metrics.
-
- Args:
- metrics: List of results dicts. These should have been written to disk by
- training jobs.
-
- Returns:
- Dict mapping stats names to values.
-
- Raises:
- ValueError: If max_npe or max_global_repetitions values are inconsistant
- across dicts in the `metrics` list.
- """
- count = len(metrics)
- success_count = 0
- total_npe = 0 # Counting NPE across all runs.
- success_npe = 0 # Counting NPE in successful runs only.
- max_npe = 0
- max_repetitions = 0
- for metric_dict in metrics:
- if not max_npe:
- max_npe = metric_dict['max_npe']
- elif max_npe != metric_dict['max_npe']:
- raise ValueError(
- 'Invalid experiment. Different reps have different max-NPE settings.')
- if not max_repetitions:
- max_repetitions = metric_dict['max_global_repetitions']
- elif max_repetitions != metric_dict['max_global_repetitions']:
- raise ValueError(
- 'Invalid experiment. Different reps have different num-repetition '
- 'settings.')
- if metric_dict['found_solution']:
- success_count += 1
- success_npe += metric_dict['npe']
- total_npe += metric_dict['npe']
- stats = {}
- stats['max_npe'] = max_npe
- stats['max_repetitions'] = max_repetitions
- stats['repetitions'] = count
- stats['successes'] = success_count # successful reps
- stats['failures'] = count - success_count # failed reps
- stats['success_npe'] = success_npe
- stats['total_npe'] = total_npe
- if success_count:
- # Only successful runs counted.
- stats['avg_success_npe'] = stats['success_npe'] / float(success_count)
- else:
- stats['avg_success_npe'] = 0.0
- if count:
- stats['success_rate'] = success_count / float(count)
- stats['avg_total_npe'] = stats['total_npe'] / float(count)
- else:
- stats['success_rate'] = 0.0
- stats['avg_total_npe'] = 0.0
-
- return stats
-
-
-ProcessedResults = namedtuple('ProcessedResults', ['metrics', 'processed'])
-
-
-def get_results_for_experiment(
- models_dir, task_name, model_type='pg', max_npe='5M', desc='v0',
- name_prefix='bf_rl_paper', extra_desc=''):
- """Get and process results for a given experiment.
-
- An experiment is a set of runs with the same hyperparameters and environment.
- It is uniquely specified by a (task_name, model_type, max_npe) triple, as
- well as an optional description.
-
- We assume that each experiment has a folder with the same name as the job that
- ran the experiment. The name is computed by
- "%name_prefix%.%desc%-%max_npe%_%task_name%".
-
- Args:
- models_dir: Parent directory containing experiment folders.
- task_name: String name of task (the coding env). See code_tasks.py or
- run_eval_tasks.py
- model_type: Name of the algorithm, such as 'pg', 'topk', 'ga', 'rand'.
- max_npe: String SI unit representation of the maximum NPE threshold for the
- experiment. For example, "5M" means 5 million.
- desc: Description.
- name_prefix: Prefix of job names. Normally leave this as default.
- extra_desc: Optional extra description at the end of the job name.
-
- Returns:
- ProcessedResults namedtuple instance, containing
- metrics: Raw dicts read from disk.
- processed: Stats computed by `process_results`.
-
- Raises:
- ValueError: If max_npe in the metrics does not match NPE in the experiment
- folder name.
- """
- folder = name_prefix + '.{0}.{1}-{2}_{3}'.format(desc, model_type, max_npe,
- task_name)
- if extra_desc:
- folder += '.' + extra_desc
-
- results = results_lib.Results(os.path.join(models_dir, folder))
- metrics, _ = results.read_all()
- processed = process_results(metrics)
- if (not np.isclose(processed['max_npe'], misc.si_to_int(max_npe))
- and processed['repetitions']):
- raise ValueError(
- 'Invalid experiment. Max-NPE setting does not match expected max-NPE '
- 'in experiment name.')
- return ProcessedResults(metrics=metrics, processed=processed)
-
-
-BestCodeResults = namedtuple(
- 'BestCodeResults',
- ['code', 'reward', 'npe', 'folder', 'finished', 'error'])
-
-
-class BestCodeResultError(object):
- success = 0
- no_solution_found = 1
- experiment_does_not_exist = 2
-
-
-def get_best_code_for_experiment(
- models_dir, task_name, model_type='pg', max_npe='5M', desc=0,
- name_prefix='bf_rl_paper', extra_desc=''):
- """Like `get_results_for_experiment`, but fetches the code solutions."""
- folder = name_prefix + '.{0}.{1}-{2}_{3}'.format(desc, model_type, max_npe,
- task_name)
- if extra_desc:
- folder += '.' + extra_desc
-
- log_dir = os.path.join(models_dir, folder, 'logs')
- search_regex = r'^solutions_([0-9])+\.txt$'
- try:
- all_children = tf.gfile.ListDirectory(log_dir)
- except tf.errors.NotFoundError:
- return BestCodeResults(
- code=None, reward=0.0, npe=0, folder=folder, finished=False,
- error=BestCodeResultError.experiment_does_not_exist)
- solution_files = [
- fname for fname in all_children if re.search(search_regex, fname)]
- max_reward = 0.0
- npe = 0
- best_code = None
- for fname in solution_files:
- with tf.gfile.FastGFile(os.path.join(log_dir, fname), 'r') as reader:
- results = [ast.literal_eval(entry) for entry in reader]
- for res in results:
- if res['reward'] > max_reward:
- best_code = res['code']
- max_reward = res['reward']
- npe = res['npe']
- error = (
- BestCodeResultError.success if best_code
- else BestCodeResultError.no_solution_found)
- try:
- # If there is a status.txt file, check if it contains the status of the job.
- with tf.gfile.FastGFile(os.path.join(log_dir, 'status.txt'), 'r') as f:
- # Job is done, so mark this experiment as finished.
- finished = f.read().lower().strip() == 'done'
- except tf.errors.NotFoundError:
- # No status file has been written, so the experiment is not done. No need to
- # report an error here, because we do not require that experiment jobs write
- # out a status.txt file until they have finished.
- finished = False
- return BestCodeResults(
- code=best_code, reward=max_reward, npe=npe, folder=folder,
- finished=finished, error=error)
-
-
-def make_results_table(
- models=None,
- tasks=None,
- max_npe='5M',
- name_prefix='bf_rl_paper',
- extra_desc='',
- models_dir='/tmp'):
- """Creates a table of results: algorithm + version by tasks.
-
- Args:
- models: The table columns. A list of (algorithm, desc) tuples.
- tasks: The table rows. List of task names.
- max_npe: String SI unit representation of the maximum NPE threshold for the
- experiment. For example, "5M" means 5 million. All entries in the table
- share the same max-NPE.
- name_prefix: Name prefix used in logging directory for the experiment.
- extra_desc: Extra description added to name of logging directory for the
- experiment.
- models_dir: Parent directory containing all experiment folders.
-
- Returns:
- A 2D list holding the table cells.
- """
- if models is None:
- models = DEFAULT_MODELS
- if tasks is None:
- tasks = DEFAULT_TASKS
- model_results = {}
- for model_type, desc in models:
- model_results[model_type] = {
- tname: get_results_for_experiment(
- models_dir, tname, model_type, max_npe, desc,
- name_prefix=name_prefix, extra_desc=extra_desc
- ).processed
- for tname in tasks}
-
- def info(stats):
- return [str(stats['repetitions']),
- '%.2f' % stats['success_rate'],
- str(int(stats['avg_total_npe']))]
-
- rows = [['max NPE: ' + max_npe]
- + misc.flatten([['{0} ({1})'.format(m, d), '', '']
- for m, d in models])]
- rows.append(
- [''] + misc.flatten([['reps', 'success rate', 'avg NPE']
- for _ in models]))
- for tname in tasks:
- rows.append(
- [tname]
- + misc.flatten([info(model_results[model][tname])
- for model, _ in models]))
-
- return rows
-
-
-def print_results_table(results_table):
- """Print human readable results table to stdout."""
- print('')
- print('=== Results Table ===')
- print('Format: # reps [success rate, avg total NPE]')
-
- def info_str(info_row):
- # num_runs (success_rate, avg_total_npe)
- if not info_row[0]:
- return '0'
- return '%s [%s, %s]' % (str(info_row[0]).ljust(2), info_row[1], info_row[2])
-
- nc = len(results_table[0]) # num cols
- out_table = [
- [results_table[0][0]] + [results_table[0][i] for i in range(1, nc, 3)]]
- for row in results_table[2:]:
- out_table.append([row[0]] + [info_str(row[i:i+3]) for i in range(1, nc, 3)])
-
- nc = len(out_table[0]) # num cols
- col_widths = [max(len(row[col]) for row in out_table) for col in range(nc)]
-
- table_string = ''
- for row in out_table:
- table_string += ''.join(
- [row[c].ljust(col_widths[c] + 2) for c in range(nc)]) + '\n'
-
- print(table_string)
-
-
-def main(argv):
- del argv # Unused.
-
- name_prefix = FLAGS.exp_prefix
- print('Experiments prefix: %s' % name_prefix)
-
- model_types = ast.literal_eval(FLAGS.model_types)
-
- if FLAGS.data == 'success_rates':
- results_table = make_results_table(
- models=model_types, tasks=FLAGS.task_list, max_npe=FLAGS.max_npe,
- models_dir=FLAGS.models_dir,
- name_prefix=name_prefix, extra_desc='')
- with tf.gfile.FastGFile(FLAGS.csv_file, 'w') as f:
- f.write(make_csv_string(results_table))
-
- print_results_table(results_table)
- else:
- # Best code
- print('* = experiment is still running')
- print('')
- print('=== Best Synthesized Code ===')
- for model_type, desc in model_types:
- print('%s (%s)' % (model_type, desc))
- sys.stdout.flush()
- for tname in FLAGS.task_list:
- res = get_best_code_for_experiment(
- FLAGS.models_dir, tname, model_type, FLAGS.max_npe, desc,
- name_prefix=name_prefix, extra_desc='')
- unfinished_mark = '' if res.finished else ' *'
- tname += unfinished_mark
- if res.error == BestCodeResultError.success:
- print(' %s' % tname)
- print(' %s' % res.code)
- print(' R=%.6f, NPE=%s' % (res.reward, misc.int_to_si(res.npe)))
- elif res.error == BestCodeResultError.experiment_does_not_exist:
- print(' Experiment does not exist. Check arguments.')
- print(' Experiment folder: %s' % res.folder)
- break
- else:
- print(' %s' % tname)
- print(' (none)')
- sys.stdout.flush()
-
-
-if __name__ == '__main__':
- app.run(main)
diff --git a/research/brain_coder/single_task/aggregate_tuning_results.py b/research/brain_coder/single_task/aggregate_tuning_results.py
deleted file mode 100644
index bb2e008ce583afbea8acabfe1ed8ccf264698f5e..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/aggregate_tuning_results.py
+++ /dev/null
@@ -1,71 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-r"""After running tuning, use this script to aggregate the results.
-
-Usage:
-
-OUT_DIR=""
-bazel run -c opt single_task:aggregate_tuning_results -- \
- --alsologtostderr \
- --tuning_dir="$OUT_DIR"
-"""
-
-import ast
-import os
-
-from absl import app
-from absl import flags
-import tensorflow as tf
-
-
-FLAGS = flags.FLAGS
-flags.DEFINE_string(
- 'tuning_dir', '',
- 'Absolute path where results tuning trial folders are found.')
-
-
-def main(argv):
- del argv # Unused.
-
- try:
- trial_dirs = tf.gfile.ListDirectory(FLAGS.tuning_dir)
- except tf.errors.NotFoundError:
- print('Tuning directory %s does not exist.' % (FLAGS.tuning_dir,))
- return
-
- metrics = []
- for trial_dir in trial_dirs:
- tuning_results_file = os.path.join(
- FLAGS.tuning_dir, trial_dir, 'tuning_results.txt')
- if tf.gfile.Exists(tuning_results_file):
- with tf.gfile.FastGFile(tuning_results_file, 'r') as reader:
- for line in reader:
- metrics.append(ast.literal_eval(line.replace(': nan,', ': 0.0,')))
-
- if not metrics:
- print('No trials found.')
- return
-
- num_trials = [m['num_trials'] for m in metrics]
- assert all(n == num_trials[0] for n in num_trials)
- num_trials = num_trials[0]
- print('Found %d completed trials out of %d' % (len(metrics), num_trials))
-
- # Sort by objective descending.
- sorted_trials = sorted(metrics, key=lambda m: -m['objective'])
-
- for i, metrics in enumerate(sorted_trials):
- hparams = metrics['hparams']
- keys = sorted(hparams.keys())
- print(
- str(i).ljust(4) + ': '
- + '{0:.2f}'.format(metrics['objective']).ljust(10)
- + '['
- + ','.join(['{}={}'.format(k, hparams[k]).ljust(24) for k in keys])
- + ']')
-
-
-if __name__ == '__main__':
- app.run(main)
diff --git a/research/brain_coder/single_task/code_tasks.py b/research/brain_coder/single_task/code_tasks.py
deleted file mode 100644
index 27cc7ecd1c76f2d765692ce0a94acd1df04ff681..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/code_tasks.py
+++ /dev/null
@@ -1,1381 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Tasks for RL."""
-
-import abc
-import copy
-import itertools
-import random
-
-from absl import logging
-import numpy as np
-from six.moves import xrange
-
-from common import bf # brain coder
-from common import reward as r # brain coder
-from single_task import misc # brain coder
-from single_task import test_tasks # brain coder
-
-
-MAX_EXECUTION_STEPS = 5000
-
-
-def make_task(task_name, override_kwargs=None, max_code_length=100,
- require_correct_syntax=False,
- do_code_simplification=False,
- correct_bonus=2.0, code_length_bonus=1.0):
- """Make tasks with setting from paper."""
- logging.info('Making paper-config task.')
- n = 16 # Number of test cases.
- task_mapping = {
- 'print-hello': (
- PrintTask, dict(base=27, fixed_string=[8, 5, 12, 12, 15])),
- 'print': (PrintIntTask, dict(base=256, fixed_string=[1, 2, 3, 4, 5])),
- 'echo': (EchoTask, dict(base=27, min_length=1, max_length=6)),
- 'remove-char': (
- RemoveCharTask, dict(base=256, n=n, min_len=1, max_len=6)),
- 'reverse': (
- ReverseTask, dict(base=256, n=n, min_len=1, max_len=6)),
- 'reverse-tune': (
- ReverseTaskV2, dict(base=256, reward_type='static-bylen')),
- 'remove-char-tune': (RemoveCharTaskV2, dict(base=27)),
- 'prefix': (CommonPrefixTask, dict(base=27)),
- 'find': (FindSubStrTask, dict(base=27)),
- 'sort3': (SortFixedTaskV2, dict(base=27, n=150, length=3)),
- 'count-char': (CountCharTaskV2, dict(n=n, max_len=6)),
- 'bool-logic': (BooleanLogicTask, dict()),
- 'add': (AddTask, dict(n=9)),
- 'echo-twice': (EchoTwiceTask, dict(n=n)),
- 'echo-thrice': (EchoThriceTask, dict(n=n)),
- 'copy-reverse': (CopyReverseTask, dict(n=n)),
- 'zero-cascade': (EchoZeroCascadeTask, dict(n=n)),
- 'cascade': (EchoCascadeTask, dict(n=n)),
- 'shift-left': (ShiftLeftTask, dict(n=n)),
- 'shift-right': (ShiftRightTask, dict(n=n)),
- 'riffle': (RiffleTask, dict(n=n)),
- 'unriffle': (UnriffleTask, dict(n=n)),
- 'middle-char': (MiddleCharTask, dict(n=n)),
- 'remove-last': (RemoveLastTask, dict(n=n)),
- 'remove-last-two': (RemoveLastTwoTask, dict(n=n)),
- 'echo-alternating': (EchoAlternatingTask, dict(n=n)),
- 'echo-half': (EchoHalfTask, dict(n=n)),
- 'length': (LengthTask, dict(n=n)),
- 'echo-second-seq': (EchoSecondSequenceTask, dict(n=n)),
- 'echo-nth-seq': (EchoNthSequenceTask, dict(n=n)),
- 'substring': (SubstringTask, dict(n=n)),
- 'divide-2': (Divide2Task, dict(n=n)),
- 'dedup': (DedupTask, dict(n=n)),
- 'remove-target-char': (RemoveTargetCharTask, dict(n=n)),
- 'list-index': (ListIndexTask, dict(n=n)),
- 'fib': (FibonacciTask, dict()),
- 'count-down': (BottlesOfBeerTask, dict()),
- 'split': (SplitTask, dict()),
- 'trim-left': (TrimLeftTask, dict()),
- 'circle-route': (
- JudgeRouteCircleTask, dict(n=100, max_len=32)),
- 'multiply': (MultiplyTask, dict(n=100)),
- 'divmod': (DivModTask, dict(n=100)),
- }
-
- if task_name not in task_mapping:
- # Test tasks.
- if task_name == 'test-hill-climb':
- return test_tasks.BasicTaskManager(test_tasks.HillClimbingTask())
- raise ValueError('Unknown task type "%s"' % task_name)
- task_cls, kwargs = task_mapping[task_name]
-
- if override_kwargs:
- if not isinstance(override_kwargs, dict):
- raise ValueError(
- 'override_kwargs must be a dict, got: %s', override_kwargs)
- kwargs.update(override_kwargs)
-
- task = task_cls(**kwargs)
-
- reward_fn = r.absolute_distance_reward
- # reward_fn = r.absolute_mod_distance_reward
- # reward_fn = r.absolute_log_distance_reward
- logging.info('Using reward function: %s', reward_fn.__name__)
-
- # We want reward with and without code simplification to be scaled the same
- # way. Without code simplification, give the maximum code length bonus
- # every time.
- min_code_length = 0.0 if do_code_simplification else max_code_length
-
- return MultiIOTaskManager(
- task=task, correct_bonus=correct_bonus,
- code_length_bonus=code_length_bonus,
- max_code_length=max_code_length, min_code_length=min_code_length,
- reward_fn=reward_fn, require_correct_syntax=require_correct_syntax)
-
-
-def concat(lists):
- if not lists:
- return []
- l = lists[0]
- for k in lists[1:]:
- l += k
- return l
-
-
-def concat_join(lists, sep):
- if not lists:
- return []
- l = lists[0]
- for k in lists[1:]:
- l += [sep] + k
- return l
-
-
-def clipped_linear(x, x0, y0, slope, y_range):
- min_y, max_y = y_range
- return min(max(slope * (x - x0) + y0, min_y), max_y)
-
-
-class MultiIOTaskManager(object):
- """Supports tasks which test the code with multiple I/O examples."""
-
- def __init__(self, task, max_code_length=32, min_code_length=0,
- max_execution_steps=MAX_EXECUTION_STEPS, correct_bonus=1.0,
- code_length_bonus=1.0, failure_reward=-2.0, reward_fn=None,
- require_correct_syntax=False):
- assert isinstance(task, BaseTask)
- self.task = task
- self.max_code_length = max_code_length
- self.min_code_length = min_code_length
- self.max_execution_steps = max_execution_steps
- self.require_correct_syntax = require_correct_syntax
- self.correct_bonus = correct_bonus
- self.code_length_bonus = code_length_bonus
- self.failure_reward = failure_reward
- self.time_penalty = (
- 1.0 / (max_code_length - min_code_length)
- if max_code_length > min_code_length else 0.0)
- if reward_fn is None:
- self.reward_fn = r.absolute_distance_reward
- else:
- self.reward_fn = reward_fn
- self.input_type = (
- task.input_type if hasattr(task, 'input_type') else misc.IOType.integer)
- self.output_type = (
- task.output_type if hasattr(task, 'output_type')
- else misc.IOType.integer)
- self._compute_best_reward()
-
- def _compute_best_reward(self):
- io_seqs = self.task.make_io_set()
- reward = 0.0
- for _, output_seq in io_seqs:
- reward += self.reward_fn(output_seq, output_seq, self.task.base)
- reward += self.correct_bonus
- reward += self.code_length_bonus # Bonus for shortest code.
- self.best_reward = reward
- self.good_reward = 0.75 * reward
- logging.info('Known best reward: %.4f', self.best_reward)
-
- def _score_batch(self, code_strings):
- return [self._score_code(code) for code in code_strings]
-
- def _score_code(self, code):
- """Run test cases on code and compute reward.
-
- Args:
- code: A single BF code string.
-
- Returns:
- misc.RewardInfo namedtuple instance containing reward and code execution
- information, including inputs, expected outputs, code outputs, input
- and output types, and reason for the reward obtained.
- """
- # Get list of 2-tuples, each containing an input sequence and an output
- # sequence.
- io_seqs = self.task.make_io_set()
- terminal_reward = 0.0
- results = []
- reason = 'correct'
- for input_seq, output_seq in io_seqs:
- eval_result = bf.evaluate(
- code, input_buffer=input_seq, timeout=0.1,
- max_steps=self.max_execution_steps,
- base=self.task.base,
- require_correct_syntax=self.require_correct_syntax)
- result, success = eval_result.output, eval_result.success
- if not success:
- # Code execution timed out.
- terminal_reward = self.failure_reward
- results = []
- reason = eval_result.failure_reason
- break
- else:
- terminal_reward += self.reward_fn(result, output_seq, self.task.base)
- if result == output_seq:
- terminal_reward += self.correct_bonus # Bonus for correct answer.
-
- # Only add additional reward for shorter code. Subtracting reward
- # interferes with the main objective. Only optimize for length once
- # any solution is found.
- if self.min_code_length == self.max_code_length:
- terminal_reward += self.code_length_bonus
- else:
- terminal_reward += self.code_length_bonus * clipped_linear(
- x=len(code), x0=self.min_code_length, y0=1.0,
- slope=-self.time_penalty, y_range=(0.0, 1.0))
-
- # reason remains 'correct' if it is already
- elif reason == 'correct':
- reason = 'wrong'
- results.append(result)
-
- # Return list of rewards, one for each char in the code. All are 0 except
- # for the terminal reward.
- terminal_reward /= self.best_reward
- return misc.RewardInfo(
- episode_rewards=[0.0] * (len(code) - 1) + [terminal_reward],
- input_case=misc.IOTuple(i for i, o in io_seqs),
- correct_output=misc.IOTuple(o for i, o in io_seqs),
- code_output=misc.IOTuple(results),
- input_type=self.input_type,
- output_type=self.output_type,
- reason=reason)
-
- def rl_batch(self, batch_size):
- """Produces list of reward functions. One for each program in the batch."""
- return [self._score_code] * batch_size
-
-
-def conditional_overwrite(current_value, new_value, allowed_overwrite_values):
- if current_value in allowed_overwrite_values:
- return new_value
- return current_value
-
-
-class BaseTask(object):
- """A coding task.
-
- All coding tasks should inherit this class.
- """
- __metaclass__ = abc.ABCMeta
-
- def __init__(self, base=256):
- self.base = base # All tasks must set the integer base that the expect.
-
- @abc.abstractmethod
- def make_io_set(self):
- """Generate a set of test cases for the task.
-
- Returns:
- List of tuples, where each tuple is (input_case, output_case).
- input_case and output_case are lists of integers.
- """
- pass
-
-
-# ==============================================================================
-# ICLR tasks.
-# ==============================================================================
-
-
-class PrintTask(BaseTask):
- """Print string coding task.
-
- Code needs to output a fixed string (given as a hyperparameter to the
- task constructor). Program input is ignored.
- """
-
- def __init__(self, base, fixed_string=None):
- super(type(self), self).__init__()
- self.base = base # base includes EOS
- self.eos = 0
- if fixed_string:
- self.fixed_string = fixed_string
- else:
- self.fixed_string = [1, 2, 3, 0] # ABC
- self.min_length = self.max_length = len(self.fixed_string)
-
- def make_io_set(self):
- return [(list(), list(self.fixed_string))]
-
-
-class RemoveCharTaskV2(BaseTask):
- """Remove character coding task (version 2).
-
- Code needs to pipe input to output, but with all the 'A' (value 1) chars
- removed. 'A' appears exactly once in each input.
-
- Test cases are hard-coded.
- """
-
- def __init__(self, base):
- super(type(self), self).__init__()
- self.base = base
- self.eos = 0
- self.remove_char = 1
- assert base >= 27
-
- def make_io_set(self):
- rm = self.remove_char
- return [
- ([rm, 0], [0]),
- ([20, rm, 0], [20, 0]),
- ([rm, 13, 0], [13, 0]),
- ([6, rm, 17, 0], [6, 17, 0]),
- ([rm, 11, 24, 0], [11, 24, 0]),
- ([2, 16, 21, rm, 0], [2, 16, 21, 0]),
- ([18, rm, 12, 26, 7, 0], [18, 12, 26, 7, 0]),
- ([9, 10, 22, rm, 4, 0], [9, 10, 22, 4, 0])]
-
-
-class RemoveCharTask(BaseTask):
- """Remove character coding task.
-
- Code needs to pipe input to output, but with all the 'A' (value 1) chars
- removed. 'A' appears at least once in each input.
-
- Test cases are dynamically generated, allowing for the number of test cases
- to be a hyperparameter.
- """
-
- def __init__(self, base, n, min_len, max_len):
- super(type(self), self).__init__()
- self.base = base
- self.eos = 0
- self.remove_char = 1
- assert base >= 27
- self._io_pairs = self._make_io_examples(n, min_len, max_len)
-
- def _make_io_examples(self, n, min_len, max_len):
- """Generate test cases for the task."""
- rand = random.Random(6849275409234) # Test cases are fixed, but varied.
- io_examples = []
- for _ in xrange(n):
- length = rand.randrange(min_len, max_len + 1)
- rm_char_pos = rand.randrange(0, length)
- input_seq = [rand.randrange(1, self.base) for _ in xrange(length)]
- input_seq[rm_char_pos] = self.remove_char
- output_seq = list(input_seq)
- del output_seq[rm_char_pos]
- output_seq.append(0)
- io_examples.append((input_seq, output_seq))
- return io_examples
-
- def make_io_set(self):
- return copy.deepcopy(self._io_pairs)
-
-
-class ReverseTaskV2(BaseTask):
- """Reverse string coding task (version 2).
-
- Code needs to pipe input to output, but in reverse order.
-
- Stochastic test case = new test case randomly generated for every run of
- `make_io_set`, i.e. different test cases every time code is scored.
-
- Task supports different types of test cases:
- rand-one: Code is scored on one stochastic test case.
- rand-many: Code is scored on 5 stochastic test cases.
- static-bylen: Code is scored on 5 static test cases. There is one test
- case for string lengths 1 through 5.
- rand-bylen: Code is scored on 5 stochastic test cases, where there is one
- test case for string lengths 1 through 5.
- """
-
- def __init__(self, base, reward_type):
- super(type(self), self).__init__()
- self.base = base # base includes EOS
- assert base >= 27
- self.eos = 0
- self.io_pair_fn = {
- # One random example at a time.
- 'rand-one': lambda: self._io_rand(1),
- # K randomy examples at a time (any lengths).
- 'rand-many': lambda: self._io_rand(5),
- # Static examples, one for each length.
- 'static-bylen': self._io_static_by_len,
- # Random examples, one for each length.
- 'rand-bylen': self._io_rand_by_len}[reward_type]
-
- def _make_io_examples(self, sequences):
- outputs = [list(i) for i in sequences]
- for o in outputs:
- o.reverse()
- o.append(0)
- inputs = [i + [0] for i in sequences]
- return zip(inputs, outputs)
-
- def _io_rand(self, k):
- inputs = [(np.random.choice(26, random.randrange(1, 6)) + 1).tolist()
- for _ in xrange(k)]
- return self._make_io_examples(inputs)
-
- def _io_rand_by_len(self, k=5):
- inputs = [(np.random.choice(26, length) + 1).tolist()
- for length in xrange(1, k + 1)]
- return self._make_io_examples(inputs)
-
- def _io_static_by_len(self):
- return [
- ([7, 0], [7, 0]),
- ([6, 2, 0], [2, 6, 0]),
- ([5, 1, 10, 0], [10, 1, 5, 0]),
- ([8, 6, 5, 15, 0], [15, 5, 6, 8, 0]),
- ([10, 12, 5, 2, 7, 0], [7, 2, 5, 12, 10, 0])]
-
- def make_io_set(self):
- return self.io_pair_fn()
-
-
-class ReverseTask(BaseTask):
- """Reverse string coding task.
-
- Code needs to pipe input to output, but in reverse order.
-
- Test cases are dynamically generated, allowing for the number of test cases
- to be a hyperparameter.
- """
-
- def __init__(self, base, n, min_len, max_len):
- super(type(self), self).__init__()
- self.base = base # base includes EOS
- assert base >= 27
- self.eos = 0
- self._io_pairs = self._make_io_examples(n, min_len, max_len)
-
- def _make_io_examples(self, n, min_len, max_len):
- """Generate test cases for the task."""
- rand = random.Random(6849275409234) # Test cases are fixed, but varied.
- io_examples = []
- for _ in xrange(n):
- length = rand.randrange(min_len, max_len + 1)
- input_seq = [rand.randrange(1, self.base) for _ in xrange(length)]
- output_seq = list(input_seq)
- output_seq.reverse()
- output_seq.append(0)
- io_examples.append((input_seq, output_seq))
- return io_examples
-
- def make_io_set(self):
- return copy.deepcopy(self._io_pairs)
-
-
-class CommonPrefixTask(BaseTask):
- """Common prefix coding task.
-
- Code needs to output the common prefix between two input lists. Input lists
- are variable length, where each list ends with a 0. A common prefix is a
- sequence which both lists start with.
- """
-
- def __init__(self, base):
- super(type(self), self).__init__()
- assert base >= 27
- self.base = base
- self.eos = 0
-
- def make_io_set(self):
- return [
- ([12, 24, 18, 0, 12, 5, 0], [12, 0]),
- ([1, 2, 3, 0, 1, 2, 17, 14, 0], [1, 2, 0]),
- ([15, 2, 1, 9, 2, 0, 15, 2, 1, 25, 8, 14, 0], [15, 2, 1, 0]),
- ([14, 9, 7, 8, 6, 16, 0, 14, 9, 7, 8, 8, 6, 8, 26, 0],
- [14, 9, 7, 8, 0]),
- ([12, 4, 16, 22, 1, 17, 0, 12, 4, 16, 22, 1, 8, 10, 0],
- [12, 4, 16, 22, 1, 0])]
-
-
-class CountCharTask(BaseTask):
-
- def __init__(self):
- super(type(self), self).__init__()
- self.base = 27
- self.eos = 0
- self.char = 1
- self.input_type = misc.IOType.string
- self.output_type = misc.IOType.integer
-
- def make_io_set(self):
- return [
- ([10, 0], [0]),
- ([1, 0], [1]),
- ([1, 1, 0], [2]),
- ([11, 1, 0], [1]),
- ([1, 24, 0], [1]),
- ([13, 6, 0], [0]),
- ([9, 2, 7, 0], [0]),
- ([1, 24, 11, 0], [1]),
- ([19, 1, 1, 0], [2]),
- ([1, 6, 1, 0], [2]),
- ([22, 16, 17, 9, 0], [0]),
- ([1, 1, 1, 19, 0], [3]),
- ([1, 1, 1, 1, 0], [4]),
- ([9, 4, 19, 11, 5, 0], [0]),
- ([24, 11, 26, 1, 15, 0], [1]),
- ([1, 1, 20, 1, 1, 0], [4]),
- ([1, 1, 1, 1, 1, 0], [5])]
-
-
-class CountCharTaskV2(BaseTask):
- """Count char coding task (version 2).
-
- Code must output the number of occurances of character 'A' (value 1) in an
- input string.
-
- Test cases are dynamically generated, allowing for the number of test cases
- to be a hyperparameter.
- """
-
- def __init__(self, n, max_len):
- super(type(self), self).__init__()
- self.base = 27
- self.eos = 0
- self.char = 1
- self.other_chars = [c for c in xrange(self.base)
- if c not in (self.eos, self.char)]
- self.input_type = misc.IOType.string
- self.output_type = misc.IOType.integer
- self._io_pairs = self._make_io_examples(n, max_len)
-
- def _make_io_examples(self, n, max_len):
- """Generate test cases for the task."""
- rand = random.Random(6849275409234) # Test cases are fixed, but varied.
- io_examples = []
- io_examples.append(([10, 0], [0]))
- io_examples.append(([1, 0], [1]))
- io_examples.append(([1, 1, 0], [2]))
- io_examples.append(([9, 4, 19, 11, 5, 0], [0]))
- io_examples.append(([24, 11, 26, 1, 15, 0], [1]))
- for _ in xrange(n - 5):
- length = rand.randrange(2, max_len + 1)
- num_chars = rand.randrange(0, max_len + 1)
- input_seq = [self.char] * num_chars + [0] * (length - num_chars)
- rand.shuffle(input_seq)
- for i in xrange(len(input_seq)):
- if not input_seq[i]:
- input_seq[i] = self.other_chars[rand.randrange(len(self.other_chars))]
- output_seq = [num_chars]
- io_examples.append((input_seq, output_seq))
- return io_examples
-
- def make_io_set(self):
- return copy.deepcopy(self._io_pairs)
-
-
-class AddTask(BaseTask):
- """Addition coding task.
-
- Code needs to read in two integers and output their sum mod the BF base,
- followed by a terminating 0.
- """
-
- def __init__(self, n=16):
- super(type(self), self).__init__()
- self.base = 256
- self.input_type = misc.IOType.integer
- self.output_type = misc.IOType.integer
- self._io_pairs = self._make_io_examples(n)
-
- def _make_io_examples(self, n):
- """Generate test cases for the task."""
- rand = random.Random(6849275409234) # Test cases are fixed, but varied.
- io_examples = [
- ([4, 0], [4, 0]),
- ([0, 5], [5, 0]),
- ([1, 2], [3, 0]),
- ([67, 21], [88, 0]),
- ([55, 56], [111, 0]),
- ([128, 33], [161, 0]),
- ([221, 251], [216, 0]),
- ([130, 127], [1, 0]),
- ([255, 1], [0, 0])]
- extra_examples = max(n - len(io_examples), 0)
- for _ in xrange(extra_examples):
- a = rand.randrange(256)
- b = rand.randrange(256)
- input_seq = [a, b]
- output_seq = [(a + b) % 256, 0]
- io_examples.append((input_seq, output_seq))
- return io_examples
-
- def make_io_set(self):
- return copy.deepcopy(self._io_pairs)
-
-
-class BooleanLogicTask(BaseTask):
- """Boolean logic (truth table) coding task.
-
- Code needs to memorize a boolean truth table. Specifically, it must encode a
- mapping from triple of bools to a single bool.
- """
-
- def __init__(self):
- super(type(self), self).__init__()
- self.base = 2
- self.input_type = misc.IOType.boolean
- self.output_type = misc.IOType.boolean
- # X(~Z) + (~Y)(~Z) + (~X)YZ
- self._truth_fn = (
- lambda x, y, z: # pylint: disable=g-long-lambda
- (x and not z) or (not y and not z) or (not x and y and z))
- self._test_cases = [
- ([x, y, z], [int(self._truth_fn(x, y, z))])
- for x, y, z in itertools.product(range(2), range(2), range(2))]
-
- def make_io_set(self):
- return copy.deepcopy(self._test_cases)
-
-
-# ------------------------------------------------------------------------------
-# The following tasks are generated from known BF solutions. This guarantees
-# that each task can be solved within the maximum code length, and maximum
-# execution steps.
-# ------------------------------------------------------------------------------
-
-
-def default_input_fn_factory(min_length=1, max_length=6, base=256):
- def _input_gen(rand):
- l = rand.randrange(min_length, max_length + 1)
- return [rand.randrange(base) for _ in xrange(l)]
- return _input_gen
-
-
-class KnownCodeBaseTask(BaseTask):
- """These tasks generate their test cases from a known BF solution.
-
- This ensures that each task has a solution which is under the max character
- length, and that it solves the test cases under the max number of execution
- steps.
- """
-
- def __init__(self, code_solution, make_input_fn, n=100, base=256,
- max_steps=5000, seed=6849275409234):
- super(KnownCodeBaseTask, self).__init__()
- # Make sure known solution is less than the code length used in experiments.
- assert len(code_solution) < 100
- self.code_solution = code_solution
- self.make_input_fn = make_input_fn
- self.n = n
- self.base = base
- self.max_steps = max_steps
- self.seed = seed
- self._test_cases = list(self._test_case_generator(code_solution))
-
- def _test_case_generator(self, code_solution):
- rand = random.Random(self.seed)
- for _ in xrange(self.n):
- input_case = self.make_input_fn(rand)
- result = bf.evaluate(
- code_solution, input_buffer=input_case, max_steps=self.max_steps,
- base=self.base, require_correct_syntax=False)
- if not result.success:
- raise RuntimeError(
- 'Program must succeed. Failed on input: %s' % input_case)
- yield input_case, result.output
-
- def make_io_set(self):
- return copy.deepcopy(self._test_cases)
-
-
-class EchoTwiceTask(KnownCodeBaseTask):
- """Echo twice."""
-
- def __init__(self, **kwargs):
- super(type(self), self).__init__(
- '>,.[>,.]<[<]>[.>].',
- default_input_fn_factory(),
- **kwargs)
-
-
-class EchoThriceTask(KnownCodeBaseTask):
- """Echo three times."""
-
- def __init__(self, **kwargs):
- super(type(self), self).__init__(
- '>,.[>,.]<[<]>[.>].<[<]>[.>].',
- default_input_fn_factory(),
- **kwargs)
-
-
-class CopyReverseTask(KnownCodeBaseTask):
- """Echo forwards, backwards, and then forwards again."""
-
- def __init__(self, **kwargs):
- super(type(self), self).__init__(
- '>,.[>,.]<[.<].>[.>].',
- default_input_fn_factory(),
- **kwargs)
-
-
-class EchoZeroCascadeTask(KnownCodeBaseTask):
- """Print k-th char with k zeros inbetween (1-indexed)."""
-
- def __init__(self, **kwargs):
- super(type(self), self).__init__(
- ',[.>[->+>.<<]>+[-<+>]<<,]',
- default_input_fn_factory(),
- **kwargs)
-
-
-class EchoCascadeTask(KnownCodeBaseTask):
- """Print k-th char k times (1-indexed)."""
-
- def __init__(self, **kwargs):
- super(type(self), self).__init__(
- ',>>+<<[>>[-<+>]<[->+<<.>]>+<<,].',
- default_input_fn_factory(base=20),
- **kwargs)
-
-
-class ShiftLeftTask(KnownCodeBaseTask):
- """Circulate shift input left."""
-
- def __init__(self, **kwargs):
- super(type(self), self).__init__(
- ',>,[.,]<.,.',
- default_input_fn_factory(),
- **kwargs)
-
-
-class ShiftRightTask(KnownCodeBaseTask):
- """Circular shift input right."""
-
- def __init__(self, **kwargs):
- super(type(self), self).__init__(
- '>,[>,]<.[-]<[<]>[.>].',
- default_input_fn_factory(),
- **kwargs)
-
-
-class RiffleTask(KnownCodeBaseTask):
- """Shuffle like a deck of cards.
-
- For input of length N, output values in the following index order:
- N-1, 0, N-2, 1, N-3, 2, ...
- """
-
- def __init__(self, **kwargs):
- super(type(self), self).__init__(
- '>,[>,]<[.[-]<[<]>.[-]>[>]<]',
- default_input_fn_factory(base=20, max_length=8),
- **kwargs)
-
-
-class UnriffleTask(KnownCodeBaseTask):
- """Inverse of riffle."""
-
- def __init__(self, **kwargs):
- super(type(self), self).__init__(
- '>,[>,[.[-]],]<[.<].',
- default_input_fn_factory(base=20, max_length=8),
- **kwargs)
-
-
-class MiddleCharTask(KnownCodeBaseTask):
- """Print middle char if length is odd, or 0 if even."""
-
- def __init__(self, **kwargs):
- super(type(self), self).__init__(
- '>,[>,]<<[[>]<[,<[<]>,>[>]][>]<<]>.',
- default_input_fn_factory(max_length=10),
- **kwargs)
-
-
-class RemoveLastTask(KnownCodeBaseTask):
- """Remove last character."""
-
- def __init__(self, **kwargs):
- super(type(self), self).__init__(
- ',>,[[<.[-]>[-<+>]],].',
- default_input_fn_factory(base=20),
- **kwargs)
-
-
-class RemoveLastTwoTask(KnownCodeBaseTask):
- """Remove last two characters."""
-
- def __init__(self, **kwargs):
- super(type(self), self).__init__(
- ',>,>,[[<<.[-]>[-<+>]>[-<+>]],].',
- default_input_fn_factory(base=10),
- **kwargs)
-
-
-class EchoAlternatingTask(KnownCodeBaseTask):
- # Print even numbered chars first (0-indexed), then odd numbered chars
-
- def __init__(self, **kwargs):
- super(type(self), self).__init__(
- '>,[.,>,]<<[<]>[.>].',
- default_input_fn_factory(base=20, max_length=8),
- **kwargs)
-
-
-class EchoHalfTask(KnownCodeBaseTask):
- """Echo only first half of the input (round down when odd lengthed)."""
-
- def __init__(self, **kwargs):
- super(type(self), self).__init__(
- '>>+>,[[<]>+[>],]<[<]>-[-[-<<+>]<[>]>]<<[->+<]>[[>]>.,<+[<]>-].',
- default_input_fn_factory(base=20, max_length=9),
- **kwargs)
-
-
-class LengthTask(KnownCodeBaseTask):
- """Print length of the input sequence."""
-
- def __init__(self, **kwargs):
- super(type(self), self).__init__(
- '>+>,[[<]>+[>],]<[<]>-.',
- default_input_fn_factory(max_length=14),
- **kwargs)
-
-
-class EchoSecondSequenceTask(KnownCodeBaseTask):
- """Echo second sequence. Sequences are separated by 0."""
-
- def __init__(self, **kwargs):
- def echo_second_gen(rand):
- l = rand.randrange(1, 6)
- x = [rand.randrange(256) for _ in xrange(l)]
- l = rand.randrange(1, 6)
- y = [rand.randrange(256) for _ in xrange(l)]
- return x + [0] + y + [0]
- super(type(self), self).__init__(
- ',[,],[.,].',
- echo_second_gen,
- **kwargs)
-
-
-class EchoNthSequenceTask(KnownCodeBaseTask):
- """Echo n-th sequence (1-indexed). Sequences are separated by 0."""
-
- def __init__(self, **kwargs):
- def echo_nth_gen(rand):
- k = rand.randrange(1, 7)
- n = rand.randrange(1, k + 1)
- x = []
- for _ in xrange(k):
- l = rand.randrange(0, 4)
- x += [rand.randrange(256) for _ in xrange(l)] + [0]
- return [n] + x
- super(type(self), self).__init__(
- ',-[->,[,]<],[.,].',
- echo_nth_gen,
- **kwargs)
-
-
-class SubstringTask(KnownCodeBaseTask):
- """Echo substring.
-
- First two inputs are i and l, where i is the starting index (0-indexed)
- and l is the length of the substring.
- """
-
- def __init__(self, **kwargs):
- def substring_gen(rand):
- l = rand.randrange(2, 16)
- i, j = sorted([rand.randrange(l), rand.randrange(l)])
- n = j - i
- x = [rand.randrange(256) for _ in xrange(l)] + [0]
- return [i, n] + x
- super(type(self), self).__init__(
- '>,<,>[->,<]>,<<[->>.,<<]',
- substring_gen,
- **kwargs)
-
-
-class Divide2Task(KnownCodeBaseTask):
- """Divide by 2 (integer floor division)."""
-
- def __init__(self, **kwargs):
- def int_input_gen(rand):
- return [rand.randrange(256)]
- super(type(self), self).__init__(
- ',[-[->>+<]>[<]<]>>.',
- int_input_gen,
- **kwargs)
-
-
-class DedupTask(KnownCodeBaseTask):
- """Deduplicate adjacent duplicate chars."""
-
- def __init__(self, **kwargs):
- def dedup_input_gen(rand):
- np_random = np.random.RandomState(rand.randrange(2147483647))
- num_unique = rand.randrange(1, 5)
- unique = np_random.choice(6, num_unique, replace=False) + 1
- return [v for v in unique for _ in xrange(rand.randrange(1, 5))] + [0]
- super(type(self), self).__init__(
- '>>,.[[-<+<+>>],[-<->]<[[-<->]<.>]<[->>+<<]>>]',
- dedup_input_gen,
- **kwargs)
-
-
-# ==============================================================================
-# Extra tasks.
-# ==============================================================================
-
-
-class PrintIntTask(BaseTask):
- """Print integer coding task.
-
- Code needs to output a fixed single value (given as a hyperparameter to the
- task constructor). Program input is ignored.
- """
-
- def __init__(self, base, fixed_string):
- super(type(self), self).__init__()
- self.base = base
- self.eos = 0
- self.fixed_string = fixed_string
- self.input_type = misc.IOType.integer
- self.output_type = misc.IOType.integer
-
- def make_io_set(self):
- return [(list(), list(self.fixed_string))]
-
-
-class EchoTask(BaseTask):
- """Echo string coding task.
-
- Code needs to pipe input to putput (without any modifications).
- """
-
- def __init__(self, base, min_length=1, max_length=5):
- super(type(self), self).__init__()
- self.base = base # base includes EOS
- self.eos = 0
- self.min_length = min_length
- self.max_length = max_length
- self._io_pairs = self._make_io_examples(25)
-
- def _make_io_examples(self, n):
- # Test cases are fixed, but varied.
- np_random = np.random.RandomState(1234567890)
- io_pairs = []
- for _ in xrange(n):
- length = np_random.randint(self.min_length, self.max_length + 1)
- input_seq = np_random.randint(1, self.base, length).tolist() + [self.eos]
- output_seq = list(input_seq)
- io_pairs.append((input_seq, output_seq))
- return io_pairs
-
- def make_io_set(self):
- return copy.deepcopy(self._io_pairs)
-
-
-class JudgeRouteCircleTask(BaseTask):
- """Judge route circle coding task.
-
- Code needs to determine if the given route makes a closed loop.
- Encoding: U = 1, R = 2, D = 3, L = 4.
-
- Based on
- https://leetcode.com/problems/judge-route-circle/description/
- """
- base = 256
- input_type = misc.IOType.integer
- output_type = misc.IOType.integer
-
- def __init__(self, n, max_len=12):
- super(type(self), self).__init__()
- self.eos = 0
- self._io_pairs = self._make_io_examples(n, max_len)
- self.input_type = misc.IOType.integer
- self.output_type = misc.IOType.integer
-
- def _solve(self, input_seq):
- assert input_seq[-1] == 0
- pos = [0, 0] # (x, y)
- for move in input_seq[:-1]:
- assert 0 < move <= 4
- if move & 1 == 0: # Left or Right.
- pos[0] += 3 - move # Add or subtract 1.
- else:
- pos[1] += 2 - move # Add or subtract 1.
- return [int(not pos[0] and not pos[1])]
-
- def _make_io_examples(self, n, max_len):
- """Generate test cases for the task."""
- rand = random.Random(6849275409234) # Test cases are fixed, but varied.
- io_examples = []
- io_examples.append(([0], [1]))
- io_examples.append(([4, 2, 0], [1]))
- io_examples.append(([2, 4, 0], [1]))
- io_examples.append(([3, 1, 0], [1]))
- io_examples.append(([1, 3, 0], [1]))
- io_examples.append(([1, 0], [0]))
- io_examples.append(([2, 0], [0]))
- io_examples.append(([3, 0], [0]))
- io_examples.append(([4, 0], [0]))
- for _ in xrange(n):
- is_true = rand.randrange(2)
- length = rand.randrange(1, max_len + 1)
- if is_true:
- # Make a true case.
- length = (length >> 1) << 1 # Make even.
- partition = (rand.randrange(length + 1) >> 1) << 1
- a = partition >> 1
- b = (length - partition) >> 1
- counts = {1: a, 2: b, 3: a, 4: b}
- else:
- # Make a false case.
- partitions = (
- [0]
- + sorted([rand.randrange(length + 1) for _ in range(3)])
- + [length])
- counts = {n: partitions[n] - partitions[n - 1] for n in range(1, 5)}
- if counts[1] == counts[3] and counts[2] == counts[4]:
- # By chance we sampled a true case. Make it false by exchanging
- # one count between even and odd pairs.
- base = 1 + 2 * rand.randrange(2)
- a, b = (base, base + 1) if rand.randrange(2) else (base + 1, base)
- if counts[a] == length or counts[b] == 0:
- # If counts are at their extreme values, then swap who gets
- # incremented and decremented.
- a, b = b, a
- counts[a] += 1
- counts[b] -= 1
- assert counts[a] <= length and counts[b] >= 0
- assert sum(counts.values()) == length
- input_seq = [n for n in xrange(1, 5) for _ in xrange(counts[n])]
- rand.shuffle(input_seq)
- input_seq += [0]
- output_seq = self._solve(input_seq)
- assert output_seq[0] == is_true
- io_examples.append((input_seq, output_seq))
- return io_examples
-
- def make_io_set(self):
- return copy.deepcopy(self._io_pairs)
-
-
-class MultiplyTask(BaseTask):
- """Multiply coding task.
-
- Code needs to multiple two ints.
-
- Solution:
- http://robl.co/brief-look-at-brainfuck/
- ,>,><<[->[->+>+<<]>>[-<<+>>]<<<]>>.
- """
- base = 512
- input_type = misc.IOType.integer
- output_type = misc.IOType.integer
-
- def __init__(self, n):
- super(type(self), self).__init__()
- self.eos = 0
- self._io_pairs = self._make_io_examples(n)
- self.input_type = misc.IOType.integer
- self.output_type = misc.IOType.integer
-
- def _factors(self, n):
- return set(i for i in range(1, int(n**0.5) + 1) if n % i == 0)
-
- def _make_io_examples(self, n):
- """Generate test cases for the task."""
- rand = random.Random(6849275409234) # Test cases are fixed, but varied.
- io_examples = []
- for _ in xrange(n):
- n = rand.randrange(self.base)
- if n == 0:
- a, b = 0, rand.randrange(self.base)
- else:
- f = list(self._factors(n))
- a = f[rand.randrange(len(f))]
- b = n // a
- if rand.randrange(2):
- a, b = b, a
- io_examples.append(([a, b], [n]))
- return io_examples
-
- def make_io_set(self):
- return copy.deepcopy(self._io_pairs)
-
-
-class DivModTask(BaseTask):
- """Divmod coding task.
-
- Code needs to take the quotient and remainder of two ints.
-
- Solution:
- http://robl.co/brief-look-at-brainfuck/
- ,>,><<[>[->+>+<<]>[-<<-[>]>>>[<[-<->]<[>]>>[[-]>>+<]>-<]<<]>>>+<<[-<<+>>]<<<]>
- >>>>[-<<<<<+>>>>>]<<<<<.>.>
- """
- base = 512
- input_type = misc.IOType.integer
- output_type = misc.IOType.integer
-
- def __init__(self, n):
- super(type(self), self).__init__()
- self.eos = 0
- self._io_pairs = self._make_io_examples(n)
- self.input_type = misc.IOType.integer
- self.output_type = misc.IOType.integer
-
- def _make_io_examples(self, n):
- rand = random.Random(6849275409234) # Test cases are fixed, but varied.
- io_examples = []
- for _ in xrange(n):
- n = rand.randrange(0, self.base)
- k = rand.randrange(1, self.base) # Divisor cannot be 0.
- io_examples.append(([n, k], list(divmod(n, k))))
- return io_examples
-
- def make_io_set(self):
- return copy.deepcopy(self._io_pairs)
-
-
-class FibonacciTask(BaseTask):
-
- def __init__(self):
- super(type(self), self).__init__()
- self.base = 256
- self.input_type = misc.IOType.integer
- self.output_type = misc.IOType.integer
-
- def make_io_set(self):
- return [
- ([0], [0, 1]),
- ([1], [1, 1]),
- ([2], [1, 2]),
- ([3], [2, 3]),
- ([4], [3, 5]),
- ([5], [5, 8]),
- ([6], [8, 13]),
- ([7], [13, 21]),
- ([8], [21, 34]),
- ([9], [34, 55]),
- ([10], [55, 89]),
- ([11], [89, 144]),
- ([12], [144, 233]),
- ([13], [233, 121])]
-
-
-class FindSubStrTask(BaseTask):
- """Find sub-string coding task.
-
- Code needs to output a bool: True if the input string contains a hard-coded
- substring, 'AB' (values [1, 2]).
- """
-
- def __init__(self, base):
- super(type(self), self).__init__()
- assert base >= 27
- self.base = base
- self.eos = 0
- self.find_str = [1, 2]
- self.input_type = misc.IOType.string
- self.output_type = misc.IOType.boolean
-
- def make_io_set(self):
- return [
- ([1, 1, 23, 0], [0]),
- ([21, 3, 2, 0], [0]),
- ([2, 1, 19, 0], [0]),
- ([2, 24, 15, 3, 0], [0]),
- ([24, 6, 10, 16, 4, 0], [0]),
- ([1, 2, 12, 0], [1]),
- ([7, 1, 2, 0], [1]),
- ([1, 2, 11, 3, 0], [1]),
- ([1, 1, 2, 18, 0], [1]),
- ([7, 25, 1, 2, 0], [1]),
- ([3, 1, 2, 11, 8, 0], [1]),
- ([15, 16, 20, 1, 2, 0], [1])]
-
-
-class SortFixedTask(BaseTask):
- """Sort list coding task.
-
- Code needs to output a sorted input list. The task consists of lists of the
- same length L, where L is provided to this task's constructor as a
- hyperparameter.
- """
-
- def __init__(self, base, length=3):
- super(type(self), self).__init__()
- assert base >= 27
- self.base = base
- self.eos = 0
- self.length = length
- assert length == 3 # More lengths will be supported.
-
- def make_io_set(self):
- if self.length == 3:
- return [
- ([1, 20, 6], [1, 6, 20]),
- ([13, 6, 7], [6, 7, 13]),
- ([24, 2, 23], [2, 23, 24]),
- ([16, 12, 3], [3, 12, 16]),
- ([11, 24, 4], [4, 11, 24]),
- ([10, 1, 19], [1, 10, 19])]
-
-
-class SortFixedTaskV2(BaseTask):
- """Sort list coding task (version 2).
-
- Code needs to output a sorted input list. The task consists of lists of the
- same length L, where L is provided to this task's constructor as a
- hyperparameter.
-
- Test cases are dynamically generated, allowing for the number of test cases
- to be a hyperparameter.
- """
-
- def __init__(self, base, n, length=3):
- super(type(self), self).__init__()
- assert base >= 27
- self.base = base
- self.eos = 0
- self._io_pairs = self._make_io_examples(n, length)
- self.input_type = misc.IOType.integer
- self.output_type = misc.IOType.integer
-
- def _make_io_examples(self, n, length):
- rand = random.Random(6849275409234) # Test cases are fixed, but varied.
- io_examples = []
- for _ in xrange(n):
- input_seq = [rand.randrange(1, self.base) for _ in xrange(length)]
- output_seq = sorted(input_seq)
- io_examples.append((input_seq, output_seq))
- return io_examples
-
- def make_io_set(self):
- return copy.deepcopy(self._io_pairs)
-
-
-class RemoveTargetCharTask(KnownCodeBaseTask):
- """Remove target character from string, where first input is the target.
-
- Target can appear multiple times.
- """
-
- def __init__(self, **kwargs):
- def randrange_hole(rand, a, hole, b):
- x = rand.randrange(a, b - 1)
- if x >= hole:
- return x + 1
- return x
- def remove_target_char_gen(rand):
- char = rand.randrange(1, 6)
- l = rand.randrange(1, 8)
- input_seq = [randrange_hole(rand, 1, char, 256) for _ in xrange(l)]
- idx = range(l)
- rand.shuffle(idx)
- num_targets = rand.randrange(0, l)
- for pos in idx[:num_targets]:
- input_seq[pos] = char
- return [char] + input_seq + [0]
- super(type(self), self).__init__(
- ',>>>,[<<<[->+>+<<]>>[->->+<<]>[>[-<+>]<.[-]]>[-]<<<[-<+>]>>,].',
- remove_target_char_gen,
- **kwargs)
-
-
-class ListIndexTask(KnownCodeBaseTask):
- """Echo i-th value in the given list."""
-
- def __init__(self, **kwargs):
- def array_index_gen(rand):
- l = rand.randrange(1, 16)
- i = rand.randrange(l)
- return [i] + [rand.randrange(256) for _ in xrange(l)] + [0]
- super(type(self), self).__init__(
- ',[->,<]>,.',
- array_index_gen,
- **kwargs)
-
-
-# ==============================================================================
-# Tasks based on primaryobjects paper.
-# ==============================================================================
-
-
-def string2tokens(string):
- return [ord(c) for c in string]
-
-
-def stringlist2tokens(strings):
- return [string2tokens(string) for string in strings]
-
-
-def string2tokens_b27(string):
- return [ord(c.lower()) - ord('a') + 1 for c in string]
-
-
-def stringlist2tokens_b27(strings):
- return [string2tokens_b27(string) for string in strings]
-
-
-class BottlesOfBeerTask(BaseTask):
- """Bottles of beer coding task.
-
- This is a counting task. Code needs to read in an int N and then output
- every int from N to 0, each separated by a 0.
- """
- base = 256
- input_type = misc.IOType.integer
- output_type = misc.IOType.integer
-
- def make_io_set(self):
- return [
- ([1], [1, 0]),
- ([2], [2, 0, 1, 0]),
- ([3], [3, 0, 2, 0, 1, 0]),
- ([4], [4, 0, 3, 0, 2, 0, 1, 0]),
- ([5], [5, 0, 4, 0, 3, 0, 2, 0, 1, 0]),
- ([6], [6, 0, 5, 0, 4, 0, 3, 0, 2, 0, 1, 0])]
-
-
-class SplitTask(BaseTask):
- """Split coding task.
-
- Code needs to pipe input strings to output, but insert a 0 after every 3
- characters. This is in essence splitting the string into intervals of length
- 3.
- """
- base = 28
- input_type = misc.IOType.string
- output_type = misc.IOType.integer
-
- def _splicer(self, lst, insert, interval=3):
- for i, item in enumerate(lst):
- yield item
- if (i + 1) % interval == 0 and i < len(lst) - 1:
- yield insert
-
- def __init__(self):
- super(type(self), self).__init__()
- inputs = stringlist2tokens_b27(
- ['hello', 'orange', 'spaghetti', 'wins', 'one'])
- targets = [list(self._splicer(i, 27)) for i in inputs]
- self._test_cases = list(zip(inputs, targets))
-
- def make_io_set(self):
- return copy.deepcopy(self._test_cases)
-
-
-class TrimLeftTask(BaseTask):
- """Trim left coding task.
-
- Code needs to pipe input strings to output, but remove everything before the
- first quotation char (").
- """
- base = 256
- input_type = misc.IOType.integer
- output_type = misc.IOType.integer
-
- def __init__(self):
- super(type(self), self).__init__()
- inputs = stringlist2tokens(
- ['a "inside" over', 'xy "test" rights', 'ca6 "foresting" service',
- 'abc"def"yz.', 'A"B"'])
- targets = stringlist2tokens(
- ['"inside" over', '"test" rights', '"foresting" service', '"def"yz.',
- '"B"'])
- self._test_cases = list(zip(inputs, targets))
-
- def make_io_set(self):
- return copy.deepcopy(self._test_cases)
diff --git a/research/brain_coder/single_task/code_tasks_test.py b/research/brain_coder/single_task/code_tasks_test.py
deleted file mode 100644
index d3260a1a56ec0f7c36363d558122f7f7e49198e6..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/code_tasks_test.py
+++ /dev/null
@@ -1,108 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Tests for code_tasks."""
-
-import numpy as np
-import tensorflow as tf
-
-from single_task import code_tasks # brain coder
-from single_task import defaults # brain coder
-
-
-def pad(string, pad_length, pad_char):
- return string + pad_char * (pad_length - len(string))
-
-
-class CodeTasksTest(tf.test.TestCase):
-
- def assertClose(self, a, b):
- self.assertTrue(
- np.isclose(a, b, atol=1e-4),
- 'Expecting approximately equal values. Got: %s, %s' % (a, b))
-
- def testMultiIOTaskManager(self):
- maxlen = 100
- padchr = '['
- task = code_tasks.make_paper_task(
- 'print', timestep_limit=maxlen, do_code_simplification=False)
- reward_fns = task.rl_batch(1)
- r = reward_fns[0]
- self.assertClose(
- r(pad('++++++++.---.+++++++...', maxlen, padchr)).episode_rewards[-1],
- 0.2444)
- self.assertClose(
- r(pad('++++++++.---.+++++++..+++.',
- maxlen, padchr)).episode_rewards[-1],
- 1.0)
-
- task = code_tasks.make_paper_task(
- 'print', timestep_limit=maxlen, do_code_simplification=True)
- reward_fns = task.rl_batch(1)
- r = reward_fns[0]
- self.assertClose(
- r('++++++++.---.+++++++...').episode_rewards[-1],
- 0.2444)
- self.assertClose(
- r('++++++++.---.+++++++..+++.').episode_rewards[-1],
- 0.935)
- self.assertClose(
- r(pad('++++++++.---.+++++++..+++.',
- maxlen, padchr)).episode_rewards[-1],
- 0.75)
-
- task = code_tasks.make_paper_task(
- 'reverse', timestep_limit=maxlen, do_code_simplification=False)
- reward_fns = task.rl_batch(1)
- r = reward_fns[0]
- self.assertClose(
- r(pad('>,>,>,.<.<.<.', maxlen, padchr)).episode_rewards[-1],
- 0.1345)
- self.assertClose(
- r(pad(',[>,]+[,<.]', maxlen, padchr)).episode_rewards[-1],
- 1.0)
-
- task = code_tasks.make_paper_task(
- 'reverse', timestep_limit=maxlen, do_code_simplification=True)
- reward_fns = task.rl_batch(1)
- r = reward_fns[0]
- self.assertClose(r('>,>,>,.<.<.<.').episode_rewards[-1], 0.1324)
- self.assertClose(r(',[>,]+[,<.]').episode_rewards[-1], 0.9725)
- self.assertClose(
- r(pad(',[>,]+[,<.]', maxlen, padchr)).episode_rewards[-1],
- 0.75)
-
- def testMakeTask(self):
- maxlen = 100
- padchr = '['
- config = defaults.default_config_with_updates(
- 'env=c(config_for_iclr=False,fixed_string=[8,5,12,12,15])')
- task = code_tasks.make_task(config.env, 'print', timestep_limit=maxlen)
- reward_fns = task.rl_batch(1)
- r = reward_fns[0]
- self.assertClose(
- r('++++++++.---.+++++++...').episode_rewards[-1],
- 0.2444)
- self.assertClose(
- r('++++++++.---.+++++++..+++.').episode_rewards[-1],
- 0.935)
- self.assertClose(
- r(pad('++++++++.---.+++++++..+++.',
- maxlen, padchr)).episode_rewards[-1],
- 0.75)
-
- def testKnownCodeBaseTask(self):
- maxlen = 100
- padchr = '['
- task = code_tasks.make_paper_task(
- 'shift-left', timestep_limit=maxlen, do_code_simplification=False)
- reward_fns = task.rl_batch(1)
- r = reward_fns[0]
- self.assertClose(
- r(pad(',>,[.,]<.,.', maxlen, padchr)).episode_rewards[-1],
- 1.0)
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/brain_coder/single_task/data.py b/research/brain_coder/single_task/data.py
deleted file mode 100644
index 8f34464f5a3e1c403b0f253f1520920c303b0819..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/data.py
+++ /dev/null
@@ -1,89 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Manage data for pretraining and RL tasks."""
-
-import ast
-from collections import namedtuple
-
-from absl import logging
-
-from single_task import code_tasks # brain coder
-
-
-RLBatch = namedtuple('RLBatch', ['reward_fns', 'batch_size', 'good_reward'])
-
-
-class DataManager(object):
- """Interface between environment and model."""
-
- def __init__(self, global_config, run_number=None,
- do_code_simplification=False):
- """Constructs a DataManager.
-
- Args:
- global_config: A config_lib.Config instance containing all config. See
- config in defaults.py.
- run_number: Which run this is (of the same experiment). This should be set
- when a task cycle is defined in the config. A task cycle is a list of
- tasks to cycle through repeatedly, and the selected task is a function
- of the run number, i.e. 0-th run, 1-st run, 2-nd run, etc...
- This can be None if only a single task is set in the config.
- do_code_simplification: When global_config.env.config_for_iclr is True,
- use this option to create code simplification (code golf) tasks, vs
- fixed length coding tasks. If True, a task with code simplification
- reward will be constructed.
-
- Raises:
- ValueError: If global_config.env.task and global_config.env.task_cycle
- are both set, or both not set. Only one should be given.
- ValueError: If global_config.env.task_cycle is set but run_number is None.
- """
- env_config = global_config.env
- self.batch_size = global_config.batch_size
-
- if env_config.task_cycle:
- if env_config.task:
- raise ValueError('Do not set both `task` and `task_cycle`.')
- if run_number is None:
- raise ValueError('Do not use task_cycle for single-run experiment.')
- index = run_number % len(env_config.task_cycle)
- self.task_name = env_config.task_cycle[index]
- logging.info('run_number: %d, task_cycle index: %d', run_number, index)
- logging.info('task_cycle: %s', env_config.task_cycle)
- elif env_config.task:
- self.task_name = env_config.task
- else:
- raise ValueError('Either `task` or `task_cycle` must be set.')
- logging.info('Task for this run: "%s"', self.task_name)
-
- logging.info('config_for_iclr=True; do_code_simplification=%s',
- do_code_simplification)
- self.rl_task = code_tasks.make_task(
- task_name=self.task_name,
- override_kwargs=ast.literal_eval(env_config.task_kwargs),
- max_code_length=global_config.timestep_limit,
- require_correct_syntax=env_config.correct_syntax,
- do_code_simplification=do_code_simplification,
- correct_bonus=env_config.task_manager_config.correct_bonus,
- code_length_bonus=env_config.task_manager_config.code_length_bonus)
-
- def sample_rl_batch(self):
- """Create reward functions from the current task.
-
- Returns:
- RLBatch namedtuple instance, which holds functions and information for
- a minibatch of episodes.
- * reward_fns: A reward function for each episode. Maps code string to
- reward.
- * batch_size: Number of episodes in this minibatch.
- * good_reward: Estimated threshold of rewards which indicate the algorithm
- is starting to solve the task. This is a heuristic that tries to
- reduce the amount of stuff written to disk.
- """
- reward_fns = self.rl_task.rl_batch(self.batch_size)
- return RLBatch(
- reward_fns=reward_fns,
- batch_size=self.batch_size,
- good_reward=self.rl_task.good_reward)
diff --git a/research/brain_coder/single_task/defaults.py b/research/brain_coder/single_task/defaults.py
deleted file mode 100644
index d9bd8b942532dfffcf06d90d331e58725c4d82a9..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/defaults.py
+++ /dev/null
@@ -1,82 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Default configuration for agent and environment."""
-
-from absl import logging
-
-from common import config_lib # brain coder
-
-
-def default_config():
- return config_lib.Config(
- agent=config_lib.OneOf(
- [config_lib.Config(
- algorithm='pg',
- policy_lstm_sizes=[35,35],
- # Set value_lstm_sizes to None to share weights with policy.
- value_lstm_sizes=[35,35],
- obs_embedding_size=10,
- grad_clip_threshold=10.0,
- param_init_factor=1.0,
- lr=5e-5,
- pi_loss_hparam=1.0,
- vf_loss_hparam=0.5,
- entropy_beta=1e-2,
- regularizer=0.0,
- softmax_tr=1.0, # Reciprocal temperature.
- optimizer='rmsprop', # 'adam', 'sgd', 'rmsprop'
- topk=0, # Top-k unique codes will be stored.
- topk_loss_hparam=0.0, # off policy loss multiplier.
- # Uniformly sample this many episodes from topk buffer per batch.
- # If topk is 0, this has no effect.
- topk_batch_size=1,
- # Exponential moving average baseline for REINFORCE.
- # If zero, A2C is used.
- # If non-zero, should be close to 1, like .99, .999, etc.
- ema_baseline_decay=0.99,
- # Whether agent can emit EOS token. If true, agent can emit EOS
- # token which ends the episode early (ends the sequence).
- # If false, agent must emit tokens until the timestep limit is
- # reached. e.g. True means variable length code, False means fixed
- # length code.
- # WARNING: Making this false slows things down.
- eos_token=False,
- replay_temperature=1.0,
- # Replay probability. 1 = always replay, 0 = always on policy.
- alpha=0.0,
- # Whether to normalize importance weights in each minibatch.
- iw_normalize=True),
- config_lib.Config(
- algorithm='ga',
- crossover_rate=0.99,
- mutation_rate=0.086),
- config_lib.Config(
- algorithm='rand')],
- algorithm='pg',
- ),
- env=config_lib.Config(
- # If True, task-specific settings are not needed.
- task='', # 'print', 'echo', 'reverse', 'remove', ...
- task_cycle=[], # If non-empty, reptitions will cycle through tasks.
- task_kwargs='{}', # Python dict literal.
- task_manager_config=config_lib.Config(
- # Reward recieved per test case. These bonuses will be scaled
- # based on how many test cases there are.
- correct_bonus=2.0, # Bonus for code getting correct answer.
- code_length_bonus=1.0), # Maximum bonus for short code.
- correct_syntax=False,
- ),
- batch_size=64,
- timestep_limit=32)
-
-
-def default_config_with_updates(config_string, do_logging=True):
- if do_logging:
- logging.info('Config string: "%s"', config_string)
- config = default_config()
- config.strict_update(config_lib.Config.parse(config_string))
- if do_logging:
- logging.info('Config:\n%s', config.pretty_str())
- return config
diff --git a/research/brain_coder/single_task/ga_lib.py b/research/brain_coder/single_task/ga_lib.py
deleted file mode 100644
index fadb96482b21a5c65c0d6d6cf4a3aec3b5708235..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/ga_lib.py
+++ /dev/null
@@ -1,472 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Genetic algorithm for BF tasks.
-
-Inspired by https://github.com/primaryobjects/AI-Programmer.
-GA function code borrowed from https://github.com/DEAP/deap.
-"""
-
-from collections import namedtuple
-import random
-
-from absl import flags
-from absl import logging
-import numpy as np
-from six.moves import xrange
-
-from common import bf # brain coder
-from common import utils # brain coder
-from single_task import misc # brain coder
-
-FLAGS = flags.FLAGS
-
-# Saving reward of previous programs saves computation if a program appears
-# again.
-USE_REWARD_CACHE = True # Disable this if GA is using up too much memory.
-GENES = bf.CHARS
-MAX_PROGRAM_STEPS = 500
-STEP_BONUS = True
-
-ALPHANUM_CHARS = (
- ['_'] +
- [chr(ord('a') + i_) for i_ in range(26)] +
- [chr(ord('A') + i_) for i_ in range(26)] +
- [chr(ord('0') + i_) for i_ in range(10)])
-
-Result = namedtuple(
- 'Result',
- ['reward', 'inputs', 'code_outputs', 'target_outputs', 'type_in',
- 'type_out', 'base', 'correct'])
-
-
-class IOType(object):
- string = 'string'
- integer = 'integer'
-
-
-class CustomType(object):
-
- def __init__(self, to_str_fn):
- self.to_str_fn = to_str_fn
-
- def __call__(self, obj):
- return self.to_str_fn(obj)
-
-
-def tokens_list_repr(tokens, repr_type, base):
- """Make human readable representation of program IO."""
- if isinstance(repr_type, CustomType):
- return repr_type(tokens)
- elif repr_type == IOType.string:
- chars = (
- [ALPHANUM_CHARS[t] for t in tokens] if base < len(ALPHANUM_CHARS)
- else [chr(t) for t in tokens])
- return ''.join(chars)
- elif repr_type == IOType.integer:
- return str(tokens)
- raise ValueError('No such representation type "%s"', repr_type)
-
-
-def io_repr(result):
- """Make human readable representation of test cases."""
- inputs = ','.join(
- tokens_list_repr(tokens, result.type_in, result.base)
- for tokens in result.inputs)
- code_outputs = ','.join(
- tokens_list_repr(tokens, result.type_out, result.base)
- for tokens in result.code_outputs)
- target_outputs = ','.join(
- tokens_list_repr(tokens, result.type_out, result.base)
- for tokens in result.target_outputs)
- return inputs, target_outputs, code_outputs
-
-
-def make_task_eval_fn(task_manager):
- """Returns a wrapper that converts an RL task into a GA task.
-
- Args:
- task_manager: Is a task manager object from code_tasks.py
-
- Returns:
- A function that takes as input a single list of a code chars, and outputs
- a Result namedtuple instance containing the reward and information about
- code execution.
- """
- def to_data_list(single_or_tuple):
- if isinstance(single_or_tuple, misc.IOTuple):
- return list(single_or_tuple)
- return [single_or_tuple]
-
- def to_ga_type(rl_type):
- if rl_type == misc.IOType.string:
- return IOType.string
- return IOType.integer
-
- # Wrapper function.
- def evalbf(bf_chars):
- result = task_manager._score_code(''.join(bf_chars))
- reward = sum(result.episode_rewards)
- correct = result.reason == 'correct'
- return Result(
- reward=reward,
- inputs=to_data_list(result.input_case),
- code_outputs=to_data_list(result.code_output),
- target_outputs=to_data_list(result.correct_output),
- type_in=to_ga_type(result.input_type),
- type_out=to_ga_type(result.output_type),
- correct=correct,
- base=task_manager.task.base)
-
- return evalbf
-
-
-def debug_str(individual, task_eval_fn):
- res = task_eval_fn(individual)
- input_str, target_output_str, code_output_str = io_repr(res)
- return (
- ''.join(individual) +
- ' | ' + input_str +
- ' | ' + target_output_str +
- ' | ' + code_output_str +
- ' | ' + str(res.reward) +
- ' | ' + str(res.correct))
-
-
-def mutate_single(code_tokens, mutation_rate):
- """Mutate a single code string.
-
- Args:
- code_tokens: A string/list/Individual of BF code chars. Must end with EOS
- symbol '_'.
- mutation_rate: Float between 0 and 1 which sets the probability of each char
- being mutated.
-
- Returns:
- An Individual instance containing the mutated code string.
-
- Raises:
- ValueError: If `code_tokens` does not end with EOS symbol.
- """
- if len(code_tokens) <= 1:
- return code_tokens
- if code_tokens[-1] == '_':
- # Do this check to ensure that the code strings have not been corrupted.
- raise ValueError('`code_tokens` must end with EOS symbol.')
- else:
- cs = Individual(code_tokens)
- eos = []
- mutated = False
- for pos in range(len(cs)):
- if random.random() < mutation_rate:
- mutated = True
- new_char = GENES[random.randrange(len(GENES))]
- x = random.random()
- if x < 0.25 and pos != 0 and pos != len(cs) - 1:
- # Insertion mutation.
- if random.random() < 0.50:
- # Shift up.
- cs = cs[:pos] + [new_char] + cs[pos:-1]
- else:
- # Shift down.
- cs = cs[1:pos] + [new_char] + cs[pos:]
- elif x < 0.50:
- # Deletion mutation.
- if random.random() < 0.50:
- # Shift down.
- cs = cs[:pos] + cs[pos + 1:] + [new_char]
- else:
- # Shift up.
- cs = [new_char] + cs[:pos] + cs[pos + 1:]
- elif x < 0.75:
- # Shift rotate mutation (position invariant).
- if random.random() < 0.50:
- # Shift down.
- cs = cs[1:] + [cs[0]]
- else:
- # Shift up.
- cs = [cs[-1]] + cs[:-1]
- else:
- # Replacement mutation.
- cs = cs[:pos] + [new_char] + cs[pos + 1:]
- assert len(cs) + len(eos) == len(code_tokens)
- if mutated:
- return Individual(cs + eos)
- else:
- return Individual(code_tokens)
-
-
-def crossover(parent1, parent2):
- """Performs crossover mating between two code strings.
-
- Crossover mating is where a random position is selected, and the chars
- after that point are swapped. The resulting new code strings are returned.
-
- Args:
- parent1: First code string.
- parent2: Second code string.
-
- Returns:
- A 2-tuple of children, i.e. the resulting code strings after swapping.
- """
- max_parent, min_parent = (
- (parent1, parent2) if len(parent1) > len(parent2)
- else (parent2, parent1))
- pos = random.randrange(len(max_parent))
- if pos >= len(min_parent):
- child1 = max_parent[:pos]
- child2 = min_parent + max_parent[pos:]
- else:
- child1 = max_parent[:pos] + min_parent[pos:]
- child2 = min_parent[:pos] + max_parent[pos:]
- return Individual(child1), Individual(child2)
-
-
-def _make_even(n):
- """Return largest even integer less than or equal to `n`."""
- return (n >> 1) << 1
-
-
-def mutate_and_crossover(population, mutation_rate, crossover_rate):
- """Take a generational step over a population.
-
- Transforms population of parents into population of children (of the same
- size) via crossover mating and then mutation on the resulting children.
-
- Args:
- population: Parent population. A list of Individual objects.
- mutation_rate: Probability of mutation. See `mutate_single`.
- crossover_rate: Probability that two parents will mate.
-
- Returns:
- Child population. A list of Individual objects.
- """
- children = [None] * len(population)
- for i in xrange(0, _make_even(len(population)), 2):
- p1 = population[i]
- p2 = population[i + 1]
- if random.random() < crossover_rate:
- p1, p2 = crossover(p1, p2)
- c1 = mutate_single(p1, mutation_rate)
- c2 = mutate_single(p2, mutation_rate)
- children[i] = c1
- children[i + 1] = c2
- if children[-1] is None:
- children[-1] = population[-1]
- return children
-
-
-def ga_loop(population, cxpb, mutpb, ngen, task_eval_fn, halloffame=None,
- checkpoint_writer=None):
- """A bare bones genetic algorithm.
-
- Similar to chapter 7 of Back, Fogel and Michalewicz, "Evolutionary
- Computation 1 : Basic Algorithms and Operators", 2000.
-
- Args:
- population: A list of individuals.
- cxpb: The probability of mating two individuals.
- mutpb: The probability of mutating a gene.
- ngen: The number of generation. Unlimited if zero.
- task_eval_fn: A python function which maps an Individual to a Result
- namedtuple.
- halloffame: (optional) a utils.MaxUniquePriorityQueue object that will be
- used to aggregate the best individuals found during search.
- checkpoint_writer: (optional) an object that can save and load populations.
- Needs to have `write`, `load`, and `has_checkpoint` methods. Used to
- periodically save progress. In event of a restart, the population will
- be loaded from disk.
-
- Returns:
- GaResult namedtuple instance. This contains information about the GA run,
- including the resulting population, best reward (fitness) obtained, and
- the best code string found.
- """
-
- has_checkpoint = False
- if checkpoint_writer and checkpoint_writer.has_checkpoint():
- try:
- gen, population, halloffame = checkpoint_writer.load()
- except EOFError: # Data was corrupted. Start over.
- pass
- else:
- has_checkpoint = True
- logging.info(
- 'Loaded population from checkpoint. Starting at generation %d', gen)
-
- # Evaluate the individuals with an invalid fitness
- invalid_ind = [ind for ind in population if not ind.fitness.valid]
- for ind in invalid_ind:
- ind.fitness.values = task_eval_fn(ind).reward,
- for _, ind in halloffame.iter_in_order():
- ind.fitness.values = task_eval_fn(ind).reward,
-
- if not has_checkpoint:
- # Evaluate the individuals with an invalid fitness
- invalid_ind = [ind for ind in population if not ind.fitness.valid]
- for ind in invalid_ind:
- ind.fitness.values = task_eval_fn(ind).reward,
-
- if halloffame is not None:
- for ind in population:
- halloffame.push(ind.fitness.values, tuple(ind), ind)
-
- logging.info('Initialized new population.')
-
- gen = 1
-
- pop_size = len(population)
- program_reward_cache = {} if USE_REWARD_CACHE else None
-
- # Begin the generational process
- while ngen == 0 or gen <= ngen:
- # Select the next generation individuals
- offspring = roulette_selection(population, pop_size - len(halloffame))
-
- # Vary the pool of individuals
- # offspring = varAnd(offspring, toolbox, cxpb, mutpb)
- offspring = mutate_and_crossover(
- offspring, mutation_rate=mutpb, crossover_rate=cxpb)
-
- # Evaluate the individuals with an invalid fitness
- invalid_ind = [ind for ind in offspring if not ind.fitness.valid]
- for ind in invalid_ind:
- str_repr = ''.join(ind)
- if program_reward_cache is not None and str_repr in program_reward_cache:
- ind.fitness.values = (program_reward_cache[str_repr],)
- else:
- eval_result = task_eval_fn(ind)
- ind.fitness.values = (eval_result.reward,)
- if program_reward_cache is not None:
- program_reward_cache[str_repr] = eval_result.reward
-
- # Replace the current population by the offspring
- population = list(offspring)
-
- # Update the hall of fame with the generated individuals
- if halloffame is not None:
- for ind in population:
- halloffame.push(ind.fitness.values, tuple(ind), ind)
-
- # elitism
- population.extend([ind for _, ind in halloffame.iter_in_order()])
-
- if gen % 100 == 0:
- top_code = '\n'.join([debug_str(ind, task_eval_fn)
- for ind in topk(population, k=4)])
- logging.info('gen: %d\nNPE: %d\n%s\n\n', gen, gen * pop_size, top_code)
-
- best_code = ''.join(halloffame.get_max()[1])
- res = task_eval_fn(best_code)
-
- # Write population and hall-of-fame to disk.
- if checkpoint_writer:
- checkpoint_writer.write(gen, population, halloffame)
-
- if res.correct:
- logging.info('Solution found:\n%s\nreward = %s\n',
- best_code, res.reward)
- break
-
- gen += 1
-
- best_code = ''.join(halloffame.get_max()[1])
- res = task_eval_fn(best_code)
-
- return GaResult(
- population=population, best_code=best_code, reward=res.reward,
- solution_found=res.correct, generations=gen,
- num_programs=gen * len(population),
- max_generations=ngen, max_num_programs=ngen * len(population))
-
-
-GaResult = namedtuple(
- 'GaResult',
- ['population', 'best_code', 'reward', 'generations', 'num_programs',
- 'solution_found', 'max_generations', 'max_num_programs'])
-
-
-def reward_conversion(reward):
- """Convert real value into positive value."""
- if reward <= 0:
- return 0.05
- return reward + 0.05
-
-
-def roulette_selection(population, k):
- """Select `k` individuals with prob proportional to fitness.
-
- Each of the `k` selections is independent.
-
- Warning:
- The roulette selection by definition cannot be used for minimization
- or when the fitness can be smaller or equal to 0.
-
- Args:
- population: A list of Individual objects to select from.
- k: The number of individuals to select.
-
- Returns:
- A list of selected individuals.
- """
- fitnesses = np.asarray(
- [reward_conversion(ind.fitness.values[0])
- for ind in population])
- assert np.all(fitnesses > 0)
-
- sum_fits = fitnesses.sum()
- chosen = [None] * k
- for i in xrange(k):
- u = random.random() * sum_fits
- sum_ = 0
- for ind, fitness in zip(population, fitnesses):
- sum_ += fitness
- if sum_ > u:
- chosen[i] = Individual(ind)
- break
- if not chosen[i]:
- chosen[i] = Individual(population[-1])
-
- return chosen
-
-
-def make_population(make_individual_fn, n):
- return [make_individual_fn() for _ in xrange(n)]
-
-
-def best(population):
- best_ind = None
- for ind in population:
- if best_ind is None or best_ind.fitness.values < ind.fitness.values:
- best_ind = ind
- return best_ind
-
-
-def topk(population, k):
- q = utils.MaxUniquePriorityQueue(k)
- for ind in population:
- q.push(ind.fitness.values, tuple(ind), ind)
- return [ind for _, ind in q.iter_in_order()]
-
-
-class Fitness(object):
-
- def __init__(self):
- self.values = ()
-
- @property
- def valid(self):
- """Assess if a fitness is valid or not."""
- return bool(self.values)
-
-
-class Individual(list):
-
- def __init__(self, *args):
- super(Individual, self).__init__(*args)
- self.fitness = Fitness()
-
-
-def random_individual(genome_size):
- return lambda: Individual(np.random.choice(GENES, genome_size).tolist())
diff --git a/research/brain_coder/single_task/ga_train.py b/research/brain_coder/single_task/ga_train.py
deleted file mode 100644
index 630eca427e478dbadad58bd94b56e89a5a747526..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/ga_train.py
+++ /dev/null
@@ -1,324 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Genetic algorithm for BF tasks.
-
-Also contains the uniform random search algorithm.
-
-Inspired by https://github.com/primaryobjects/AI-Programmer.
-GA function code borrowed from https://github.com/DEAP/deap.
-"""
-
-import cPickle
-import os
-import sys
-from time import sleep
-
-from absl import flags
-from absl import logging
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-from common import utils # brain coder
-from single_task import data # brain coder
-from single_task import defaults # brain coder
-from single_task import ga_lib # brain coder
-from single_task import results_lib # brain coder
-
-FLAGS = flags.FLAGS
-
-
-def define_tuner_hparam_space(hparam_space_type):
- """Define tunable hparams for grid search."""
- if hparam_space_type != 'ga':
- raise ValueError('Hparam space is not valid: "%s"' % hparam_space_type)
- return {
- 'population_size': [10, 25, 50, 100, 500],
- 'crossover_rate': [0.2, 0.5, 0.7, 0.9, 0.95],
- 'mutation_rate': [0.01, 0.03, 0.05, 0.1, 0.15]}
-
-
-def write_hparams_to_config(config, hparams, hparam_space_type):
- """Write hparams given by the tuner into the Config object."""
- if hparam_space_type != 'ga':
- raise ValueError('Hparam space is not valid: "%s"' % hparam_space_type)
- config.batch_size = hparams.population_size
- config.agent.crossover_rate = hparams.crossover_rate
- config.agent.mutation_rate = hparams.mutation_rate
-
-
-class CheckpointWriter(object):
- """Manages loading and saving GA populations to disk.
-
- This object is used by the genetic algorithm to save progress periodically
- so that a recent population can be loaded from disk in the event of a restart.
- """
-
- def __init__(self, checkpoint_dir, population_size):
- self.checkpoint_file = os.path.join(checkpoint_dir, 'checkpoint.pickle')
- self.population_size = population_size
-
- def write(self, gen, population, halloffame):
- """Write GA state to disk.
-
- Overwrites previous saved state.
-
- Args:
- gen: Generation number.
- population: List of Individual objects.
- halloffame: Hall-of-fame buffer. Typically a priority queue.
- """
- raw = cPickle.dumps((gen, population, halloffame))
- with tf.gfile.FastGFile(self.checkpoint_file, 'w') as f:
- f.write(raw)
-
- def load(self):
- """Loads GA state from disk.
-
- Loads whatever is on disk, which will be whatever the most recent call
- to `write` wrote.
-
- Returns:
- gen: Generation number.
- population: List of Individual objects.
- halloffame: Hall-of-fame buffer. Typically a priority queue.
- """
- with tf.gfile.FastGFile(self.checkpoint_file, 'r') as f:
- raw = f.read()
- objs = cPickle.loads(raw)
- # Validate data.
- assert isinstance(objs, tuple) and len(objs) == 3, (
- 'Expecting a 3-tuple, but got %s instead.' % (objs,))
- gen, population, halloffame = objs
- assert isinstance(gen, int), (
- 'Expecting `gen` to be an integer, got %s' % (gen,))
- assert (
- isinstance(population, list)
- and len(population) == self.population_size
- ), (
- 'Expecting `population` to be a list with size %d, got %s'
- % (self.population_size, population))
- assert halloffame is None or len(halloffame) == 2, (
- 'Expecting hall-of-fame object to have length two, got length %d'
- % len(halloffame))
- logging.info('Loaded pop from checkpoint file: "%s".',
- self.checkpoint_file)
- return gen, population, halloffame
-
- def has_checkpoint(self):
- """Checks if a checkpoint exists on disk, and if so returns True."""
- return tf.gfile.Exists(self.checkpoint_file)
-
-
-def run_training(config=None, tuner=None, logdir=None, trial_name=None, # pylint: disable=unused-argument
- is_chief=True):
- """Do all training runs.
-
- This is the top level training function for policy gradient based models.
- Run this from the main function.
-
- Args:
- config: config_lib.Config instance containing global config (agent and
- environment hparams). If None, config will be parsed from FLAGS.config.
- tuner: (unused) A tuner instance. Leave as None if not tuning.
- logdir: Parent directory where all data from all runs will be written. If
- None, FLAGS.logdir will be used.
- trial_name: (unused) If tuning, set this to a unique string that identifies
- this trial. If `tuner` is not None, this also must be set.
- is_chief: True if this worker is the chief.
-
- Returns:
- List of results dicts which were written to disk. Each training run gets a
- results dict. Results dict contains metrics, i.e. (name, value) pairs which
- give information about the training run.
-
- Raises:
- ValueError: If FLAGS.num_workers does not divide FLAGS.num_repetitions.
- ValueError: If results dicts read from disk contain invalid data.
- """
- if not config:
- # If custom config is not given, get it from flags.
- config = defaults.default_config_with_updates(FLAGS.config)
- if not logdir:
- logdir = FLAGS.logdir
-
- if FLAGS.num_repetitions % FLAGS.num_workers != 0:
- raise ValueError('Number of workers must divide number of repetitions')
- num_local_reps = FLAGS.num_repetitions // FLAGS.num_workers
- logging.info('Running %d reps globally.', FLAGS.num_repetitions)
- logging.info('This worker will run %d local reps.', num_local_reps)
- if FLAGS.max_npe:
- max_generations = FLAGS.max_npe // config.batch_size
- logging.info('Max samples per rep: %d', FLAGS.max_npe)
- logging.info('Max generations per rep: %d', max_generations)
- else:
- max_generations = sys.maxint
- logging.info('Running unlimited generations.')
-
- assert FLAGS.num_workers > 0
- logging.info('Starting experiment. Directory: "%s"', logdir)
- results = results_lib.Results(logdir, FLAGS.task_id)
- local_results_list = results.read_this_shard()
- if local_results_list:
- if local_results_list[0]['max_npe'] != FLAGS.max_npe:
- raise ValueError(
- 'Cannot resume training. Max-NPE changed. Was %s, now %s',
- local_results_list[0]['max_npe'], FLAGS.max_npe)
- if local_results_list[0]['max_global_repetitions'] != FLAGS.num_repetitions:
- raise ValueError(
- 'Cannot resume training. Number of repetitions changed. Was %s, '
- 'now %s',
- local_results_list[0]['max_global_repetitions'],
- FLAGS.num_repetitions)
- start_rep = len(local_results_list)
-
- for rep in xrange(start_rep, num_local_reps):
- global_rep = num_local_reps * FLAGS.task_id + rep
- logging.info(
- 'Starting repetition: Rep = %d. (global rep = %d)',
- rep, global_rep)
-
- # Save data for each rep, like checkpoints, goes into separate folders.
- run_dir = os.path.join(logdir, 'run_%d' % global_rep)
-
- if not tf.gfile.IsDirectory(run_dir):
- tf.gfile.MakeDirs(run_dir)
- checkpoint_writer = CheckpointWriter(run_dir,
- population_size=config.batch_size)
-
- data_manager = data.DataManager(config, run_number=global_rep)
- task_eval_fn = ga_lib.make_task_eval_fn(data_manager.rl_task)
-
- if config.agent.algorithm == 'rand':
- logging.info('Running random search.')
- assert FLAGS.max_npe
- result = run_random_search(
- FLAGS.max_npe, run_dir, task_eval_fn, config.timestep_limit)
- else:
- assert config.agent.algorithm == 'ga'
- logging.info('Running genetic algorithm.')
- pop = ga_lib.make_population(
- ga_lib.random_individual(config.timestep_limit),
- n=config.batch_size)
- hof = utils.MaxUniquePriorityQueue(2) # Hall of fame.
- result = ga_lib.ga_loop(
- pop,
- cxpb=config.agent.crossover_rate, mutpb=config.agent.mutation_rate,
- task_eval_fn=task_eval_fn,
- ngen=max_generations, halloffame=hof,
- checkpoint_writer=checkpoint_writer)
-
- logging.info('Finished rep. Num gens: %d', result.generations)
-
- results_dict = {
- 'max_npe': FLAGS.max_npe,
- 'batch_size': config.batch_size,
- 'max_batches': FLAGS.max_npe // config.batch_size,
- 'npe': result.num_programs,
- 'max_global_repetitions': FLAGS.num_repetitions,
- 'max_local_repetitions': num_local_reps,
- 'code_solution': result.best_code if result.solution_found else '',
- 'best_reward': result.reward,
- 'num_batches': result.generations,
- 'found_solution': result.solution_found,
- 'task': data_manager.task_name,
- 'global_rep': global_rep}
- logging.info('results_dict: %s', results_dict)
- results.append(results_dict)
-
- if is_chief:
- logging.info(
- 'Worker is chief. Waiting for all workers to finish so that results '
- 'can be reported to the tuner.')
-
- global_results_list, shard_stats = results.read_all(
- num_shards=FLAGS.num_workers)
- while not all(s.finished for s in shard_stats):
- logging.info(
- 'Still waiting on these workers: %s',
- ', '.join(
- ['%d (%d reps left)'
- % (i, s.max_local_reps - s.num_local_reps_completed)
- for i, s in enumerate(shard_stats)
- if not s.finished]))
- sleep(60)
- global_results_list, shard_stats = results.read_all(
- num_shards=FLAGS.num_workers)
-
- logging.info(
- '%d results obtained. Chief worker is exiting the experiment.',
- len(global_results_list))
-
- return global_results_list
-
-
-def run_random_search(max_num_programs, checkpoint_dir, task_eval_fn,
- timestep_limit):
- """Run uniform random search routine.
-
- Randomly samples programs from a uniform distribution until either a valid
- program is found, or the maximum NPE is reached. Results are written to disk
- and returned.
-
- Args:
- max_num_programs: Maximum NPE (number of programs executed). If no solution
- is found after this many programs are tried, the run is stopped and
- considered a failure.
- checkpoint_dir: Where to save state during the run.
- task_eval_fn: Function that maps code string to result containing total
- reward and info about success.
- timestep_limit: Maximum length of code strings.
-
- Returns:
- ga_lib.GaResult namedtuple instance. This contains the best code and highest
- reward found.
- """
- checkpoint_file = os.path.join(checkpoint_dir, 'random_search.txt')
- num_programs_seen = 0
- found_solution = False
- best_code = ''
- best_reward = 0.0
- if tf.gfile.Exists(checkpoint_file):
- try:
- with tf.gfile.FastGFile(checkpoint_file, 'r') as f:
- lines = list(f)
- num_programs_seen = int(lines[0])
- found_solution = bool(int(lines[1]))
- if found_solution:
- best_code = lines[2]
- best_reward = float(lines[3])
- except: # pylint: disable=bare-except
- pass
-
- while not found_solution and num_programs_seen < max_num_programs:
- if num_programs_seen % 1000 == 0:
- logging.info('num_programs_seen = %d', num_programs_seen)
- with tf.gfile.FastGFile(checkpoint_file, 'w') as f:
- f.write(str(num_programs_seen) + '\n')
- f.write(str(int(found_solution)) + '\n')
-
- code = np.random.choice(ga_lib.GENES, timestep_limit).tolist()
- res = task_eval_fn(code)
- found_solution = res.correct
- num_programs_seen += 1
-
- if found_solution:
- best_code = ''.join(code)
- best_reward = res.reward
-
- logging.info('num_programs_seen = %d', num_programs_seen)
- logging.info('found solution: %s', found_solution)
- with tf.gfile.FastGFile(checkpoint_file, 'w') as f:
- f.write(str(num_programs_seen) + '\n')
- f.write(str(int(found_solution)) + '\n')
- if found_solution:
- f.write(best_code + '\n')
- f.write(str(best_reward) + '\n')
-
- return ga_lib.GaResult(
- population=[], best_code=best_code, reward=best_reward,
- solution_found=found_solution, generations=num_programs_seen,
- num_programs=num_programs_seen, max_generations=max_num_programs,
- max_num_programs=max_num_programs)
diff --git a/research/brain_coder/single_task/ga_train_test.py b/research/brain_coder/single_task/ga_train_test.py
deleted file mode 100644
index ff69ad84952a3fb90cad28b3cf8e67ff55c96e95..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/ga_train_test.py
+++ /dev/null
@@ -1,51 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Tests for ga_train.
-
-Tests that ga runs for a few generations without crashing.
-"""
-
-from absl import flags
-import tensorflow as tf
-
-from single_task import defaults # brain coder
-from single_task import run # brain coder
-
-FLAGS = flags.FLAGS
-
-
-class GaTest(tf.test.TestCase):
-
- def RunTrainingSteps(self, config_string, num_steps=10):
- """Run a few training steps with the given config.
-
- Just check that nothing crashes.
-
- Args:
- config_string: Config encoded in a string. See
- $REPO_PATH/common/config_lib.py
- num_steps: Number of training steps to run. Defaults to 10.
- """
- config = defaults.default_config_with_updates(config_string)
- FLAGS.max_npe = num_steps * config.batch_size
- FLAGS.logdir = tf.test.get_temp_dir()
- FLAGS.config = config_string
- run.main(None)
-
- def testGeneticAlgorithm(self):
- self.RunTrainingSteps(
- 'env=c(task="reverse"),'
- 'agent=c(algorithm="ga"),'
- 'timestep_limit=40,batch_size=64')
-
- def testUniformRandomSearch(self):
- self.RunTrainingSteps(
- 'env=c(task="reverse"),'
- 'agent=c(algorithm="rand"),'
- 'timestep_limit=40,batch_size=64')
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/brain_coder/single_task/launch_training.sh b/research/brain_coder/single_task/launch_training.sh
deleted file mode 100755
index a4a4688ed2912792185aa8f3134b1680fed6f006..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/launch_training.sh
+++ /dev/null
@@ -1,72 +0,0 @@
-#!/bin/bash
-# Launches training jobs.
-# Modify this file to launch workers with your prefered cloud API.
-# The following implementation runs each worker as a subprocess on the local
-# machine.
-
-MODELS_DIR="/tmp/models"
-
-# Get command line options.
-OPTS=$(getopt -n "$0" -o "" --long "job_name:,config:,num_workers:,num_ps:,max_npe:,num_repetitions:,stop_on_success:" -- "$@")
-if [ $? != 0 ] ; then echo "Failed parsing options." >&2 ; exit 1 ; fi
-
-eval set -- "$OPTS"
-
-JOB_NAME="" # Name of the process and the logs directory.
-CONFIG="" # Model and environment hparams.
-# NUM_WORKERS: Number of workers to launch for this training job. If using
-# neural networks, each worker will be 1 replica.
-NUM_WORKERS=1
-# NUM_PS: Number of parameter servers to launch for this training job. Only set
-# this if using neural networks. For 1 worker, no parameter servers are needed.
-# For more than 1 worker, at least 1 parameter server is needed to store the
-# global model.
-NUM_PS=0
-# MAX_NPE: Maximum number of programs executed. Training will quit once this
-# threshold is reached. If 0, the threshold is infinite.
-MAX_NPE=0
-NUM_REPETITIONS=1 # How many times to run this experiment.
-STOP_ON_SUCCESS=true # Whether to halt training when a solution is found.
-
-# Parse options into variables.
-while true; do
- case "$1" in
- --job_name ) JOB_NAME="$2"; shift; shift ;;
- --config ) CONFIG="$2"; shift; shift ;;
- --num_workers ) NUM_WORKERS="$2"; shift; shift ;;
- --num_ps ) NUM_PS="$2"; shift; shift ;;
- --max_npe ) MAX_NPE="$2"; shift; shift ;;
- --num_repetitions ) NUM_REPETITIONS="$2"; shift; shift ;;
- --stop_on_success ) STOP_ON_SUCCESS="$2"; shift; shift ;;
- -- ) shift; break ;;
- * ) break ;;
- esac
-done
-
-# Launch jobs.
-# TODO: multi-worker RL training
-
-LOGDIR="$MODELS_DIR/$JOB_NAME"
-mkdir -p $LOGDIR
-
-BIN_DIR="bazel-bin/single_task"
-for (( i=0; i "$LOGDIR/task_$i.log" & # Run as subprocess
- echo "Launched task $i. Logs: $LOGDIR/task_$i.log"
-done
-
-
-# Use "pidof run.par" to find jobs.
-# Kill with "pkill run.par"
diff --git a/research/brain_coder/single_task/launch_tuning.sh b/research/brain_coder/single_task/launch_tuning.sh
deleted file mode 100755
index 97ce51b543e13d4b1c412656a93197b5b47373bb..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/launch_tuning.sh
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/bin/bash
-# Launches tuning jobs.
-# Modify this file to launch workers with your prefered cloud API.
-# The following implementation runs each worker as a subprocess on the local
-# machine.
-
-MODELS_DIR="/tmp/models"
-
-# Get command line options.
-OPTS=$(getopt -n "$0" -o "" --long "job_name:,config:,num_tuners:,num_workers_per_tuner:,num_ps_per_tuner:,max_npe:,num_repetitions:,stop_on_success:,fixed_hparams:,hparam_space_type:" -- "$@")
-if [ $? != 0 ] ; then echo "Failed parsing options." >&2 ; exit 1 ; fi
-
-eval set -- "$OPTS"
-
-JOB_NAME="" # Name of the process and the logs directory.
-CONFIG="" # Model and environment hparams.
-# NUM_TUNERS: Number of tuning jobs to launch. Each tuning job can train a
-# hparam combination. So more tuners means more hparams tried in parallel.
-NUM_TUNERS=1
-# NUM_WORKERS_PER_TUNER: Number of workers to launch for each tuning job. If
-# using neural networks, each worker will be 1 replica.
-NUM_WORKERS_PER_TUNER=1
-# NUM_PS_PER_TUNER: Number of parameter servers to launch for this tuning job.
-# Only set this if using neural networks. For 1 worker per tuner, no parameter
-# servers are needed. For more than 1 worker per tuner, at least 1 parameter
-# server per tuner is needed to store the global model for each tuner.
-NUM_PS_PER_TUNER=0
-# MAX_NPE: Maximum number of programs executed. Training will quit once this
-# threshold is reached. If 0, the threshold is infinite.
-MAX_NPE=0
-NUM_REPETITIONS=25 # How many times to run this experiment.
-STOP_ON_SUCCESS=true # Whether to halt training when a solution is found.
-# FIXED_HPARAMS: Hold hparams fixed in the grid search. This reduces the search
-# space.
-FIXED_HPARAMS=""
-# HPARAM_SPACE_TYPE: Specifies the hparam search space. See
-# `define_tuner_hparam_space` functions defined in pg_train.py and ga_train.py.
-HPARAM_SPACE_TYPE="pg"
-
-# Parse options into variables.
-while true; do
- case "$1" in
- --job_name ) JOB_NAME="$2"; shift; shift ;;
- --config ) CONFIG="$2"; shift; shift ;;
- --num_tuners ) NUM_TUNERS="$2"; shift; shift ;;
- --num_workers_per_tuner ) NUM_WORKERS_PER_TUNER="$2"; shift; shift ;;
- --num_ps_per_tuner ) NUM_PS_PER_TUNER="$2"; shift; shift ;;
- --max_npe ) MAX_NPE="$2"; shift; shift ;;
- --num_repetitions ) NUM_REPETITIONS="$2"; shift; shift ;;
- --stop_on_success ) STOP_ON_SUCCESS="$2"; shift; shift ;;
- --fixed_hparams ) FIXED_HPARAMS="$2"; shift; shift ;;
- --hparam_space_type ) HPARAM_SPACE_TYPE="$2"; shift; shift ;;
- -- ) shift; break ;;
- * ) break ;;
- esac
-done
-
-# Launch jobs.
-# TODO: multi-worker RL training
-
-LOGDIR="$MODELS_DIR/$JOB_NAME"
-mkdir -p $LOGDIR
-
-BIN_DIR="bazel-bin/single_task"
-for ((tuner=0;tuner "$LOGDIR/tuner_$tuner.task_$i.log" & # Run as subprocess
- echo "Launched tuner $tuner, task $i. Logs: $LOGDIR/tuner_$tuner.task_$i.log"
- done
-done
-
-# Use "pidof tune.par" to find jobs.
-# Kill with "pkill tune.par"
diff --git a/research/brain_coder/single_task/misc.py b/research/brain_coder/single_task/misc.py
deleted file mode 100644
index 07061d81c8aaafd4d97efc11ecca451528c6e9dd..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/misc.py
+++ /dev/null
@@ -1,149 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Utilities specific to this project."""
-
-from collections import namedtuple
-from six import string_types
-
-
-#####################
-# BF-lang utilities #
-#####################
-
-
-BF_EOS_INT = 0 # Also used as SOS (start of sequence).
-BF_EOS_CHAR = TEXT_EOS_CHAR = '_'
-BF_LANG_INTS = range(1, 9)
-BF_INT_TO_CHAR = [BF_EOS_CHAR, '>', '<', '+', '-', '[', ']', '.', ',']
-BF_CHAR_TO_INT = dict([(c, i) for i, c in enumerate(BF_INT_TO_CHAR)])
-
-
-RewardInfo = namedtuple('RewardInfo', ['episode_rewards', 'input_case',
- 'correct_output',
- 'code_output', 'reason', 'input_type',
- 'output_type'])
-
-
-class IOType(object):
- string = 'string'
- integer = 'integer'
- boolean = 'boolean'
-
-
-class IOTuple(tuple):
- pass
-
-
-def flatten(lst):
- return [item for row in lst for item in row]
-
-
-def bf_num_tokens():
- # BF tokens plus EOS.
- return len(BF_INT_TO_CHAR)
-
-
-def bf_char2int(bf_char):
- """Convert BF code char to int token."""
- return BF_CHAR_TO_INT[bf_char]
-
-
-def bf_int2char(bf_int):
- """Convert BF int token to code char."""
- return BF_INT_TO_CHAR[bf_int]
-
-
-def bf_tokens_to_string(bf_tokens, truncate=True):
- """Convert token list to code string. Will truncate at EOS token.
-
- Args:
- bf_tokens: Python list of ints representing the code string.
- truncate: If true, the output string will end at the first EOS token.
- If false, the entire token list is converted to string.
-
- Returns:
- String representation of the tokens.
-
- Raises:
- ValueError: If bf_tokens is not a python list.
- """
- if not isinstance(bf_tokens, list):
- raise ValueError('Only python list supported here.')
- if truncate:
- try:
- eos_index = bf_tokens.index(BF_EOS_INT)
- except ValueError:
- eos_index = len(bf_tokens)
- else:
- eos_index = len(bf_tokens)
- return ''.join([BF_INT_TO_CHAR[t] for t in bf_tokens[:eos_index]])
-
-
-def bf_string_to_tokens(bf_string):
- """Convert string to token list. Will strip and append EOS token."""
- tokens = [BF_CHAR_TO_INT[char] for char in bf_string.strip()]
- tokens.append(BF_EOS_INT)
- return tokens
-
-
-def tokens_to_text(tokens):
- """Convert token list to human readable text."""
- return ''.join(
- [TEXT_EOS_CHAR if t == 0 else chr(t - 1 + ord('A')) for t in tokens])
-
-
-###################################
-# Number representation utilities #
-###################################
-
-
-# https://en.wikipedia.org/wiki/Metric_prefix
-si_magnitudes = {
- 'k': 1e3,
- 'm': 1e6,
- 'g': 1e9}
-
-
-def si_to_int(s):
- """Convert string ending with SI magnitude to int.
-
- Examples: 5K ==> 5000, 12M ==> 12000000.
-
- Args:
- s: String in the form 'xx..xP' where x is a digit and P is an SI prefix.
-
- Returns:
- Integer equivalent to the string.
- """
- if isinstance(s, string_types) and s[-1].lower() in si_magnitudes.keys():
- return int(int(s[:-1]) * si_magnitudes[s[-1].lower()])
- return int(s)
-
-
-def int_to_si(n):
- """Convert integer to string with SI magnitude.
-
- `n` will be truncated.
-
- Examples: 5432 ==> 5k, 12345678 ==> 12M
-
- Args:
- n: Integer to represent as a string.
-
- Returns:
- String representation of `n` containing SI magnitude.
- """
- m = abs(n)
- sign = -1 if n < 0 else 1
- if m < 1e3:
- return str(n)
- if m < 1e6:
- return '{0}K'.format(sign*int(m / 1e3))
- if m < 1e9:
- return '{0}M'.format(sign*int(m / 1e6))
- if m < 1e12:
- return '{0}G'.format(sign*int(m / 1e9))
- return str(m)
-
diff --git a/research/brain_coder/single_task/pg_agent.py b/research/brain_coder/single_task/pg_agent.py
deleted file mode 100644
index 13fc7da2dc89a1fbcc7fa5efbbce87008580aa92..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/pg_agent.py
+++ /dev/null
@@ -1,1297 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Language model agent.
-
-Agent outputs code in a sequence just like a language model. Can be trained
-as a language model or using RL, or a combination of the two.
-"""
-
-from collections import namedtuple
-from math import exp
-from math import log
-import time
-
-from absl import logging
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-from common import rollout as rollout_lib # brain coder
-from common import utils # brain coder
-from single_task import misc # brain coder
-
-
-# Experiments in the ICLR 2018 paper used reduce_sum instead of reduce_mean for
-# some losses. We make all loses be batch_size independent, and multiply the
-# changed losses by 64, which was the fixed batch_size when the experiments
-# where run. The loss hyperparameters still match what is reported in the paper.
-MAGIC_LOSS_MULTIPLIER = 64
-
-
-def rshift_time(tensor_2d, fill=misc.BF_EOS_INT):
- """Right shifts a 2D tensor along the time dimension (axis-1)."""
- dim_0 = tf.shape(tensor_2d)[0]
- fill_tensor = tf.fill([dim_0, 1], fill)
- return tf.concat([fill_tensor, tensor_2d[:, :-1]], axis=1)
-
-
-def join(a, b):
- # Concat a and b along 0-th dim.
- if a is None or len(a) == 0: # pylint: disable=g-explicit-length-test
- return b
- if b is None or len(b) == 0: # pylint: disable=g-explicit-length-test
- return a
- return np.concatenate((a, b))
-
-
-def make_optimizer(kind, lr):
- if kind == 'sgd':
- return tf.train.GradientDescentOptimizer(lr)
- elif kind == 'adam':
- return tf.train.AdamOptimizer(lr)
- elif kind == 'rmsprop':
- return tf.train.RMSPropOptimizer(learning_rate=lr, decay=0.99)
- else:
- raise ValueError('Optimizer type "%s" not recognized.' % kind)
-
-
-class LinearWrapper(tf.contrib.rnn.RNNCell):
- """RNNCell wrapper that adds a linear layer to the output."""
-
- def __init__(self, cell, output_size, dtype=tf.float32, suppress_index=None):
- self.cell = cell
- self._output_size = output_size
- self._dtype = dtype
- self._suppress_index = suppress_index
- self.smallest_float = -2.4e38
-
- def __call__(self, inputs, state, scope=None):
- with tf.variable_scope(type(self).__name__):
- outputs, state = self.cell(inputs, state, scope=scope)
- logits = tf.matmul(
- outputs,
- tf.get_variable('w_output',
- [self.cell.output_size, self.output_size],
- dtype=self._dtype))
- if self._suppress_index is not None:
- # Replace the target index with -inf, so that it never gets selected.
- batch_size = tf.shape(logits)[0]
- logits = tf.concat(
- [logits[:, :self._suppress_index],
- tf.fill([batch_size, 1], self.smallest_float),
- logits[:, self._suppress_index + 1:]],
- axis=1)
-
- return logits, state
-
- @property
- def output_size(self):
- return self._output_size
-
- @property
- def state_size(self):
- return self.cell.state_size
-
- def zero_state(self, batch_size, dtype):
- return self.cell.zero_state(batch_size, dtype)
-
-
-UpdateStepResult = namedtuple(
- 'UpdateStepResult',
- ['global_step', 'global_npe', 'summaries_list', 'gradients_dict'])
-
-
-class AttrDict(dict):
- """Dict with attributes as keys.
-
- https://stackoverflow.com/a/14620633
- """
-
- def __init__(self, *args, **kwargs):
- super(AttrDict, self).__init__(*args, **kwargs)
- self.__dict__ = self
-
-
-class LMAgent(object):
- """Language model agent."""
- action_space = misc.bf_num_tokens()
- observation_space = misc.bf_num_tokens()
-
- def __init__(self, global_config, task_id=0,
- logging_file=None,
- experience_replay_file=None,
- global_best_reward_fn=None,
- found_solution_op=None,
- assign_code_solution_fn=None,
- program_count=None,
- do_iw_summaries=False,
- stop_on_success=True,
- dtype=tf.float32,
- verbose_level=0,
- is_local=True):
- self.config = config = global_config.agent
- self.logging_file = logging_file
- self.experience_replay_file = experience_replay_file
- self.task_id = task_id
- self.verbose_level = verbose_level
- self.global_best_reward_fn = global_best_reward_fn
- self.found_solution_op = found_solution_op
- self.assign_code_solution_fn = assign_code_solution_fn
- self.parent_scope_name = tf.get_variable_scope().name
- self.dtype = dtype
- self.allow_eos_token = config.eos_token
- self.stop_on_success = stop_on_success
- self.pi_loss_hparam = config.pi_loss_hparam
- self.vf_loss_hparam = config.vf_loss_hparam
- self.is_local = is_local
-
- self.top_reward = 0.0
- self.embeddings_trainable = True
-
- self.no_op = tf.no_op()
-
- self.learning_rate = tf.constant(
- config.lr, dtype=dtype, name='learning_rate')
- self.initializer = tf.contrib.layers.variance_scaling_initializer(
- factor=config.param_init_factor,
- mode='FAN_AVG',
- uniform=True,
- dtype=dtype) # TF's default initializer.
- tf.get_variable_scope().set_initializer(self.initializer)
-
- self.a2c = config.ema_baseline_decay == 0
- if not self.a2c:
- logging.info('Using exponential moving average REINFORCE baselines.')
- self.ema_baseline_decay = config.ema_baseline_decay
- self.ema_by_len = [0.0] * global_config.timestep_limit
- else:
- logging.info('Using advantage (a2c) with learned value function.')
- self.ema_baseline_decay = 0.0
- self.ema_by_len = None
-
- # Top-k
- if config.topk and config.topk_loss_hparam:
- self.topk_loss_hparam = config.topk_loss_hparam
- self.topk_batch_size = config.topk_batch_size
- if self.topk_batch_size <= 0:
- raise ValueError('topk_batch_size must be a positive integer. Got %s',
- self.topk_batch_size)
- self.top_episodes = utils.MaxUniquePriorityQueue(config.topk)
- logging.info('Made max-priorty-queue with capacity %d',
- self.top_episodes.capacity)
- else:
- self.top_episodes = None
- self.topk_loss_hparam = 0.0
- logging.info('No max-priorty-queue')
-
- # Experience replay.
- self.replay_temperature = config.replay_temperature
- self.num_replay_per_batch = int(global_config.batch_size * config.alpha)
- self.num_on_policy_per_batch = (
- global_config.batch_size - self.num_replay_per_batch)
- self.replay_alpha = (
- self.num_replay_per_batch / float(global_config.batch_size))
- logging.info('num_replay_per_batch: %d', self.num_replay_per_batch)
- logging.info('num_on_policy_per_batch: %d', self.num_on_policy_per_batch)
- logging.info('replay_alpha: %s', self.replay_alpha)
- if self.num_replay_per_batch > 0:
- # Train with off-policy episodes from replay buffer.
- start_time = time.time()
- self.experience_replay = utils.RouletteWheel(
- unique_mode=True, save_file=experience_replay_file)
- logging.info('Took %s sec to load replay buffer from disk.',
- int(time.time() - start_time))
- logging.info('Replay buffer file location: "%s"',
- self.experience_replay.save_file)
- else:
- # Only train on-policy.
- self.experience_replay = None
-
- if program_count is not None:
- self.program_count = program_count
- self.program_count_add_ph = tf.placeholder(
- tf.int64, [], 'program_count_add_ph')
- self.program_count_add_op = self.program_count.assign_add(
- self.program_count_add_ph)
-
- ################################
- # RL policy and value networks #
- ################################
- batch_size = global_config.batch_size
- logging.info('batch_size: %d', batch_size)
-
- self.policy_cell = LinearWrapper(
- tf.contrib.rnn.MultiRNNCell(
- [tf.contrib.rnn.BasicLSTMCell(cell_size)
- for cell_size in config.policy_lstm_sizes]),
- self.action_space,
- dtype=dtype,
- suppress_index=None if self.allow_eos_token else misc.BF_EOS_INT)
- self.value_cell = LinearWrapper(
- tf.contrib.rnn.MultiRNNCell(
- [tf.contrib.rnn.BasicLSTMCell(cell_size)
- for cell_size in config.value_lstm_sizes]),
- 1,
- dtype=dtype)
-
- obs_embedding_scope = 'obs_embed'
- with tf.variable_scope(
- obs_embedding_scope,
- initializer=tf.random_uniform_initializer(minval=-1.0, maxval=1.0)):
- obs_embeddings = tf.get_variable(
- 'embeddings',
- [self.observation_space, config.obs_embedding_size],
- dtype=dtype, trainable=self.embeddings_trainable)
- self.obs_embeddings = obs_embeddings
-
- ################################
- # RL policy and value networks #
- ################################
-
- initial_state = tf.fill([batch_size], misc.BF_EOS_INT)
- def loop_fn(loop_time, cell_output, cell_state, loop_state):
- """Function called by tf.nn.raw_rnn to instantiate body of the while_loop.
-
- See https://www.tensorflow.org/api_docs/python/tf/nn/raw_rnn for more
- information.
-
- When time is 0, and cell_output, cell_state, loop_state are all None,
- `loop_fn` will create the initial input, internal cell state, and loop
- state. When time > 0, `loop_fn` will operate on previous cell output,
- state, and loop state.
-
- Args:
- loop_time: A scalar tensor holding the current timestep (zero based
- counting).
- cell_output: Output of the raw_rnn cell at the current timestep.
- cell_state: Cell internal state at the current timestep.
- loop_state: Additional loop state. These tensors were returned by the
- previous call to `loop_fn`.
-
- Returns:
- elements_finished: Bool tensor of shape [batch_size] which marks each
- sequence in the batch as being finished or not finished.
- next_input: A tensor containing input to be fed into the cell at the
- next timestep.
- next_cell_state: Cell internal state to be fed into the cell at the
- next timestep.
- emit_output: Tensor to be added to the TensorArray returned by raw_rnn
- as output from the while_loop.
- next_loop_state: Additional loop state. These tensors will be fed back
- into the next call to `loop_fn` as `loop_state`.
- """
- if cell_output is None: # 0th time step.
- next_cell_state = self.policy_cell.zero_state(batch_size, dtype)
- elements_finished = tf.zeros([batch_size], tf.bool)
- output_lengths = tf.ones([batch_size], dtype=tf.int32)
- next_input = tf.gather(obs_embeddings, initial_state)
- emit_output = None
- next_loop_state = (
- tf.TensorArray(dtype=tf.int32, size=0, dynamic_size=True),
- output_lengths,
- elements_finished
- )
- else:
- scaled_logits = cell_output * config.softmax_tr # Scale temperature.
- prev_chosen, prev_output_lengths, prev_elements_finished = loop_state
- next_cell_state = cell_state
- chosen_outputs = tf.to_int32(tf.where(
- tf.logical_not(prev_elements_finished),
- tf.multinomial(logits=scaled_logits, num_samples=1)[:, 0],
- tf.zeros([batch_size], dtype=tf.int64)))
- elements_finished = tf.logical_or(
- tf.equal(chosen_outputs, misc.BF_EOS_INT),
- loop_time >= global_config.timestep_limit)
- output_lengths = tf.where(
- elements_finished,
- prev_output_lengths,
- # length includes EOS token. empty seq has len 1.
- tf.tile(tf.expand_dims(loop_time + 1, 0), [batch_size])
- )
- next_input = tf.gather(obs_embeddings, chosen_outputs)
- emit_output = scaled_logits
- next_loop_state = (prev_chosen.write(loop_time - 1, chosen_outputs),
- output_lengths,
- tf.logical_or(prev_elements_finished,
- elements_finished))
- return (elements_finished, next_input, next_cell_state, emit_output,
- next_loop_state)
-
- with tf.variable_scope('policy'):
- (decoder_outputs_ta,
- _, # decoder_state
- (sampled_output_ta, output_lengths, _)) = tf.nn.raw_rnn(
- cell=self.policy_cell,
- loop_fn=loop_fn)
- policy_logits = tf.transpose(decoder_outputs_ta.stack(), (1, 0, 2),
- name='policy_logits')
- sampled_tokens = tf.transpose(sampled_output_ta.stack(), (1, 0),
- name='sampled_tokens')
- # Add SOS to beginning of the sequence.
- rshift_sampled_tokens = rshift_time(sampled_tokens, fill=misc.BF_EOS_INT)
-
- # Initial state is 0, 2nd state is first token.
- # Note: If value of last state is computed, this will be used as bootstrap.
- if self.a2c:
- with tf.variable_scope('value'):
- value_output, _ = tf.nn.dynamic_rnn(
- self.value_cell,
- tf.gather(obs_embeddings, rshift_sampled_tokens),
- sequence_length=output_lengths,
- dtype=dtype)
- value = tf.squeeze(value_output, axis=[2])
- else:
- value = tf.zeros([], dtype=dtype)
-
- # for sampling actions from the agent, and which told tensors for doing
- # gradient updates on the agent.
- self.sampled_batch = AttrDict(
- logits=policy_logits,
- value=value,
- tokens=sampled_tokens,
- episode_lengths=output_lengths,
- probs=tf.nn.softmax(policy_logits),
- log_probs=tf.nn.log_softmax(policy_logits))
-
- # adjusted_lengths can be less than the full length of each episode.
- # Use this to train on only part of an episode (starting from t=0).
- self.adjusted_lengths = tf.placeholder(
- tf.int32, [None], name='adjusted_lengths')
- self.policy_multipliers = tf.placeholder(
- dtype,
- [None, None],
- name='policy_multipliers')
- # Empirical value, i.e. discounted sum of observed future rewards from each
- # time step in the episode.
- self.empirical_values = tf.placeholder(
- dtype,
- [None, None],
- name='empirical_values')
-
- # Off-policy training. Just add supervised loss to the RL loss.
- self.off_policy_targets = tf.placeholder(
- tf.int32,
- [None, None],
- name='off_policy_targets')
- self.off_policy_target_lengths = tf.placeholder(
- tf.int32, [None], name='off_policy_target_lengths')
-
- self.actions = tf.placeholder(tf.int32, [None, None], name='actions')
- # Add SOS to beginning of the sequence.
- inputs = rshift_time(self.actions, fill=misc.BF_EOS_INT)
- with tf.variable_scope('policy', reuse=True):
- logits, _ = tf.nn.dynamic_rnn(
- self.policy_cell, tf.gather(obs_embeddings, inputs),
- sequence_length=self.adjusted_lengths,
- dtype=dtype)
-
- if self.a2c:
- with tf.variable_scope('value', reuse=True):
- value_output, _ = tf.nn.dynamic_rnn(
- self.value_cell,
- tf.gather(obs_embeddings, inputs),
- sequence_length=self.adjusted_lengths,
- dtype=dtype)
- value2 = tf.squeeze(value_output, axis=[2])
- else:
- value2 = tf.zeros([], dtype=dtype)
-
- self.given_batch = AttrDict(
- logits=logits,
- value=value2,
- tokens=sampled_tokens,
- episode_lengths=self.adjusted_lengths,
- probs=tf.nn.softmax(logits),
- log_probs=tf.nn.log_softmax(logits))
-
- # Episode masks.
- max_episode_length = tf.shape(self.actions)[1]
- # range_row shape: [1, max_episode_length]
- range_row = tf.expand_dims(tf.range(max_episode_length), 0)
- episode_masks = tf.cast(
- tf.less(range_row, tf.expand_dims(self.given_batch.episode_lengths, 1)),
- dtype=dtype)
- episode_masks_3d = tf.expand_dims(episode_masks, 2)
-
- # Length adjusted episodes.
- self.a_probs = a_probs = self.given_batch.probs * episode_masks_3d
- self.a_log_probs = a_log_probs = (
- self.given_batch.log_probs * episode_masks_3d)
- self.a_value = a_value = self.given_batch.value * episode_masks
- self.a_policy_multipliers = a_policy_multipliers = (
- self.policy_multipliers * episode_masks)
- if self.a2c:
- self.a_empirical_values = a_empirical_values = (
- self.empirical_values * episode_masks)
-
- # pi_loss is scalar
- acs_onehot = tf.one_hot(self.actions, self.action_space, dtype=dtype)
- self.acs_onehot = acs_onehot
- chosen_masked_log_probs = acs_onehot * a_log_probs
- pi_target = tf.expand_dims(a_policy_multipliers, -1)
- pi_loss_per_step = chosen_masked_log_probs * pi_target # Maximize.
- self.pi_loss = pi_loss = (
- -tf.reduce_mean(tf.reduce_sum(pi_loss_per_step, axis=[1, 2]), axis=0)
- * MAGIC_LOSS_MULTIPLIER) # Minimize.
- assert len(self.pi_loss.shape) == 0 # pylint: disable=g-explicit-length-test
-
- # shape: [batch_size, time]
- self.chosen_log_probs = tf.reduce_sum(chosen_masked_log_probs, axis=2)
- self.chosen_probs = tf.reduce_sum(acs_onehot * a_probs, axis=2)
-
- # loss of value function
- if self.a2c:
- vf_loss_per_step = tf.square(a_value - a_empirical_values)
- self.vf_loss = vf_loss = (
- tf.reduce_mean(tf.reduce_sum(vf_loss_per_step, axis=1), axis=0)
- * MAGIC_LOSS_MULTIPLIER) # Minimize.
- assert len(self.vf_loss.shape) == 0 # pylint: disable=g-explicit-length-test
- else:
- self.vf_loss = vf_loss = 0.0
-
- # Maximize entropy regularizer
- self.entropy = entropy = (
- -tf.reduce_mean(
- tf.reduce_sum(a_probs * a_log_probs, axis=[1, 2]), axis=0)
- * MAGIC_LOSS_MULTIPLIER) # Maximize
- self.negentropy = -entropy # Minimize negentropy.
- assert len(self.negentropy.shape) == 0 # pylint: disable=g-explicit-length-test
-
- # off-policy loss
- self.offp_switch = tf.placeholder(dtype, [], name='offp_switch')
- if self.top_episodes is not None:
- # Add SOS to beginning of the sequence.
- offp_inputs = tf.gather(obs_embeddings,
- rshift_time(self.off_policy_targets,
- fill=misc.BF_EOS_INT))
- with tf.variable_scope('policy', reuse=True):
- offp_logits, _ = tf.nn.dynamic_rnn(
- self.policy_cell, offp_inputs, self.off_policy_target_lengths,
- dtype=dtype) # shape: [batch_size, time, action_space]
- topk_loss_per_step = tf.nn.sparse_softmax_cross_entropy_with_logits(
- labels=self.off_policy_targets,
- logits=offp_logits,
- name='topk_loss_per_logit')
- # Take mean over batch dimension so that the loss multiplier strength is
- # independent of batch size. Sum over time dimension.
- topk_loss = tf.reduce_mean(
- tf.reduce_sum(topk_loss_per_step, axis=1), axis=0)
- assert len(topk_loss.shape) == 0 # pylint: disable=g-explicit-length-test
- self.topk_loss = topk_loss * self.offp_switch
- logging.info('Including off policy loss.')
- else:
- self.topk_loss = topk_loss = 0.0
-
- self.entropy_hparam = tf.constant(
- config.entropy_beta, dtype=dtype, name='entropy_beta')
-
- self.pi_loss_term = pi_loss * self.pi_loss_hparam
- self.vf_loss_term = vf_loss * self.vf_loss_hparam
- self.entropy_loss_term = self.negentropy * self.entropy_hparam
- self.topk_loss_term = self.topk_loss_hparam * topk_loss
- self.loss = (
- self.pi_loss_term
- + self.vf_loss_term
- + self.entropy_loss_term
- + self.topk_loss_term)
-
- params = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES,
- tf.get_variable_scope().name)
- self.trainable_variables = params
- self.sync_variables = self.trainable_variables
- non_embedding_params = [p for p in params
- if obs_embedding_scope not in p.name]
- self.non_embedding_params = non_embedding_params
- self.params = params
-
- if config.regularizer:
- logging.info('Adding L2 regularizer with scale %.2f.',
- config.regularizer)
- self.regularizer = config.regularizer * sum(
- tf.nn.l2_loss(w) for w in non_embedding_params)
- self.loss += self.regularizer
- else:
- logging.info('Skipping regularizer.')
- self.regularizer = 0.0
-
- # Only build gradients graph for local model.
- if self.is_local:
- unclipped_grads = tf.gradients(self.loss, params)
- self.dense_unclipped_grads = [
- tf.convert_to_tensor(g) for g in unclipped_grads]
- self.grads, self.global_grad_norm = tf.clip_by_global_norm(
- unclipped_grads, config.grad_clip_threshold)
- self.gradients_dict = dict(zip(params, self.grads))
- self.optimizer = make_optimizer(config.optimizer, self.learning_rate)
- self.all_variables = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES,
- tf.get_variable_scope().name)
-
- self.do_iw_summaries = do_iw_summaries
- if self.do_iw_summaries:
- b = None
- self.log_iw_replay_ph = tf.placeholder(tf.float32, [b],
- 'log_iw_replay_ph')
- self.log_iw_policy_ph = tf.placeholder(tf.float32, [b],
- 'log_iw_policy_ph')
- self.log_prob_replay_ph = tf.placeholder(tf.float32, [b],
- 'log_prob_replay_ph')
- self.log_prob_policy_ph = tf.placeholder(tf.float32, [b],
- 'log_prob_policy_ph')
- self.log_norm_replay_weights_ph = tf.placeholder(
- tf.float32, [b], 'log_norm_replay_weights_ph')
- self.iw_summary_op = tf.summary.merge([
- tf.summary.histogram('is/log_iw_replay', self.log_iw_replay_ph),
- tf.summary.histogram('is/log_iw_policy', self.log_iw_policy_ph),
- tf.summary.histogram('is/log_prob_replay', self.log_prob_replay_ph),
- tf.summary.histogram('is/log_prob_policy', self.log_prob_policy_ph),
- tf.summary.histogram(
- 'is/log_norm_replay_weights', self.log_norm_replay_weights_ph),
- ])
-
- def make_summary_ops(self):
- """Construct summary ops for the model."""
- # size = number of timesteps across entire batch. Number normalized by size
- # will not be affected by the amount of padding at the ends of sequences
- # in the batch.
- size = tf.cast(
- tf.reduce_sum(self.given_batch.episode_lengths), dtype=self.dtype)
- offp_size = tf.cast(tf.reduce_sum(self.off_policy_target_lengths),
- dtype=self.dtype)
- scope_prefix = self.parent_scope_name
-
- def _remove_prefix(prefix, name):
- assert name.startswith(prefix)
- return name[len(prefix):]
-
- # RL summaries.
- self.rl_summary_op = tf.summary.merge(
- [tf.summary.scalar('model/policy_loss', self.pi_loss / size),
- tf.summary.scalar('model/value_loss', self.vf_loss / size),
- tf.summary.scalar('model/topk_loss', self.topk_loss / offp_size),
- tf.summary.scalar('model/entropy', self.entropy / size),
- tf.summary.scalar('model/loss', self.loss / size),
- tf.summary.scalar('model/grad_norm',
- tf.global_norm(self.grads)),
- tf.summary.scalar('model/unclipped_grad_norm', self.global_grad_norm),
- tf.summary.scalar('model/non_embedding_var_norm',
- tf.global_norm(self.non_embedding_params)),
- tf.summary.scalar('hparams/entropy_beta', self.entropy_hparam),
- tf.summary.scalar('hparams/topk_loss_hparam', self.topk_loss_hparam),
- tf.summary.scalar('hparams/learning_rate', self.learning_rate),
- tf.summary.scalar('model/trainable_var_norm',
- tf.global_norm(self.trainable_variables)),
- tf.summary.scalar('loss/loss', self.loss),
- tf.summary.scalar('loss/entropy', self.entropy_loss_term),
- tf.summary.scalar('loss/vf', self.vf_loss_term),
- tf.summary.scalar('loss/policy', self.pi_loss_term),
- tf.summary.scalar('loss/offp', self.topk_loss_term)] +
- [tf.summary.scalar(
- 'param_norms/' + _remove_prefix(scope_prefix + '/', p.name),
- tf.norm(p))
- for p in self.params] +
- [tf.summary.scalar(
- 'grad_norms/' + _remove_prefix(scope_prefix + '/', p.name),
- tf.norm(g))
- for p, g in zip(self.params, self.grads)] +
- [tf.summary.scalar(
- 'unclipped_grad_norms/' + _remove_prefix(scope_prefix + '/',
- p.name),
- tf.norm(g))
- for p, g in zip(self.params, self.dense_unclipped_grads)])
-
- self.text_summary_placeholder = tf.placeholder(tf.string, shape=[])
- self.rl_text_summary_op = tf.summary.text('rl',
- self.text_summary_placeholder)
-
- def _rl_text_summary(self, session, step, npe, tot_r, num_steps,
- input_case, code_output, code, reason):
- """Logs summary about a single episode and creates a text_summary for TB.
-
- Args:
- session: tf.Session instance.
- step: Global training step.
- npe: Number of programs executed so far.
- tot_r: Total reward.
- num_steps: Number of timesteps in the episode (i.e. code length).
- input_case: Inputs for test cases.
- code_output: Outputs produced by running the code on the inputs.
- code: String representation of the code.
- reason: Reason for the reward assigned by the task.
-
- Returns:
- Serialized text summary data for tensorboard.
- """
- if not input_case:
- input_case = ' '
- if not code_output:
- code_output = ' '
- if not code:
- code = ' '
- text = (
- 'Tot R: **%.2f**; Len: **%d**; Reason: **%s**\n\n'
- 'Input: **`%s`**; Output: **`%s`**\n\nCode: **`%s`**'
- % (tot_r, num_steps, reason, input_case, code_output, code))
- text_summary = session.run(self.rl_text_summary_op,
- {self.text_summary_placeholder: text})
- logging.info(
- 'Step %d.\t NPE: %d\t Reason: %s.\t Tot R: %.2f.\t Length: %d. '
- '\tInput: %s \tOutput: %s \tProgram: %s',
- step, npe, reason, tot_r, num_steps, input_case,
- code_output, code)
- return text_summary
-
- def _rl_reward_summary(self, total_rewards):
- """Create summary ops that report on episode rewards.
-
- Creates summaries for average, median, max, and min rewards in the batch.
-
- Args:
- total_rewards: Tensor of shape [batch_size] containing the total reward
- from each episode in the batch.
-
- Returns:
- tf.Summary op.
- """
- tr = np.asarray(total_rewards)
- reward_summary = tf.Summary(value=[
- tf.Summary.Value(
- tag='reward/avg',
- simple_value=np.mean(tr)),
- tf.Summary.Value(
- tag='reward/med',
- simple_value=np.median(tr)),
- tf.Summary.Value(
- tag='reward/max',
- simple_value=np.max(tr)),
- tf.Summary.Value(
- tag='reward/min',
- simple_value=np.min(tr))])
- return reward_summary
-
- def _iw_summary(self, session, replay_iw, replay_log_probs,
- norm_replay_weights, on_policy_iw,
- on_policy_log_probs):
- """Compute summaries for importance weights at a given batch.
-
- Args:
- session: tf.Session instance.
- replay_iw: Importance weights for episodes from replay buffer.
- replay_log_probs: Total log probabilities of the replay episodes under the
- current policy.
- norm_replay_weights: Normalized replay weights, i.e. values in `replay_iw`
- divided by the total weight in the entire replay buffer. Note, this is
- also the probability of selecting each episode from the replay buffer
- (in a roulette wheel replay buffer).
- on_policy_iw: Importance weights for episodes sampled from the current
- policy.
- on_policy_log_probs: Total log probabilities of the on-policy episodes
- under the current policy.
-
- Returns:
- Serialized TF summaries. Use a summary writer to write these summaries to
- disk.
- """
- return session.run(
- self.iw_summary_op,
- {self.log_iw_replay_ph: np.log(replay_iw),
- self.log_iw_policy_ph: np.log(on_policy_iw),
- self.log_norm_replay_weights_ph: np.log(norm_replay_weights),
- self.log_prob_replay_ph: replay_log_probs,
- self.log_prob_policy_ph: on_policy_log_probs})
-
- def _compute_iw(self, policy_log_probs, replay_weights):
- """Compute importance weights for a batch of episodes.
-
- Arguments are iterables of length batch_size.
-
- Args:
- policy_log_probs: Log probability of each episode under the current
- policy.
- replay_weights: Weight of each episode in the replay buffer. 0 for
- episodes not sampled from the replay buffer (i.e. sampled from the
- policy).
-
- Returns:
- Numpy array of shape [batch_size] containing the importance weight for
- each episode in the batch.
- """
- log_total_replay_weight = log(self.experience_replay.total_weight)
-
- # importance weight
- # = 1 / [(1 - a) + a * exp(log(replay_weight / total_weight / p))]
- # = 1 / ((1-a) + a*q/p)
- a = float(self.replay_alpha)
- a_com = 1.0 - a # compliment of a
- importance_weights = np.asarray(
- [1.0 / (a_com
- + a * exp((log(replay_weight) - log_total_replay_weight)
- - log_p))
- if replay_weight > 0 else 1.0 / a_com
- for log_p, replay_weight
- in zip(policy_log_probs, replay_weights)])
- return importance_weights
-
- def update_step(self, session, rl_batch, train_op, global_step_op,
- return_gradients=False):
- """Perform gradient update on the model.
-
- Args:
- session: tf.Session instance.
- rl_batch: RLBatch instance from data.py. Use DataManager to create a
- RLBatch for each call to update_step. RLBatch contains a batch of
- tasks.
- train_op: A TF op which will perform the gradient update. LMAgent does not
- own its training op, so that trainers can do distributed training
- and construct a specialized training op.
- global_step_op: A TF op which will return the current global step when
- run (should not increment it).
- return_gradients: If True, the gradients will be saved and returned from
- this method call. This is useful for testing.
-
- Returns:
- Results from the update step in a UpdateStepResult namedtuple, including
- global step, global NPE, serialized summaries, and optionally gradients.
- """
- assert self.is_local
-
- # Do update for REINFORCE or REINFORCE + replay buffer.
- if self.experience_replay is None:
- # Train with on-policy REINFORCE.
-
- # Sample new programs from the policy.
- num_programs_from_policy = rl_batch.batch_size
- (batch_actions,
- batch_values,
- episode_lengths) = session.run(
- [self.sampled_batch.tokens, self.sampled_batch.value,
- self.sampled_batch.episode_lengths])
- if episode_lengths.size == 0:
- # This should not happen.
- logging.warn(
- 'Shapes:\n'
- 'batch_actions.shape: %s\n'
- 'batch_values.shape: %s\n'
- 'episode_lengths.shape: %s\n',
- batch_actions.shape, batch_values.shape, episode_lengths.shape)
-
- # Compute rewards.
- code_scores = compute_rewards(
- rl_batch, batch_actions, episode_lengths)
- code_strings = code_scores.code_strings
- batch_tot_r = code_scores.total_rewards
- test_cases = code_scores.test_cases
- code_outputs = code_scores.code_outputs
- reasons = code_scores.reasons
-
- # Process on-policy samples.
- batch_targets, batch_returns = process_episodes(
- code_scores.batch_rewards, episode_lengths, a2c=self.a2c,
- baselines=self.ema_by_len,
- batch_values=batch_values)
- batch_policy_multipliers = batch_targets
- batch_emp_values = batch_returns if self.a2c else [[]]
- adjusted_lengths = episode_lengths
-
- if self.top_episodes:
- assert len(self.top_episodes) > 0 # pylint: disable=g-explicit-length-test
- off_policy_targets = [
- item for item, _
- in self.top_episodes.random_sample(self.topk_batch_size)]
- off_policy_target_lengths = [len(t) for t in off_policy_targets]
- off_policy_targets = utils.stack_pad(off_policy_targets, pad_axes=0,
- dtype=np.int32)
- offp_switch = 1
- else:
- off_policy_targets = [[0]]
- off_policy_target_lengths = [1]
- offp_switch = 0
-
- fetches = {
- 'global_step': global_step_op,
- 'program_count': self.program_count,
- 'summaries': self.rl_summary_op,
- 'train_op': train_op,
- 'gradients': self.gradients_dict if return_gradients else self.no_op}
- fetched = session.run(
- fetches,
- {self.actions: batch_actions,
- self.empirical_values: batch_emp_values,
- self.policy_multipliers: batch_policy_multipliers,
- self.adjusted_lengths: adjusted_lengths,
- self.off_policy_targets: off_policy_targets,
- self.off_policy_target_lengths: off_policy_target_lengths,
- self.offp_switch: offp_switch})
-
- combined_adjusted_lengths = adjusted_lengths
- combined_returns = batch_returns
- else:
- # Train with REINFORCE + off-policy replay buffer by using importance
- # sampling.
-
- # Sample new programs from the policy.
- # Note: batch size is constant. A full batch will be sampled, but not all
- # programs will be executed and added to the replay buffer. Those which
- # are not executed will be discarded and not counted.
- batch_actions, batch_values, episode_lengths, log_probs = session.run(
- [self.sampled_batch.tokens, self.sampled_batch.value,
- self.sampled_batch.episode_lengths, self.sampled_batch.log_probs])
- if episode_lengths.size == 0:
- # This should not happen.
- logging.warn(
- 'Shapes:\n'
- 'batch_actions.shape: %s\n'
- 'batch_values.shape: %s\n'
- 'episode_lengths.shape: %s\n',
- batch_actions.shape, batch_values.shape, episode_lengths.shape)
-
- # Sample from experince replay buffer
- empty_replay_buffer = (
- self.experience_replay.is_empty()
- if self.experience_replay is not None else True)
- num_programs_from_replay_buff = (
- self.num_replay_per_batch if not empty_replay_buffer else 0)
- num_programs_from_policy = (
- rl_batch.batch_size - num_programs_from_replay_buff)
- if (not empty_replay_buffer) and num_programs_from_replay_buff:
- result = self.experience_replay.sample_many(
- num_programs_from_replay_buff)
- experience_samples, replay_weights = zip(*result)
- (replay_actions,
- replay_rewards,
- _, # log probs
- replay_adjusted_lengths) = zip(*experience_samples)
-
- replay_batch_actions = utils.stack_pad(replay_actions, pad_axes=0,
- dtype=np.int32)
-
- # compute log probs for replay samples under current policy
- all_replay_log_probs, = session.run(
- [self.given_batch.log_probs],
- {self.actions: replay_batch_actions,
- self.adjusted_lengths: replay_adjusted_lengths})
- replay_log_probs = [
- np.choose(replay_actions[i], all_replay_log_probs[i, :l].T).sum()
- for i, l in enumerate(replay_adjusted_lengths)]
- else:
- # Replay buffer is empty. Do not sample from it.
- replay_actions = None
- replay_policy_multipliers = None
- replay_adjusted_lengths = None
- replay_log_probs = None
- replay_weights = None
- replay_returns = None
- on_policy_weights = [0] * num_programs_from_replay_buff
-
- assert not self.a2c # TODO(danabo): Support A2C with importance sampling.
-
- # Compute rewards.
- code_scores = compute_rewards(
- rl_batch, batch_actions, episode_lengths,
- batch_size=num_programs_from_policy)
- code_strings = code_scores.code_strings
- batch_tot_r = code_scores.total_rewards
- test_cases = code_scores.test_cases
- code_outputs = code_scores.code_outputs
- reasons = code_scores.reasons
-
- # Process on-policy samples.
- p = num_programs_from_policy
- batch_targets, batch_returns = process_episodes(
- code_scores.batch_rewards, episode_lengths[:p], a2c=False,
- baselines=self.ema_by_len)
- batch_policy_multipliers = batch_targets
- batch_emp_values = [[]]
- on_policy_returns = batch_returns
-
- # Process off-policy samples.
- if (not empty_replay_buffer) and num_programs_from_replay_buff:
- offp_batch_rewards = [
- [0.0] * (l - 1) + [r]
- for l, r in zip(replay_adjusted_lengths, replay_rewards)]
- assert len(offp_batch_rewards) == num_programs_from_replay_buff
- assert len(replay_adjusted_lengths) == num_programs_from_replay_buff
- replay_batch_targets, replay_returns = process_episodes(
- offp_batch_rewards, replay_adjusted_lengths, a2c=False,
- baselines=self.ema_by_len)
- # Convert 2D array back into ragged 2D list.
- replay_policy_multipliers = [
- replay_batch_targets[i, :l]
- for i, l
- in enumerate(
- replay_adjusted_lengths[:num_programs_from_replay_buff])]
-
- adjusted_lengths = episode_lengths[:num_programs_from_policy]
-
- if self.top_episodes:
- assert len(self.top_episodes) > 0 # pylint: disable=g-explicit-length-test
- off_policy_targets = [
- item for item, _
- in self.top_episodes.random_sample(self.topk_batch_size)]
- off_policy_target_lengths = [len(t) for t in off_policy_targets]
- off_policy_targets = utils.stack_pad(off_policy_targets, pad_axes=0,
- dtype=np.int32)
- offp_switch = 1
- else:
- off_policy_targets = [[0]]
- off_policy_target_lengths = [1]
- offp_switch = 0
-
- # On-policy episodes.
- if num_programs_from_policy:
- separate_actions = [
- batch_actions[i, :l]
- for i, l in enumerate(adjusted_lengths)]
- chosen_log_probs = [
- np.choose(separate_actions[i], log_probs[i, :l].T)
- for i, l in enumerate(adjusted_lengths)]
- new_experiences = [
- (separate_actions[i],
- batch_tot_r[i],
- chosen_log_probs[i].sum(), l)
- for i, l in enumerate(adjusted_lengths)]
- on_policy_policy_multipliers = [
- batch_policy_multipliers[i, :l]
- for i, l in enumerate(adjusted_lengths)]
- (on_policy_actions,
- _, # rewards
- on_policy_log_probs,
- on_policy_adjusted_lengths) = zip(*new_experiences)
- else:
- new_experiences = []
- on_policy_policy_multipliers = []
- on_policy_actions = []
- on_policy_log_probs = []
- on_policy_adjusted_lengths = []
-
- if (not empty_replay_buffer) and num_programs_from_replay_buff:
- # Look for new experiences in replay buffer. Assign weight if an episode
- # is in the buffer.
- on_policy_weights = [0] * num_programs_from_policy
- for i, cs in enumerate(code_strings):
- if self.experience_replay.has_key(cs):
- on_policy_weights[i] = self.experience_replay.get_weight(cs)
-
- # Randomly select on-policy or off policy episodes to train on.
- combined_actions = join(replay_actions, on_policy_actions)
- combined_policy_multipliers = join(
- replay_policy_multipliers, on_policy_policy_multipliers)
- combined_adjusted_lengths = join(
- replay_adjusted_lengths, on_policy_adjusted_lengths)
- combined_returns = join(replay_returns, on_policy_returns)
- combined_actions = utils.stack_pad(combined_actions, pad_axes=0)
- combined_policy_multipliers = utils.stack_pad(combined_policy_multipliers,
- pad_axes=0)
- # P
- combined_on_policy_log_probs = join(replay_log_probs, on_policy_log_probs)
- # Q
- # Assume weight is zero for all sequences sampled from the policy.
- combined_q_weights = join(replay_weights, on_policy_weights)
-
- # Importance adjustment. Naive formulation:
- # E_{x~p}[f(x)] ~= 1/N sum_{x~p}(f(x)) ~= 1/N sum_{x~q}(f(x) * p(x)/q(x)).
- # p(x) is the policy, and q(x) is the off-policy distribution, i.e. replay
- # buffer distribution. Importance weight w(x) = p(x) / q(x).
-
- # Instead of sampling from the replay buffer only, we sample from a
- # mixture distribution of the policy and replay buffer.
- # We are sampling from the mixture a*q(x) + (1-a)*p(x), where 0 <= a <= 1.
- # Thus the importance weight w(x) = p(x) / (a*q(x) + (1-a)*p(x))
- # = 1 / ((1-a) + a*q(x)/p(x)) where q(x) is 0 for x sampled from the
- # policy.
- # Note: a = self.replay_alpha
- if empty_replay_buffer:
- # The replay buffer is empty.
- # Do no gradient update this step. The replay buffer will have stuff in
- # it next time.
- combined_policy_multipliers *= 0
- elif not num_programs_from_replay_buff:
- combined_policy_multipliers = np.ones([len(combined_actions), 1],
- dtype=np.float32)
- else:
- # If a < 1 compute importance weights
- # importance weight
- # = 1 / [(1 - a) + a * exp(log(replay_weight / total_weight / p))]
- # = 1 / ((1-a) + a*q/p)
- importance_weights = self._compute_iw(combined_on_policy_log_probs,
- combined_q_weights)
- if self.config.iw_normalize:
- importance_weights *= (
- float(rl_batch.batch_size) / importance_weights.sum())
- combined_policy_multipliers *= importance_weights.reshape(-1, 1)
-
- # Train on replay batch, top-k MLE.
- assert self.program_count is not None
- fetches = {
- 'global_step': global_step_op,
- 'program_count': self.program_count,
- 'summaries': self.rl_summary_op,
- 'train_op': train_op,
- 'gradients': self.gradients_dict if return_gradients else self.no_op}
- fetched = session.run(
- fetches,
- {self.actions: combined_actions,
- self.empirical_values: [[]], # replay_emp_values,
- self.policy_multipliers: combined_policy_multipliers,
- self.adjusted_lengths: combined_adjusted_lengths,
- self.off_policy_targets: off_policy_targets,
- self.off_policy_target_lengths: off_policy_target_lengths,
- self.offp_switch: offp_switch})
-
- # Add to experience replay buffer.
- self.experience_replay.add_many(
- objs=new_experiences,
- weights=[exp(r / self.replay_temperature) for r in batch_tot_r],
- keys=code_strings)
-
- # Update program count.
- session.run(
- [self.program_count_add_op],
- {self.program_count_add_ph: num_programs_from_policy})
-
- # Update EMA baselines on the mini-batch which we just did traning on.
- if not self.a2c:
- for i in xrange(rl_batch.batch_size):
- episode_length = combined_adjusted_lengths[i]
- empirical_returns = combined_returns[i, :episode_length]
- for j in xrange(episode_length):
- # Update ema_baselines in place.
- self.ema_by_len[j] = (
- self.ema_baseline_decay * self.ema_by_len[j]
- + (1 - self.ema_baseline_decay) * empirical_returns[j])
-
- global_step = fetched['global_step']
- global_npe = fetched['program_count']
- core_summaries = fetched['summaries']
- summaries_list = [core_summaries]
-
- if num_programs_from_policy:
- s_i = 0
- text_summary = self._rl_text_summary(
- session,
- global_step,
- global_npe,
- batch_tot_r[s_i],
- episode_lengths[s_i], test_cases[s_i],
- code_outputs[s_i], code_strings[s_i], reasons[s_i])
- reward_summary = self._rl_reward_summary(batch_tot_r)
-
- is_best = False
- if self.global_best_reward_fn:
- # Save best reward.
- best_reward = np.max(batch_tot_r)
- is_best = self.global_best_reward_fn(session, best_reward)
-
- if self.found_solution_op is not None and 'correct' in reasons:
- session.run(self.found_solution_op)
-
- # Save program to disk for record keeping.
- if self.stop_on_success:
- solutions = [
- {'code': code_strings[i], 'reward': batch_tot_r[i],
- 'npe': global_npe}
- for i in xrange(len(reasons)) if reasons[i] == 'correct']
- elif is_best:
- solutions = [
- {'code': code_strings[np.argmax(batch_tot_r)],
- 'reward': np.max(batch_tot_r),
- 'npe': global_npe}]
- else:
- solutions = []
- if solutions:
- if self.assign_code_solution_fn:
- self.assign_code_solution_fn(session, solutions[0]['code'])
- with tf.gfile.FastGFile(self.logging_file, 'a') as writer:
- for solution_dict in solutions:
- writer.write(str(solution_dict) + '\n')
-
- max_i = np.argmax(batch_tot_r)
- max_tot_r = batch_tot_r[max_i]
- if max_tot_r >= self.top_reward:
- if max_tot_r >= self.top_reward:
- self.top_reward = max_tot_r
- logging.info('Top code: r=%.2f, \t%s', max_tot_r, code_strings[max_i])
- if self.top_episodes is not None:
- self.top_episodes.push(
- max_tot_r, tuple(batch_actions[max_i, :episode_lengths[max_i]]))
-
- summaries_list += [text_summary, reward_summary]
-
- if self.do_iw_summaries and not empty_replay_buffer:
- # prob of replay samples under replay buffer sampling.
- norm_replay_weights = [
- w / self.experience_replay.total_weight
- for w in replay_weights]
- replay_iw = self._compute_iw(replay_log_probs, replay_weights)
- on_policy_iw = self._compute_iw(on_policy_log_probs, on_policy_weights)
- summaries_list.append(
- self._iw_summary(
- session, replay_iw, replay_log_probs, norm_replay_weights,
- on_policy_iw, on_policy_log_probs))
-
- return UpdateStepResult(
- global_step=global_step,
- global_npe=global_npe,
- summaries_list=summaries_list,
- gradients_dict=fetched['gradients'])
-
-
-def io_to_text(io_case, io_type):
- if isinstance(io_case, misc.IOTuple):
- # If there are many strings, join them with ','.
- return ','.join([io_to_text(e, io_type) for e in io_case])
- if io_type == misc.IOType.string:
- # There is one string. Return it.
- return misc.tokens_to_text(io_case)
- if (io_type == misc.IOType.integer
- or io_type == misc.IOType.boolean):
- if len(io_case) == 1:
- return str(io_case[0])
- return str(io_case)
-
-
-CodeScoreInfo = namedtuple(
- 'CodeScoreInfo',
- ['code_strings', 'batch_rewards', 'total_rewards', 'test_cases',
- 'code_outputs', 'reasons'])
-
-
-def compute_rewards(rl_batch, batch_actions, episode_lengths, batch_size=None):
- """Compute rewards for each episode in the batch.
-
- Args:
- rl_batch: A data.RLBatch instance. This holds information about the task
- each episode is solving, and a reward function for each episode.
- batch_actions: Contains batch of episodes. Each sequence of actions will be
- converted into a BF program and then scored. A numpy array of shape
- [batch_size, max_sequence_length].
- episode_lengths: The sequence length of each episode in the batch. Iterable
- of length batch_size.
- batch_size: (optional) number of programs to score. Use this to limit the
- number of programs executed from this batch. For example, when doing
- importance sampling some of the on-policy episodes will be discarded
- and they should not be executed. `batch_size` can be less than or equal
- to the size of the input batch.
-
- Returns:
- CodeScoreInfo namedtuple instance. This holds not just the computed rewards,
- but additional information computed during code execution which can be used
- for debugging and monitoring. this includes: BF code strings, test cases
- the code was executed on, code outputs from those test cases, and reasons
- for success or failure.
- """
- code_strings = [
- ''.join([misc.bf_int2char(a) for a in action_sequence[:l]])
- for action_sequence, l in zip(batch_actions, episode_lengths)]
- if batch_size is None:
- batch_size = len(code_strings)
- else:
- assert batch_size <= len(code_strings)
- code_strings = code_strings[:batch_size]
-
- if isinstance(rl_batch.reward_fns, (list, tuple)):
- # reward_fns is a list of functions, same length as code_strings.
- assert len(rl_batch.reward_fns) >= batch_size
- r_fn_results = [
- rl_batch.reward_fns[i](code_strings[i]) for i in xrange(batch_size)]
- else:
- # reward_fns is allowed to be one function which processes a batch of code
- # strings. This is useful for efficiency and batch level computation.
- r_fn_results = rl_batch.reward_fns(code_strings)
-
- # Expecting that r_fn returns a list of rewards. Length of list equals
- # length of the code string (including EOS char).
-
- batch_rewards = [r.episode_rewards for r in r_fn_results]
- total_rewards = [sum(b) for b in batch_rewards]
- test_cases = [io_to_text(r.input_case, r.input_type) for r in r_fn_results]
- code_outputs = [io_to_text(r.code_output, r.output_type)
- for r in r_fn_results]
- reasons = [r.reason for r in r_fn_results]
- return CodeScoreInfo(
- code_strings=code_strings,
- batch_rewards=batch_rewards,
- total_rewards=total_rewards,
- test_cases=test_cases,
- code_outputs=code_outputs,
- reasons=reasons)
-
-
-def process_episodes(
- batch_rewards, episode_lengths, a2c=False, baselines=None,
- batch_values=None):
- """Compute REINFORCE targets.
-
- REINFORCE here takes the form:
- grad_t = grad[log(pi(a_t|c_t))*target_t]
- where c_t is context: i.e. RNN state or environment state (or both).
-
- Two types of targets are supported:
- 1) Advantage actor critic (a2c).
- 2) Vanilla REINFORCE with baseline.
-
- Args:
- batch_rewards: Rewards received in each episode in the batch. A numpy array
- of shape [batch_size, max_sequence_length]. Note, these are per-timestep
- rewards, not total reward.
- episode_lengths: Length of each episode. An iterable of length batch_size.
- a2c: A bool. Whether to compute a2c targets (True) or vanilla targets
- (False).
- baselines: If a2c is False, provide baselines for each timestep. This is a
- list (or indexable container) of length max_time. Note: baselines are
- shared across all episodes, which is why there is no batch dimension.
- It is up to the caller to update baselines accordingly.
- batch_values: If a2c is True, provide values computed by a value estimator.
- A numpy array of shape [batch_size, max_sequence_length].
-
- Returns:
- batch_targets: REINFORCE targets for each episode and timestep. A numpy
- array of shape [batch_size, max_sequence_length].
- batch_returns: Returns computed for each episode and timestep. This is for
- reference, and is not used in the REINFORCE gradient update (but was
- used to compute the targets). A numpy array of shape
- [batch_size, max_sequence_length].
- """
- num_programs = len(batch_rewards)
- assert num_programs <= len(episode_lengths)
- batch_returns = [None] * num_programs
- batch_targets = [None] * num_programs
- for i in xrange(num_programs):
- episode_length = episode_lengths[i]
- assert len(batch_rewards[i]) == episode_length
- # Compute target for each timestep.
- # If we are computing A2C:
- # target_t = advantage_t = R_t - V(c_t)
- # where V(c_t) is a learned value function (provided as `values`).
- # Otherwise:
- # target_t = R_t - baselines[t]
- # where `baselines` are provided.
- # In practice we use a more generalized formulation of advantage. See docs
- # for `discounted_advantage_and_rewards`.
- if a2c:
- # Compute advantage.
- assert batch_values is not None
- episode_values = batch_values[i, :episode_length]
- episode_rewards = batch_rewards[i]
- emp_val, gen_adv = rollout_lib.discounted_advantage_and_rewards(
- episode_rewards, episode_values, gamma=1.0, lambda_=1.0)
- batch_returns[i] = emp_val
- batch_targets[i] = gen_adv
- else:
- # Compute return for each timestep. See section 3 of
- # https://arxiv.org/pdf/1602.01783.pdf
- assert baselines is not None
- empirical_returns = rollout_lib.discount(batch_rewards[i], gamma=1.0)
- targets = [None] * episode_length
- for j in xrange(episode_length):
- targets[j] = empirical_returns[j] - baselines[j]
- batch_returns[i] = empirical_returns
- batch_targets[i] = targets
- batch_returns = utils.stack_pad(batch_returns, 0)
- if num_programs:
- batch_targets = utils.stack_pad(batch_targets, 0)
- else:
- batch_targets = np.array([], dtype=np.float32)
-
- return (batch_targets, batch_returns)
diff --git a/research/brain_coder/single_task/pg_agent_test.py b/research/brain_coder/single_task/pg_agent_test.py
deleted file mode 100644
index 503d37ecacbf968b0786b3553e6a97667569bf7d..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/pg_agent_test.py
+++ /dev/null
@@ -1,395 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Tests for pg_agent."""
-
-from collections import Counter
-
-from absl import logging
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-from common import utils # brain coder
-from single_task import data # brain coder
-from single_task import defaults # brain coder
-from single_task import misc # brain coder
-from single_task import pg_agent as agent_lib # brain coder
-from single_task import pg_train # brain coder
-
-
-# Symmetric mean absolute percentage error (SMAPE).
-# https://en.wikipedia.org/wiki/Symmetric_mean_absolute_percentage_error
-def smape(a, b):
- return 2.0 * abs(a - b) / float(a + b)
-
-
-def onehot(dim, num_dims):
- value = np.zeros(num_dims, dtype=np.float32)
- value[dim] = 1
- return value
-
-
-def random_sequence(max_length, num_tokens, eos=0):
- length = np.random.randint(1, max_length - 1)
- return np.append(np.random.randint(1, num_tokens, length), eos)
-
-
-def repeat_and_pad(v, rep, total_len):
- return [v] * rep + [0.0] * (total_len - rep)
-
-
-class AgentTest(tf.test.TestCase):
-
- def testProcessEpisodes(self):
- batch_size = 3
-
- def reward_fn(code_string):
- return misc.RewardInfo(
- episode_rewards=[float(ord(c)) for c in code_string],
- input_case=[],
- correct_output=[],
- code_output=[],
- input_type=misc.IOType.integer,
- output_type=misc.IOType.integer,
- reason='none')
-
- rl_batch = data.RLBatch(
- reward_fns=[reward_fn for _ in range(batch_size)],
- batch_size=batch_size,
- good_reward=10.0)
- batch_actions = np.asarray([
- [4, 5, 3, 6, 8, 1, 0, 0],
- [1, 2, 3, 4, 0, 0, 0, 0],
- [8, 7, 6, 5, 4, 3, 2, 1]], dtype=np.int32)
- batch_values = np.asarray([
- [0, 1, 2, 1, 0, 1, 1, 0],
- [0, 2, 1, 2, 1, 0, 0, 0],
- [0, 1, 1, 0, 0, 0, 1, 1]], dtype=np.float32)
- episode_lengths = np.asarray([7, 5, 8], dtype=np.int32)
-
- scores = agent_lib.compute_rewards(
- rl_batch, batch_actions, episode_lengths)
- batch_targets, batch_returns = agent_lib.process_episodes(
- scores.batch_rewards, episode_lengths, a2c=True,
- batch_values=batch_values)
- self.assertEqual(
- [[473.0, 428.0, 337.0, 294.0, 201.0, 157.0, 95.0, 0.0],
- [305.0, 243.0, 183.0, 140.0, 95.0, 0.0, 0.0, 0.0],
- [484.0, 440.0, 394.0, 301.0, 210.0, 165.0, 122.0, 62.0]],
- batch_returns.tolist())
- self.assertEqual(
- [[473.0, 427.0, 335.0, 293.0, 201.0, 156.0, 94.0, 0.0],
- [305.0, 241.0, 182.0, 138.0, 94.0, 0.0, 0.0, 0.0],
- [484.0, 439.0, 393.0, 301.0, 210.0, 165.0, 121.0, 61.0]],
- batch_targets.tolist())
-
- def testVarUpdates(self):
- """Tests that variables get updated as expected.
-
- For the RL update, check that gradients are non-zero and that the global
- model gets updated.
- """
- config = defaults.default_config_with_updates(
- 'env=c(task="reverse"),'
- 'agent=c(algorithm="pg",eos_token=True,optimizer="sgd",lr=1.0)')
- lr = config.agent.lr
-
- tf.reset_default_graph()
- trainer = pg_train.AsyncTrainer(
- config, task_id=0, ps_tasks=0, num_workers=1)
- global_init_op = tf.variables_initializer(
- tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, 'global'))
- with tf.Session() as sess:
- sess.run(global_init_op) # Initialize global copy.
- trainer.initialize(sess)
- model = trainer.model
- global_vars = sess.run(trainer.global_model.trainable_variables)
- local_vars = sess.run(model.trainable_variables)
-
- # Make sure names match.
- g_prefix = 'global/'
- l_prefix = 'local/'
- for g, l in zip(trainer.global_model.trainable_variables,
- model.trainable_variables):
- self.assertEqual(g.name[len(g_prefix):], l.name[len(l_prefix):])
-
- # Assert that shapes and values are the same between global and local
- # models.
- for g, l in zip(global_vars, local_vars):
- self.assertEqual(g.shape, l.shape)
- self.assertTrue(np.array_equal(g, l))
-
- # Make all gradients dense tensors.
- for param, grad in model.gradients_dict.items():
- if isinstance(grad, tf.IndexedSlices):
- # Converts to dense tensor.
- model.gradients_dict[param] = tf.multiply(grad, 1.0)
-
- # Perform update.
- results = model.update_step(
- sess, trainer.data_manager.sample_rl_batch(), trainer.train_op,
- trainer.global_step, return_gradients=True)
- grads_dict = results.gradients_dict
- for grad in grads_dict.values():
- self.assertIsNotNone(grad)
- self.assertTrue(np.count_nonzero(grad) > 0)
- global_update = sess.run(trainer.global_model.trainable_variables)
- for tf_var, var_before, var_after in zip(
- model.trainable_variables, local_vars, global_update):
- # Check that the params were updated.
- self.assertTrue(np.allclose(
- var_after,
- var_before - grads_dict[tf_var] * lr))
-
- # Test that global to local sync works.
- sess.run(trainer.sync_op)
- global_vars = sess.run(trainer.global_model.trainable_variables)
- local_vars = sess.run(model.trainable_variables)
- for l, g in zip(local_vars, global_vars):
- self.assertTrue(np.allclose(l, g))
-
- def testMonteCarloGradients(self):
- """Test Monte Carlo estimate of REINFORCE gradient.
-
- Test that the Monte Carlo estimate of the REINFORCE gradient is
- approximately equal to the true gradient. We compute the true gradient for a
- toy environment with a very small action space.
-
- Similar to section 5 of https://arxiv.org/pdf/1505.00521.pdf.
- """
- # Test may have different outcome on different machines due to different
- # rounding behavior of float arithmetic.
- tf.reset_default_graph()
- tf.set_random_seed(12345678987654321)
- np.random.seed(1294024302)
- max_length = 2
- num_tokens = misc.bf_num_tokens()
- eos = misc.BF_EOS_INT
- assert eos == 0
- def sequence_iterator(max_length):
- """Iterates through all sequences up to the given length."""
- yield [eos]
- for a in xrange(1, num_tokens):
- if max_length > 1:
- for sub_seq in sequence_iterator(max_length - 1):
- yield [a] + sub_seq
- else:
- yield [a]
- actions = list(sequence_iterator(max_length))
-
- # This batch contains all possible episodes up to max_length.
- actions_batch = utils.stack_pad(actions, 0)
- lengths_batch = [len(s) for s in actions]
-
- reward_map = {tuple(a): np.random.randint(-1, 7) for a in actions_batch}
- # reward_map = {tuple(a): np.random.normal(3, 1)
- # for a in actions_batch} # normal distribution
- # reward_map = {tuple(a): 1.0
- # for a in actions_batch} # expected reward is 1
-
- n = 100000 # MC sample size.
- config = defaults.default_config_with_updates(
- 'env=c(task="print"),'
- 'agent=c(algorithm="pg",optimizer="sgd",lr=1.0,ema_baseline_decay=0.99,'
- 'entropy_beta=0.0,topk_loss_hparam=0.0,regularizer=0.0,'
- 'policy_lstm_sizes=[10],eos_token=True),'
- 'batch_size='+str(n)+',timestep_limit='+str(max_length))
-
- dtype = tf.float64
- trainer = pg_train.AsyncTrainer(
- config, task_id=0, ps_tasks=0, num_workers=1, dtype=dtype)
- model = trainer.model
- actions_ph = model.actions
- lengths_ph = model.adjusted_lengths
- multipliers_ph = model.policy_multipliers
-
- global_init_op = tf.variables_initializer(
- tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, 'global'))
- with tf.Session() as sess, sess.graph.as_default():
- sess.run(global_init_op) # Initialize global copy.
- trainer.initialize(sess)
-
- # Compute exact gradients.
- # exact_grads = sum(P(a) * grad(log P(a)) * R(a) for a in actions_batch)
- true_loss_unnormalized = 0.0
- exact_grads = [np.zeros(v.shape) for v in model.trainable_variables]
- episode_probs_map = {}
- grads_map = {}
- for a_idx in xrange(len(actions_batch)):
- a = actions_batch[a_idx]
- grads_result, probs_result, loss = sess.run(
- [model.dense_unclipped_grads, model.chosen_probs, model.loss],
- {actions_ph: [a],
- lengths_ph: [lengths_batch[a_idx]],
- multipliers_ph: [
- repeat_and_pad(reward_map[tuple(a)],
- lengths_batch[a_idx],
- max_length)]})
- # Take product over time axis.
- episode_probs_result = np.prod(probs_result[0, :lengths_batch[a_idx]])
- for i in range(0, len(exact_grads)):
- exact_grads[i] += grads_result[i] * episode_probs_result
- episode_probs_map[tuple(a)] = episode_probs_result
- reward_map[tuple(a)] = reward_map[tuple(a)]
- grads_map[tuple(a)] = grads_result
- true_loss_unnormalized += loss
- # Normalize loss. Since each episode is feed into the model one at a time,
- # normalization needs to be done manually.
- true_loss = true_loss_unnormalized / float(len(actions_batch))
-
- # Compute Monte Carlo gradients.
- # E_a~P[grad(log P(a)) R(a)] is aprox. eq. to
- # sum(grad(log P(a)) R(a) for a in actions_sampled_from_P) / n
- # where len(actions_sampled_from_P) == n.
- #
- # In other words, sample from the policy and compute the gradients of the
- # log probs weighted by the returns. This will excersize the code in
- # agent.py
- sampled_actions, sampled_lengths = sess.run(
- [model.sampled_tokens, model.episode_lengths])
- pi_multipliers = [
- repeat_and_pad(reward_map[tuple(a)], l, max_length)
- for a, l in zip(sampled_actions, sampled_lengths)]
- mc_grads_unnormalized, sampled_probs, mc_loss_unnormalized = sess.run(
- [model.dense_unclipped_grads, model.chosen_probs, model.loss],
- {actions_ph: sampled_actions,
- multipliers_ph: pi_multipliers,
- lengths_ph: sampled_lengths})
- # Loss is already normalized across the minibatch, so no normalization
- # is needed.
- mc_grads = mc_grads_unnormalized
- mc_loss = mc_loss_unnormalized
-
- # Make sure true loss and MC loss are similar.
- loss_error = smape(true_loss, mc_loss)
- self.assertTrue(loss_error < 0.15, msg='actual: %s' % loss_error)
-
- # Check that probs computed for episodes sampled from the model are the same
- # as the recorded true probs.
- for i in range(100):
- acs = tuple(sampled_actions[i].tolist())
- sampled_prob = np.prod(sampled_probs[i, :sampled_lengths[i]])
- self.assertTrue(np.isclose(episode_probs_map[acs], sampled_prob))
-
- # Make sure MC estimates of true probs are close.
- counter = Counter(tuple(e) for e in sampled_actions)
- for acs, count in counter.iteritems():
- mc_prob = count / float(len(sampled_actions))
- true_prob = episode_probs_map[acs]
- error = smape(mc_prob, true_prob)
- self.assertTrue(
- error < 0.15,
- msg='actual: %s; count: %s; mc_prob: %s; true_prob: %s'
- % (error, count, mc_prob, true_prob))
-
- # Manually recompute MC gradients and make sure they match MC gradients
- # computed in TF.
- mc_grads_recompute = [np.zeros(v.shape) for v in model.trainable_variables]
- for i in range(n):
- acs = tuple(sampled_actions[i].tolist())
- for i in range(0, len(mc_grads_recompute)):
- mc_grads_recompute[i] += grads_map[acs][i]
- for i in range(0, len(mc_grads_recompute)):
- self.assertTrue(np.allclose(mc_grads[i], mc_grads_recompute[i] / n))
-
- # Check angle between gradients as fraction of pi.
- for index in range(len(mc_grads)):
- v1 = mc_grads[index].reshape(-1)
- v2 = exact_grads[index].reshape(-1)
- # angle = arccos(v1 . v2 / (|v1|*|v2|))
- angle_rad = np.arccos(
- np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2)))
- logging.info('angle / pi: %s', angle_rad / np.pi)
- angle_frac = angle_rad / np.pi
- self.assertTrue(angle_frac < 0.02, msg='actual: %s' % angle_frac)
- # Check norms.
- for index in range(len(mc_grads)):
- v1_norm = np.linalg.norm(mc_grads[index].reshape(-1))
- v2_norm = np.linalg.norm(exact_grads[index].reshape(-1))
- error = smape(v1_norm, v2_norm)
- self.assertTrue(error < 0.02, msg='actual: %s' % error)
-
- # Check expected rewards.
- # E_a~P[R(a)] approx eq sum(P(a) * R(a) for a in actions)
- mc_expected_reward = np.mean(
- [reward_map[tuple(a)] for a in sampled_actions])
- exact_expected_reward = np.sum(
- [episode_probs_map[k] * reward_map[k] for k in reward_map])
- error = smape(mc_expected_reward, exact_expected_reward)
- self.assertTrue(error < 0.005, msg='actual: %s' % angle_frac)
-
- def testNumericalGradChecking(self):
- # Similar to
- # http://ufldl.stanford.edu/wiki/index.php/Gradient_checking_and_advanced_optimization.
- epsilon = 1e-4
- eos = misc.BF_EOS_INT
- self.assertEqual(0, eos)
- config = defaults.default_config_with_updates(
- 'env=c(task="print"),'
- 'agent=c(algorithm="pg",optimizer="sgd",lr=1.0,ema_baseline_decay=0.99,'
- 'entropy_beta=0.0,topk_loss_hparam=0.0,policy_lstm_sizes=[10],'
- 'eos_token=True),'
- 'batch_size=64')
- dtype = tf.float64
- tf.reset_default_graph()
- tf.set_random_seed(12345678987654321)
- np.random.seed(1294024302)
- trainer = pg_train.AsyncTrainer(
- config, task_id=0, ps_tasks=0, num_workers=1, dtype=dtype)
- model = trainer.model
- actions_ph = model.actions
- lengths_ph = model.adjusted_lengths
- multipliers_ph = model.policy_multipliers
- loss = model.pi_loss
- global_init_op = tf.variables_initializer(
- tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, 'global'))
-
- assign_add_placeholders = [None] * len(model.trainable_variables)
- assign_add_ops = [None] * len(model.trainable_variables)
- param_shapes = [None] * len(model.trainable_variables)
- for i, param in enumerate(model.trainable_variables):
- param_shapes[i] = param.get_shape().as_list()
- assign_add_placeholders[i] = tf.placeholder(dtype,
- np.prod(param_shapes[i]))
- assign_add_ops[i] = param.assign_add(
- tf.reshape(assign_add_placeholders[i], param_shapes[i]))
-
- with tf.Session() as sess:
- sess.run(global_init_op) # Initialize global copy.
- trainer.initialize(sess)
-
- actions_raw = [random_sequence(10, 9) for _ in xrange(16)]
- actions_batch = utils.stack_pad(actions_raw, 0)
- lengths_batch = [len(l) for l in actions_raw]
- feed = {actions_ph: actions_batch,
- multipliers_ph: np.ones_like(actions_batch),
- lengths_ph: lengths_batch}
-
- estimated_grads = [None] * len(model.trainable_variables)
- for i, param in enumerate(model.trainable_variables):
- param_size = np.prod(param_shapes[i])
- estimated_grads[i] = np.zeros(param_size, dtype=np.float64)
- for index in xrange(param_size):
- e = onehot(index, param_size) * epsilon
- sess.run(assign_add_ops[i],
- {assign_add_placeholders[i]: e})
- j_plus = sess.run(loss, feed)
- sess.run(assign_add_ops[i],
- {assign_add_placeholders[i]: -2 * e})
- j_minus = sess.run(loss, feed)
- sess.run(assign_add_ops[i],
- {assign_add_placeholders[i]: e})
- estimated_grads[i][index] = (j_plus - j_minus) / (2 * epsilon)
- estimated_grads[i] = estimated_grads[i].reshape(param_shapes[i])
-
- analytic_grads = sess.run(model.dense_unclipped_grads, feed)
-
- for g1, g2 in zip(estimated_grads[1:], analytic_grads[1:]):
- logging.info('norm (g1-g2): %s', np.abs(g1 - g2).mean())
- self.assertTrue(np.allclose(g1, g2))
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/brain_coder/single_task/pg_train.py b/research/brain_coder/single_task/pg_train.py
deleted file mode 100644
index fde7cc84729a56002e8688d268a2085432ee124e..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/pg_train.py
+++ /dev/null
@@ -1,782 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-r"""Train RL agent on coding tasks."""
-
-import contextlib
-import cPickle
-import cProfile
-import marshal
-import os
-import time
-
-from absl import flags
-from absl import logging
-import tensorflow as tf
-
-# internal session lib import
-
-from single_task import data # brain coder
-from single_task import defaults # brain coder
-from single_task import pg_agent as agent_lib # brain coder
-from single_task import results_lib # brain coder
-
-
-FLAGS = flags.FLAGS
-flags.DEFINE_string(
- 'master', '',
- 'URL of the TensorFlow master to use.')
-flags.DEFINE_integer(
- 'ps_tasks', 0,
- 'Number of parameter server tasks. Only set to 0 for '
- 'single worker training.')
-flags.DEFINE_integer(
- 'summary_interval', 10,
- 'How often to write summaries.')
-flags.DEFINE_integer(
- 'summary_tasks', 16,
- 'If greater than 0 only tasks 0 through summary_tasks - 1 '
- 'will write summaries. If 0, all tasks will write '
- 'summaries.')
-flags.DEFINE_bool(
- 'stop_on_success', True,
- 'If True, training will stop as soon as a solution is found. '
- 'If False, training will continue indefinitely until another '
- 'stopping condition is reached.')
-flags.DEFINE_bool(
- 'do_profiling', False,
- 'If True, cProfile profiler will run and results will be '
- 'written to logdir. WARNING: Results will not be written if '
- 'the code crashes. Make sure it exists successfully.')
-flags.DEFINE_integer('model_v', 0, 'Model verbosity level.')
-flags.DEFINE_bool(
- 'delayed_graph_cleanup', True,
- 'If true, container for n-th run will not be reset until the (n+1)-th run '
- 'is complete. This greatly reduces the chance that a worker is still '
- 'using the n-th container when it is cleared.')
-
-
-def define_tuner_hparam_space(hparam_space_type):
- """Define tunable hparams for grid search."""
- if hparam_space_type not in ('pg', 'pg-topk', 'topk', 'is'):
- raise ValueError('Hparam space is not valid: "%s"' % hparam_space_type)
-
- # Discrete hparam space is stored as a dict from hparam name to discrete
- # values.
- hparam_space = {}
-
- if hparam_space_type in ('pg', 'pg-topk', 'is'):
- # Add a floating point parameter named learning rate.
- hparam_space['lr'] = [1e-5, 1e-4, 1e-3]
- hparam_space['entropy_beta'] = [0.005, 0.01, 0.05, 0.10]
- else: # 'topk'
- # Add a floating point parameter named learning rate.
- hparam_space['lr'] = [1e-5, 1e-4, 1e-3]
- hparam_space['entropy_beta'] = [0.0, 0.005, 0.01, 0.05, 0.10]
-
- if hparam_space_type in ('topk', 'pg-topk'):
- # topk tuning will be enabled.
- hparam_space['topk'] = [10]
- hparam_space['topk_loss_hparam'] = [1.0, 10.0, 50.0, 200.0]
-
- elif hparam_space_type == 'is':
- # importance sampling tuning will be enabled.
- hparam_space['replay_temperature'] = [0.25, 0.5, 1.0, 2.0]
- hparam_space['alpha'] = [0.5, 0.75, 63/64.]
-
- return hparam_space
-
-
-def write_hparams_to_config(config, hparams, hparam_space_type):
- """Write hparams given by the tuner into the Config object."""
- if hparam_space_type not in ('pg', 'pg-topk', 'topk', 'is'):
- raise ValueError('Hparam space is not valid: "%s"' % hparam_space_type)
-
- config.agent.lr = hparams.lr
- config.agent.entropy_beta = hparams.entropy_beta
-
- if hparam_space_type in ('topk', 'pg-topk'):
- # topk tuning will be enabled.
- config.agent.topk = hparams.topk
- config.agent.topk_loss_hparam = hparams.topk_loss_hparam
- elif hparam_space_type == 'is':
- # importance sampling tuning will be enabled.
- config.agent.replay_temperature = hparams.replay_temperature
- config.agent.alpha = hparams.alpha
-
-
-def make_initialized_variable(value, name, shape=None, dtype=tf.float32):
- """Create a tf.Variable with a constant initializer.
-
- Args:
- value: Constant value to initialize the variable with. This is the value
- that the variable starts with.
- name: Name of the variable in the TF graph.
- shape: Shape of the variable. If None, variable will be a scalar.
- dtype: Data type of the variable. Should be a TF dtype. Defaults to
- tf.float32.
-
- Returns:
- tf.Variable instance.
- """
- if shape is None:
- shape = []
- return tf.get_variable(
- name=name, shape=shape, initializer=tf.constant_initializer(value),
- dtype=dtype, trainable=False)
-
-
-class AsyncTrainer(object):
- """Manages graph creation and training.
-
- This async trainer creates a global model on the parameter server, and a local
- model (for this worker). Gradient updates are sent to the global model, and
- the updated weights are synced to the local copy.
- """
-
- def __init__(self, config, task_id, ps_tasks, num_workers, is_chief=True,
- summary_writer=None,
- dtype=tf.float32,
- summary_interval=1,
- run_number=0,
- logging_dir='/tmp', model_v=0):
- self.config = config
- self.data_manager = data.DataManager(
- config, run_number=run_number,
- do_code_simplification=not FLAGS.stop_on_success)
- self.task_id = task_id
- self.ps_tasks = ps_tasks
- self.is_chief = is_chief
- if ps_tasks == 0:
- assert task_id == 0, 'No parameter servers specified. Expecting 1 task.'
- assert num_workers == 1, (
- 'No parameter servers specified. Expecting 1 task.')
- worker_device = '/job:localhost/replica:%d/task:0/cpu:0' % task_id
- # worker_device = '/cpu:0'
- # ps_device = '/cpu:0'
- else:
- assert num_workers > 0, 'There must be at least 1 training worker.'
- worker_device = '/job:worker/replica:%d/task:0/cpu:0' % task_id
- # ps_device = '/job:ps/replica:0/task:0/cpu:0'
- logging.info('worker_device: %s', worker_device)
-
- logging_file = os.path.join(
- logging_dir, 'solutions_%d.txt' % task_id)
- experience_replay_file = os.path.join(
- logging_dir, 'replay_buffer_%d.pickle' % task_id)
- self.topk_file = os.path.join(
- logging_dir, 'topk_buffer_%d.pickle' % task_id)
-
- tf.get_variable_scope().set_use_resource(True)
-
- # global model
- with tf.device(tf.train.replica_device_setter(ps_tasks,
- ps_device='/job:ps/replica:0',
- worker_device=worker_device)):
- with tf.variable_scope('global'):
- global_model = agent_lib.LMAgent(config, dtype=dtype, is_local=False)
- global_params_dict = {p.name: p
- for p in global_model.sync_variables}
- self.global_model = global_model
- self.global_step = make_initialized_variable(
- 0, 'global_step', dtype=tf.int64)
-
- self.global_best_reward = make_initialized_variable(
- -10.0, 'global_best_reward', dtype=tf.float64)
- self.is_best_model = make_initialized_variable(
- False, 'is_best_model', dtype=tf.bool)
- self.reset_is_best_model = self.is_best_model.assign(False)
- self.global_best_reward_placeholder = tf.placeholder(
- tf.float64, [], name='global_best_reward_placeholder')
- self.assign_global_best_reward_op = tf.group(
- self.global_best_reward.assign(
- self.global_best_reward_placeholder),
- self.is_best_model.assign(True))
- def assign_global_best_reward_fn(session, reward):
- reward = round(reward, 10)
- best_reward = round(session.run(self.global_best_reward), 10)
- is_best = reward > best_reward
- if is_best:
- session.run(self.assign_global_best_reward_op,
- {self.global_best_reward_placeholder: reward})
- return is_best
- self.assign_global_best_reward_fn = assign_global_best_reward_fn
-
- # Any worker will set to true when it finds a solution.
- self.found_solution_flag = make_initialized_variable(
- False, 'found_solution_flag', dtype=tf.bool)
- self.found_solution_op = self.found_solution_flag.assign(True)
-
- self.run_number = make_initialized_variable(
- run_number, 'run_number', dtype=tf.int32)
-
- # Store a solution when found.
- self.code_solution_variable = tf.get_variable(
- 'code_solution', [], tf.string,
- initializer=tf.constant_initializer(''))
- self.code_solution_ph = tf.placeholder(
- tf.string, [], name='code_solution_ph')
- self.code_solution_assign_op = self.code_solution_variable.assign(
- self.code_solution_ph)
- def assign_code_solution_fn(session, code_solution_string):
- session.run(self.code_solution_assign_op,
- {self.code_solution_ph: code_solution_string})
- self.assign_code_solution_fn = assign_code_solution_fn
-
- # Count all programs sampled from policy. This does not include
- # programs sampled from replay buffer.
- # This equals NPE (number of programs executed). Only programs sampled
- # from the policy need to be executed.
- self.program_count = make_initialized_variable(
- 0, 'program_count', dtype=tf.int64)
-
- # local model
- with tf.device(worker_device):
- with tf.variable_scope('local'):
- self.model = model = agent_lib.LMAgent(
- config,
- task_id=task_id,
- logging_file=logging_file,
- experience_replay_file=experience_replay_file,
- dtype=dtype,
- global_best_reward_fn=self.assign_global_best_reward_fn,
- found_solution_op=self.found_solution_op,
- assign_code_solution_fn=self.assign_code_solution_fn,
- program_count=self.program_count,
- stop_on_success=FLAGS.stop_on_success,
- verbose_level=model_v)
- local_params = model.trainable_variables
- local_params_dict = {p.name: p for p in local_params}
-
- # Pull global params to local model.
- def _global_to_local_scope(name):
- assert name.startswith('global/')
- return 'local' + name[6:]
- sync_dict = {
- local_params_dict[_global_to_local_scope(p_name)]: p
- for p_name, p in global_params_dict.items()}
- self.sync_op = tf.group(*[v_local.assign(v_global)
- for v_local, v_global
- in sync_dict.items()])
-
- # Pair local gradients with global params.
- grad_var_dict = {
- gradient: sync_dict[local_var]
- for local_var, gradient in model.gradients_dict.items()}
-
- # local model
- model.make_summary_ops() # Don't put summaries under 'local' scope.
- with tf.variable_scope('local'):
- self.train_op = model.optimizer.apply_gradients(
- grad_var_dict.items(), global_step=self.global_step)
- self.local_init_op = tf.variables_initializer(
- tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES,
- tf.get_variable_scope().name))
-
- self.local_step = 0
- self.last_summary_time = time.time()
- self.summary_interval = summary_interval
- self.summary_writer = summary_writer
- self.cached_global_step = -1
- self.cached_global_npe = -1
-
- logging.info('summary_interval: %d', self.summary_interval)
-
- # Load top-k buffer.
- if self.model.top_episodes is not None and tf.gfile.Exists(self.topk_file):
- try:
- with tf.gfile.FastGFile(self.topk_file, 'r') as f:
- self.model.top_episodes = cPickle.loads(f.read())
- logging.info(
- 'Loaded top-k buffer from disk with %d items. Location: "%s"',
- len(self.model.top_episodes), self.topk_file)
- except (cPickle.UnpicklingError, EOFError) as e:
- logging.warn(
- 'Failed to load existing top-k buffer from disk. Removing bad file.'
- '\nLocation: "%s"\nException: %s', self.topk_file, str(e))
- tf.gfile.Remove(self.topk_file)
-
- def initialize(self, session):
- """Run initialization ops."""
- session.run(self.local_init_op)
- session.run(self.sync_op)
- self.cached_global_step, self.cached_global_npe = session.run(
- [self.global_step, self.program_count])
-
- def update_global_model(self, session):
- """Run an update step.
-
- 1) Asynchronously copy global weights to local model.
- 2) Call into local model's update_step method, which does the following:
- a) Sample batch of programs from policy.
- b) Compute rewards.
- c) Compute gradients and update the global model asynchronously.
- 3) Write tensorboard summaries to disk.
-
- Args:
- session: tf.Session instance.
- """
- session.run(self.sync_op) # Copy weights from global to local.
-
- with session.as_default():
- result = self.model.update_step(
- session, self.data_manager.sample_rl_batch(), self.train_op,
- self.global_step)
- global_step = result.global_step
- global_npe = result.global_npe
- summaries = result.summaries_list
- self.cached_global_step = global_step
- self.cached_global_npe = global_npe
- self.local_step += 1
-
- if self.summary_writer and self.local_step % self.summary_interval == 0:
- if not isinstance(summaries, (tuple, list)):
- summaries = [summaries]
- summaries.append(self._local_step_summary())
- if self.is_chief:
- (global_best_reward,
- found_solution_flag,
- program_count) = session.run(
- [self.global_best_reward,
- self.found_solution_flag,
- self.program_count])
- summaries.append(
- tf.Summary(
- value=[tf.Summary.Value(
- tag='model/best_reward',
- simple_value=global_best_reward)]))
- summaries.append(
- tf.Summary(
- value=[tf.Summary.Value(
- tag='model/solution_found',
- simple_value=int(found_solution_flag))]))
- summaries.append(
- tf.Summary(
- value=[tf.Summary.Value(
- tag='model/program_count',
- simple_value=program_count)]))
- for s in summaries:
- self.summary_writer.add_summary(s, global_step)
- self.last_summary_time = time.time()
-
- def _local_step_summary(self):
- """Compute number of local steps per time increment."""
- dt = time.time() - self.last_summary_time
- steps_per_time = self.summary_interval / float(dt)
- return tf.Summary(value=[
- tf.Summary.Value(
- tag='local_step/per_sec',
- simple_value=steps_per_time),
- tf.Summary.Value(
- tag='local_step/step',
- simple_value=self.local_step)])
-
- def maybe_save_best_model(self, session, saver, checkpoint_file):
- """Check if this model got the highest reward and save to disk if so."""
- if self.is_chief and session.run(self.is_best_model):
- logging.info('Saving best model to "%s"', checkpoint_file)
- saver.save(session, checkpoint_file)
- session.run(self.reset_is_best_model)
-
- def save_replay_buffer(self):
- """Save replay buffer to disk.
-
- Call this periodically so that training can recover if jobs go down.
- """
- if self.model.experience_replay is not None:
- logging.info('Saving experience replay buffer to "%s".',
- self.model.experience_replay.save_file)
- self.model.experience_replay.incremental_save(True)
-
- def delete_replay_buffer(self):
- """Delete replay buffer from disk.
-
- Call this at the end of training to clean up. Replay buffer can get very
- large.
- """
- if self.model.experience_replay is not None:
- logging.info('Deleting experience replay buffer at "%s".',
- self.model.experience_replay.save_file)
- tf.gfile.Remove(self.model.experience_replay.save_file)
-
- def save_topk_buffer(self):
- """Save top-k buffer to disk.
-
- Call this periodically so that training can recover if jobs go down.
- """
- if self.model.top_episodes is not None:
- logging.info('Saving top-k buffer to "%s".', self.topk_file)
- # Overwrite previous data each time.
- with tf.gfile.FastGFile(self.topk_file, 'w') as f:
- f.write(cPickle.dumps(self.model.top_episodes))
-
-
-@contextlib.contextmanager
-def managed_session(sv, master='', config=None,
- start_standard_services=True,
- close_summary_writer=True,
- max_wait_secs=7200):
- # Same as Supervisor.managed_session, but with configurable timeout.
- try:
- sess = sv.prepare_or_wait_for_session(
- master=master, config=config,
- start_standard_services=start_standard_services,
- max_wait_secs=max_wait_secs)
- yield sess
- except tf.errors.DeadlineExceededError:
- raise
- except Exception as e: # pylint: disable=broad-except
- sv.request_stop(e)
- finally:
- try:
- # Request all the threads to stop and wait for them to do so. Any
- # exception raised by the threads is raised again from stop().
- # Passing stop_grace_period_secs is for blocked enqueue/dequeue
- # threads which are not checking for `should_stop()`. They
- # will be stopped when we close the session further down.
- sv.stop(close_summary_writer=close_summary_writer)
- finally:
- # Close the session to finish up all pending calls. We do not care
- # about exceptions raised when closing. This takes care of
- # blocked enqueue/dequeue calls.
- try:
- sess.close()
- except Exception: # pylint: disable=broad-except
- # Silently ignore exceptions raised by close().
- pass
-
-
-def train(config, is_chief, tuner=None, run_dir=None, run_number=0,
- results_writer=None):
- """Run training loop.
-
- Args:
- config: config_lib.Config instance containing global config (agent and env).
- is_chief: True if this worker is chief. Chief worker manages writing some
- data to disk and initialization of the global model.
- tuner: A tuner instance. If not tuning, leave as None.
- run_dir: Directory where all data for this run will be written. If None,
- run_dir = FLAGS.logdir. Set this argument when doing multiple runs.
- run_number: Which run is this.
- results_writer: Managest writing training results to disk. Results are a
- dict of metric names and values.
-
- Returns:
- The trainer object used to run training updates.
- """
- logging.info('Will run asynchronous training.')
-
- if run_dir is None:
- run_dir = FLAGS.logdir
- train_dir = os.path.join(run_dir, 'train')
- best_model_checkpoint = os.path.join(train_dir, 'best.ckpt')
- events_dir = '%s/events_%d' % (run_dir, FLAGS.task_id)
- logging.info('Events directory: %s', events_dir)
-
- logging_dir = os.path.join(run_dir, 'logs')
- if not tf.gfile.Exists(logging_dir):
- tf.gfile.MakeDirs(logging_dir)
- status_file = os.path.join(logging_dir, 'status.txt')
-
- if FLAGS.summary_tasks and FLAGS.task_id < FLAGS.summary_tasks:
- summary_writer = tf.summary.FileWriter(events_dir)
- else:
- summary_writer = None
-
- # Only profile task 0.
- if FLAGS.do_profiling:
- logging.info('Profiling enabled')
- profiler = cProfile.Profile()
- profiler.enable()
- else:
- profiler = None
-
- trainer = AsyncTrainer(
- config, FLAGS.task_id, FLAGS.ps_tasks, FLAGS.num_workers,
- is_chief=is_chief,
- summary_interval=FLAGS.summary_interval,
- summary_writer=summary_writer,
- logging_dir=logging_dir,
- run_number=run_number,
- model_v=FLAGS.model_v)
-
- variables_to_save = [v for v in tf.global_variables()
- if v.name.startswith('global')]
- global_init_op = tf.variables_initializer(variables_to_save)
- saver = tf.train.Saver(variables_to_save)
-
- var_list = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES,
- tf.get_variable_scope().name)
- logging.info('Trainable vars:')
- for v in var_list:
- logging.info(' %s, %s, %s', v.name, v.device, v.get_shape())
-
- logging.info('All vars:')
- for v in tf.global_variables():
- logging.info(' %s, %s, %s', v.name, v.device, v.get_shape())
-
- def init_fn(unused_sess):
- logging.info('No checkpoint found. Initialized global params.')
-
- sv = tf.train.Supervisor(is_chief=is_chief,
- logdir=train_dir,
- saver=saver,
- summary_op=None,
- init_op=global_init_op,
- init_fn=init_fn,
- summary_writer=summary_writer,
- ready_op=tf.report_uninitialized_variables(
- variables_to_save),
- ready_for_local_init_op=None,
- global_step=trainer.global_step,
- save_model_secs=30,
- save_summaries_secs=30)
-
- # Add a thread that periodically checks if this Trial should stop
- # based on an early stopping policy.
- if tuner:
- sv.Loop(60, tuner.check_for_stop, (sv.coord,))
-
- last_replay_save_time = time.time()
-
- global_step = -1
- logging.info(
- 'Starting session. '
- 'If this hangs, we\'re mostly likely waiting to connect '
- 'to the parameter server. One common cause is that the parameter '
- 'server DNS name isn\'t resolving yet, or is misspecified.')
- should_retry = True
- supervisor_deadline_exceeded = False
- while should_retry:
- try:
- with managed_session(
- sv, FLAGS.master, max_wait_secs=60) as session, session.as_default():
- should_retry = False
- do_training = True
-
- try:
- trainer.initialize(session)
- if session.run(trainer.run_number) != run_number:
- # If we loaded existing model from disk, and the saved run number is
- # different, throw an exception.
- raise RuntimeError(
- 'Expecting to be on run %d, but is actually on run %d. '
- 'run_dir: "%s"'
- % (run_number, session.run(trainer.run_number), run_dir))
- global_step = trainer.cached_global_step
- logging.info('Starting training at step=%d', global_step)
- while do_training:
- trainer.update_global_model(session)
-
- if is_chief:
- trainer.maybe_save_best_model(
- session, saver, best_model_checkpoint)
- global_step = trainer.cached_global_step
- global_npe = trainer.cached_global_npe
-
- if time.time() - last_replay_save_time >= 30:
- trainer.save_replay_buffer()
- trainer.save_topk_buffer()
- last_replay_save_time = time.time()
-
- # Stopping conditions.
- if tuner and tuner.should_trial_stop():
- logging.info('Tuner requested early stopping. Finishing.')
- do_training = False
- if is_chief and FLAGS.stop_on_success:
- found_solution = session.run(trainer.found_solution_flag)
- if found_solution:
- do_training = False
- logging.info('Solution found. Finishing.')
- if FLAGS.max_npe and global_npe >= FLAGS.max_npe:
- # Max NPE (number of programs executed) reached.
- logging.info('Max NPE reached. Finishing.')
- do_training = False
- if sv.should_stop():
- logging.info('Supervisor issued stop. Finishing.')
- do_training = False
-
- except tf.errors.NotFoundError:
- # Catch "Error while reading resource variable".
- # The chief worker likely destroyed the container, so do not retry.
- logging.info('Caught NotFoundError. Quitting.')
- do_training = False
- should_retry = False
- break
- except tf.errors.InternalError as e:
- # Catch "Invalid variable reference."
- if str(e).startswith('Invalid variable reference.'):
- # The chief worker likely destroyed the container, so do not
- # retry.
- logging.info(
- 'Caught "InternalError: Invalid variable reference.". '
- 'Quitting.')
- do_training = False
- should_retry = False
- break
- else:
- # Pass exception through.
- raise
-
- # Exited training loop. Write results to disk.
- if is_chief and results_writer:
- assert not should_retry
- with tf.gfile.FastGFile(status_file, 'w') as f:
- f.write('done')
- (program_count,
- found_solution,
- code_solution,
- best_reward,
- global_step) = session.run(
- [trainer.program_count,
- trainer.found_solution_flag,
- trainer.code_solution_variable,
- trainer.global_best_reward,
- trainer.global_step])
- results_dict = {
- 'max_npe': FLAGS.max_npe,
- 'batch_size': config.batch_size,
- 'max_batches': FLAGS.max_npe // config.batch_size,
- 'npe': program_count,
- 'max_global_repetitions': FLAGS.num_repetitions,
- 'max_local_repetitions': FLAGS.num_repetitions,
- 'code_solution': code_solution,
- 'best_reward': best_reward,
- 'num_batches': global_step,
- 'found_solution': found_solution,
- 'task': trainer.data_manager.task_name,
- 'global_rep': run_number}
- logging.info('results_dict: %s', results_dict)
- results_writer.append(results_dict)
-
- except tf.errors.AbortedError:
- # Catch "Graph handle is not found" error due to preempted jobs.
- logging.info('Caught AbortedError. Retying.')
- should_retry = True
- except tf.errors.DeadlineExceededError:
- supervisor_deadline_exceeded = True
- should_retry = False
-
- if is_chief:
- logging.info('This is chief worker. Stopping all workers.')
- sv.stop()
-
- if supervisor_deadline_exceeded:
- logging.info('Supervisor timed out. Quitting.')
- else:
- logging.info('Reached %s steps. Worker stopped.', global_step)
-
- # Dump profiling.
- """
- How to use profiling data.
-
- Download the profiler dump to your local machine, say to PROF_FILE_PATH.
- In a separate script, run something like the following:
-
- import pstats
- p = pstats.Stats(PROF_FILE_PATH)
- p.strip_dirs().sort_stats('cumtime').print_stats()
-
- This will sort by 'cumtime', which "is the cumulative time spent in this and
- all subfunctions (from invocation till exit)."
- https://docs.python.org/2/library/profile.html#instant-user-s-manual
- """ # pylint: disable=pointless-string-statement
- if profiler:
- prof_file = os.path.join(run_dir, 'task_%d.prof' % FLAGS.task_id)
- logging.info('Done profiling.\nDumping to "%s".', prof_file)
- profiler.create_stats()
- with tf.gfile.Open(prof_file, 'w') as f:
- f.write(marshal.dumps(profiler.stats))
-
- return trainer
-
-
-def run_training(config=None, tuner=None, logdir=None, trial_name=None,
- is_chief=True):
- """Do all training runs.
-
- This is the top level training function for policy gradient based models.
- Run this from the main function.
-
- Args:
- config: config_lib.Config instance containing global config (agent and
- environment hparams). If None, config will be parsed from FLAGS.config.
- tuner: A tuner instance. Leave as None if not tuning.
- logdir: Parent directory where all data from all runs will be written. If
- None, FLAGS.logdir will be used.
- trial_name: If tuning, set this to a unique string that identifies this
- trial. If `tuner` is not None, this also must be set.
- is_chief: True if this worker is the chief.
-
- Returns:
- List of results dicts which were written to disk. Each training run gets a
- results dict. Results dict contains metrics, i.e. (name, value) pairs which
- give information about the training run.
-
- Raises:
- ValueError: If results dicts read from disk contain invalid data.
- """
- if not config:
- # If custom config is not given, get it from flags.
- config = defaults.default_config_with_updates(FLAGS.config)
- if not logdir:
- logdir = FLAGS.logdir
- if not tf.gfile.Exists(logdir):
- tf.gfile.MakeDirs(logdir)
- assert FLAGS.num_repetitions > 0
- results = results_lib.Results(logdir)
- results_list, _ = results.read_all()
-
- logging.info('Starting experiment. Directory: "%s"', logdir)
-
- if results_list:
- if results_list[0]['max_npe'] != FLAGS.max_npe:
- raise ValueError(
- 'Cannot resume training. Max-NPE changed. Was %s, now %s',
- results_list[0]['max_npe'], FLAGS.max_npe)
- if results_list[0]['max_global_repetitions'] != FLAGS.num_repetitions:
- raise ValueError(
- 'Cannot resume training. Number of repetitions changed. Was %s, '
- 'now %s',
- results_list[0]['max_global_repetitions'],
- FLAGS.num_repetitions)
-
- while len(results_list) < FLAGS.num_repetitions:
- run_number = len(results_list)
- rep_container_name = trial_name if trial_name else 'container'
- if FLAGS.num_repetitions > 1:
- rep_dir = os.path.join(logdir, 'run_%d' % run_number)
- rep_container_name = rep_container_name + '_run_' + str(run_number)
- else:
- rep_dir = logdir
-
- logging.info(
- 'Starting repetition %d (%d out of %d)', run_number, run_number + 1,
- FLAGS.num_repetitions)
-
- # Train will write result to disk.
- with tf.container(rep_container_name):
- trainer = train(config, is_chief, tuner, rep_dir, run_number, results)
- logging.info('Done training.')
-
- if is_chief:
- # Destroy current container immediately (clears current graph).
- logging.info('Clearing shared variables.')
- tf.Session.reset(FLAGS.master, containers=[rep_container_name])
- logging.info('Shared variables cleared.')
-
- # Delete replay buffer on disk.
- assert trainer
- trainer.delete_replay_buffer()
- else:
- # Give chief worker time to clean up.
- sleep_sec = 30.0
- logging.info('Sleeping for %s sec.', sleep_sec)
- time.sleep(sleep_sec)
- tf.reset_default_graph()
- logging.info('Default graph reset.')
-
- # Expecting that train wrote new result to disk before returning.
- results_list, _ = results.read_all()
- return results_list
diff --git a/research/brain_coder/single_task/pg_train_test.py b/research/brain_coder/single_task/pg_train_test.py
deleted file mode 100644
index 0a562e5331e638cab82bc8033bfa2c1fc355e960..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/pg_train_test.py
+++ /dev/null
@@ -1,87 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Tests for pg_train.
-
-These tests excersize code paths available through configuration options.
-Training will be run for just a few steps with the goal being to check that
-nothing crashes.
-"""
-
-from absl import flags
-import tensorflow as tf
-
-from single_task import defaults # brain coder
-from single_task import run # brain coder
-
-FLAGS = flags.FLAGS
-
-
-class TrainTest(tf.test.TestCase):
-
- def RunTrainingSteps(self, config_string, num_steps=10):
- """Run a few training steps with the given config.
-
- Just check that nothing crashes.
-
- Args:
- config_string: Config encoded in a string. See
- $REPO_PATH/common/config_lib.py
- num_steps: Number of training steps to run. Defaults to 10.
- """
- config = defaults.default_config_with_updates(config_string)
- FLAGS.master = ''
- FLAGS.max_npe = num_steps * config.batch_size
- FLAGS.summary_interval = 1
- FLAGS.logdir = tf.test.get_temp_dir()
- FLAGS.config = config_string
- tf.reset_default_graph()
- run.main(None)
-
- def testVanillaPolicyGradient(self):
- self.RunTrainingSteps(
- 'env=c(task="reverse"),'
- 'agent=c(algorithm="pg"),'
- 'timestep_limit=90,batch_size=64')
-
- def testVanillaPolicyGradient_VariableLengthSequences(self):
- self.RunTrainingSteps(
- 'env=c(task="reverse"),'
- 'agent=c(algorithm="pg",eos_token=False),'
- 'timestep_limit=90,batch_size=64')
-
- def testVanillaActorCritic(self):
- self.RunTrainingSteps(
- 'env=c(task="reverse"),'
- 'agent=c(algorithm="pg",ema_baseline_decay=0.0),'
- 'timestep_limit=90,batch_size=64')
-
- def testPolicyGradientWithTopK(self):
- self.RunTrainingSteps(
- 'env=c(task="reverse"),'
- 'agent=c(algorithm="pg",topk_loss_hparam=1.0,topk=10),'
- 'timestep_limit=90,batch_size=64')
-
- def testVanillaActorCriticWithTopK(self):
- self.RunTrainingSteps(
- 'env=c(task="reverse"),'
- 'agent=c(algorithm="pg",ema_baseline_decay=0.0,topk_loss_hparam=1.0,'
- 'topk=10),'
- 'timestep_limit=90,batch_size=64')
-
- def testPolicyGradientWithTopK_VariableLengthSequences(self):
- self.RunTrainingSteps(
- 'env=c(task="reverse"),'
- 'agent=c(algorithm="pg",topk_loss_hparam=1.0,topk=10,eos_token=False),'
- 'timestep_limit=90,batch_size=64')
-
- def testPolicyGradientWithImportanceSampling(self):
- self.RunTrainingSteps(
- 'env=c(task="reverse"),'
- 'agent=c(algorithm="pg",alpha=0.5),'
- 'timestep_limit=90,batch_size=64')
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/brain_coder/single_task/results_lib.py b/research/brain_coder/single_task/results_lib.py
deleted file mode 100644
index fd28fdd49ba3200dc9faa18d1722235ee4bf2ac2..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/results_lib.py
+++ /dev/null
@@ -1,155 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Results object manages distributed reading and writing of results to disk."""
-
-import ast
-from collections import namedtuple
-import os
-import re
-from six.moves import xrange
-import tensorflow as tf
-
-
-ShardStats = namedtuple(
- 'ShardStats',
- ['num_local_reps_completed', 'max_local_reps', 'finished'])
-
-
-def ge_non_zero(a, b):
- return a >= b and b > 0
-
-
-def get_shard_id(file_name):
- assert file_name[-4:].lower() == '.txt'
- return int(file_name[file_name.rfind('_') + 1: -4])
-
-
-class Results(object):
- """Manages reading and writing training results to disk asynchronously.
-
- Each worker writes to its own file, so that there are no race conditions when
- writing happens. However any worker may read any file, as is the case for
- `read_all`. Writes are expected to be atomic so that workers will never
- read incomplete data, and this is likely to be the case on Unix systems.
- Reading out of date data is fine, as workers calling `read_all` will wait
- until data from every worker has been written before proceeding.
- """
- file_template = 'experiment_results_{0}.txt'
- search_regex = r'^experiment_results_([0-9])+\.txt$'
-
- def __init__(self, log_dir, shard_id=0):
- """Construct `Results` instance.
-
- Args:
- log_dir: Where to write results files.
- shard_id: Unique id for this file (i.e. shard). Each worker that will
- be writing results should use a different shard id. If there are
- N shards, each shard should be numbered 0 through N-1.
- """
- # Use different files for workers so that they can write to disk async.
- assert 0 <= shard_id
- self.file_name = self.file_template.format(shard_id)
- self.log_dir = log_dir
- self.results_file = os.path.join(self.log_dir, self.file_name)
-
- def append(self, metrics):
- """Append results to results list on disk."""
- with tf.gfile.FastGFile(self.results_file, 'a') as writer:
- writer.write(str(metrics) + '\n')
-
- def read_this_shard(self):
- """Read only from this shard."""
- return self._read_shard(self.results_file)
-
- def _read_shard(self, results_file):
- """Read only from the given shard file."""
- try:
- with tf.gfile.FastGFile(results_file, 'r') as reader:
- results = [ast.literal_eval(entry) for entry in reader]
- except tf.errors.NotFoundError:
- # No results written to disk yet. Return empty list.
- return []
- return results
-
- def _get_max_local_reps(self, shard_results):
- """Get maximum number of repetitions the given shard needs to complete.
-
- Worker working on each shard needs to complete a certain number of runs
- before it finishes. This method will return that number so that we can
- determine which shards are still not done.
-
- We assume that workers are including a 'max_local_repetitions' value in
- their results, which should be the total number of repetitions it needs to
- run.
-
- Args:
- shard_results: Dict mapping metric names to values. This should be read
- from a shard on disk.
-
- Returns:
- Maximum number of repetitions the given shard needs to complete.
- """
- mlrs = [r['max_local_repetitions'] for r in shard_results]
- if not mlrs:
- return 0
- for n in mlrs[1:]:
- assert n == mlrs[0], 'Some reps have different max rep.'
- return mlrs[0]
-
- def read_all(self, num_shards=None):
- """Read results across all shards, i.e. get global results list.
-
- Args:
- num_shards: (optional) specifies total number of shards. If the caller
- wants information about which shards are incomplete, provide this
- argument (so that shards which have yet to be created are still
- counted as incomplete shards). Otherwise, no information about
- incomplete shards will be returned.
-
- Returns:
- aggregate: Global list of results (across all shards).
- shard_stats: List of ShardStats instances, one for each shard. Or None if
- `num_shards` is None.
- """
- try:
- all_children = tf.gfile.ListDirectory(self.log_dir)
- except tf.errors.NotFoundError:
- if num_shards is None:
- return [], None
- return [], [[] for _ in xrange(num_shards)]
- shard_ids = {
- get_shard_id(fname): fname
- for fname in all_children if re.search(self.search_regex, fname)}
-
- if num_shards is None:
- aggregate = []
- shard_stats = None
- for results_file in shard_ids.values():
- aggregate.extend(self._read_shard(
- os.path.join(self.log_dir, results_file)))
- else:
- results_per_shard = [None] * num_shards
- for shard_id in xrange(num_shards):
- if shard_id in shard_ids:
- results_file = shard_ids[shard_id]
- results_per_shard[shard_id] = self._read_shard(
- os.path.join(self.log_dir, results_file))
- else:
- results_per_shard[shard_id] = []
-
- # Compute shard stats.
- shard_stats = []
- for shard_results in results_per_shard:
- max_local_reps = self._get_max_local_reps(shard_results)
- shard_stats.append(ShardStats(
- num_local_reps_completed=len(shard_results),
- max_local_reps=max_local_reps,
- finished=ge_non_zero(len(shard_results), max_local_reps)))
-
- # Compute aggregate.
- aggregate = [
- r for shard_results in results_per_shard for r in shard_results]
-
- return aggregate, shard_stats
diff --git a/research/brain_coder/single_task/results_lib_test.py b/research/brain_coder/single_task/results_lib_test.py
deleted file mode 100644
index 6fe838d74d6a3bdea4c3b219a4d3ceea4385a97e..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/results_lib_test.py
+++ /dev/null
@@ -1,84 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Tests for results_lib."""
-
-import contextlib
-import os
-import shutil
-import tempfile
-from six.moves import xrange
-import tensorflow as tf
-
-from single_task import results_lib # brain coder
-
-
-@contextlib.contextmanager
-def temporary_directory(suffix='', prefix='tmp', base_path=None):
- """A context manager to create a temporary directory and clean up on exit.
-
- The parameters are the same ones expected by tempfile.mkdtemp.
- The directory will be securely and atomically created.
- Everything under it will be removed when exiting the context.
-
- Args:
- suffix: optional suffix.
- prefix: options prefix.
- base_path: the base path under which to create the temporary directory.
- Yields:
- The absolute path of the new temporary directory.
- """
- temp_dir_path = tempfile.mkdtemp(suffix, prefix, base_path)
- try:
- yield temp_dir_path
- finally:
- try:
- shutil.rmtree(temp_dir_path)
- except OSError as e:
- if e.message == 'Cannot call rmtree on a symbolic link':
- # Interesting synthetic exception made up by shutil.rmtree.
- # Means we received a symlink from mkdtemp.
- # Also means must clean up the symlink instead.
- os.unlink(temp_dir_path)
- else:
- raise
-
-
-def freeze(dictionary):
- """Convert dict to hashable frozenset."""
- return frozenset(dictionary.iteritems())
-
-
-class ResultsLibTest(tf.test.TestCase):
-
- def testResults(self):
- with temporary_directory() as logdir:
- results_obj = results_lib.Results(logdir)
- self.assertEqual(results_obj.read_this_shard(), [])
- results_obj.append(
- {'foo': 1.5, 'bar': 2.5, 'baz': 0})
- results_obj.append(
- {'foo': 5.5, 'bar': -1, 'baz': 2})
- self.assertEqual(
- results_obj.read_this_shard(),
- [{'foo': 1.5, 'bar': 2.5, 'baz': 0},
- {'foo': 5.5, 'bar': -1, 'baz': 2}])
-
- def testShardedResults(self):
- with temporary_directory() as logdir:
- n = 4 # Number of shards.
- results_objs = [
- results_lib.Results(logdir, shard_id=i) for i in xrange(n)]
- for i, robj in enumerate(results_objs):
- robj.append({'foo': i, 'bar': 1 + i * 2})
- results_list, _ = results_objs[0].read_all()
-
- # Check results. Order does not matter here.
- self.assertEqual(
- set(freeze(r) for r in results_list),
- set(freeze({'foo': i, 'bar': 1 + i * 2}) for i in xrange(n)))
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/brain_coder/single_task/run.py b/research/brain_coder/single_task/run.py
deleted file mode 100644
index 9d8f37c973dcca3bbf8e25bce3d181e5405c6167..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/run.py
+++ /dev/null
@@ -1,142 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-r"""Run training.
-
-Choose training algorithm and task(s) and follow these examples.
-
-Run synchronous policy gradient training locally:
-
-CONFIG="agent=c(algorithm='pg'),env=c(task='reverse')"
-OUT_DIR="/tmp/bf_pg_local"
-rm -rf $OUT_DIR
-bazel run -c opt single_task:run -- \
- --alsologtostderr \
- --config="$CONFIG" \
- --max_npe=0 \
- --logdir="$OUT_DIR" \
- --summary_interval=1 \
- --model_v=0
-learning/brain/tensorboard/tensorboard.sh --port 12345 --logdir "$OUT_DIR"
-
-
-Run genetic algorithm locally:
-
-CONFIG="agent=c(algorithm='ga'),env=c(task='reverse')"
-OUT_DIR="/tmp/bf_ga_local"
-rm -rf $OUT_DIR
-bazel run -c opt single_task:run -- \
- --alsologtostderr \
- --config="$CONFIG" \
- --max_npe=0 \
- --logdir="$OUT_DIR"
-
-
-Run uniform random search locally:
-
-CONFIG="agent=c(algorithm='rand'),env=c(task='reverse')"
-OUT_DIR="/tmp/bf_rand_local"
-rm -rf $OUT_DIR
-bazel run -c opt single_task:run -- \
- --alsologtostderr \
- --config="$CONFIG" \
- --max_npe=0 \
- --logdir="$OUT_DIR"
-"""
-
-from absl import app
-from absl import flags
-from absl import logging
-
-from single_task import defaults # brain coder
-from single_task import ga_train # brain coder
-from single_task import pg_train # brain coder
-
-FLAGS = flags.FLAGS
-flags.DEFINE_string('config', '', 'Configuration.')
-flags.DEFINE_string(
- 'logdir', None, 'Absolute path where to write results.')
-flags.DEFINE_integer('task_id', 0, 'ID for this worker.')
-flags.DEFINE_integer('num_workers', 1, 'How many workers there are.')
-flags.DEFINE_integer(
- 'max_npe', 0,
- 'NPE = number of programs executed. Maximum number of programs to execute '
- 'in each run. Training will complete when this threshold is reached. Set '
- 'to 0 for unlimited training.')
-flags.DEFINE_integer(
- 'num_repetitions', 1,
- 'Number of times the same experiment will be run (globally across all '
- 'workers). Each run is independent.')
-flags.DEFINE_string(
- 'log_level', 'INFO',
- 'The threshold for what messages will be logged. One of DEBUG, INFO, WARN, '
- 'ERROR, or FATAL.')
-
-
-# To register an algorithm:
-# 1) Add dependency in the BUILD file to this build rule.
-# 2) Import the algorithm's module at the top of this file.
-# 3) Add a new entry in the following dict. The key is the algorithm name
-# (used to select the algorithm in the config). The value is the module
-# defining the expected functions for training and tuning. See the docstring
-# for `get_namespace` for further details.
-ALGORITHM_REGISTRATION = {
- 'pg': pg_train,
- 'ga': ga_train,
- 'rand': ga_train,
-}
-
-
-def get_namespace(config_string):
- """Get namespace for the selected algorithm.
-
- Users who want to add additional algorithm types should modify this function.
- The algorithm's namespace should contain the following functions:
- run_training: Run the main training loop.
- define_tuner_hparam_space: Return the hparam tuning space for the algo.
- write_hparams_to_config: Helper for tuning. Write hparams chosen for tuning
- to the Config object.
- Look at pg_train.py and ga_train.py for function signatures and
- implementations.
-
- Args:
- config_string: String representation of a Config object. This will get
- parsed into a Config in order to determine what algorithm to use.
-
- Returns:
- algorithm_namespace: The module corresponding to the algorithm given in the
- config.
- config: The Config object resulting from parsing `config_string`.
-
- Raises:
- ValueError: If config.agent.algorithm is not one of the registered
- algorithms.
- """
- config = defaults.default_config_with_updates(config_string)
- if config.agent.algorithm not in ALGORITHM_REGISTRATION:
- raise ValueError('Unknown algorithm type "%s"' % (config.agent.algorithm,))
- else:
- return ALGORITHM_REGISTRATION[config.agent.algorithm], config
-
-
-def main(argv):
- del argv # Unused.
-
- logging.set_verbosity(FLAGS.log_level)
-
- flags.mark_flag_as_required('logdir')
- if FLAGS.num_workers <= 0:
- raise ValueError('num_workers flag must be greater than 0.')
- if FLAGS.task_id < 0:
- raise ValueError('task_id flag must be greater than or equal to 0.')
- if FLAGS.task_id >= FLAGS.num_workers:
- raise ValueError(
- 'task_id flag must be strictly less than num_workers flag.')
-
- ns, _ = get_namespace(FLAGS.config)
- ns.run_training(is_chief=FLAGS.task_id == 0)
-
-
-if __name__ == '__main__':
- app.run(main)
diff --git a/research/brain_coder/single_task/run_eval_tasks.py b/research/brain_coder/single_task/run_eval_tasks.py
deleted file mode 100755
index eb684c344381462cd3626404b5d7fd7cf5d72b22..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/run_eval_tasks.py
+++ /dev/null
@@ -1,296 +0,0 @@
-#!/usr/bin/env python
-from __future__ import print_function
-
-r"""This script can launch any eval experiments from the paper.
-
-This is a script. Run with python, not bazel.
-
-Usage:
-./single_task/run_eval_tasks.py \
- --exp EXP --desc DESC [--tuning_tasks] [--iclr_tasks] [--task TASK] \
- [--tasks TASK1 TASK2 ...]
-
-where EXP is one of the keys in `experiments`,
-and DESC is a string description of the set of experiments (such as "v0")
-
-Set only one of these flags:
---tuning_tasks flag only runs tuning tasks.
---iclr_tasks flag only runs the tasks included in the paper.
---regression_tests flag runs tasks which function as regression tests.
---task flag manually selects a single task to run.
---tasks flag takes a custom list of tasks.
-
-Other flags:
---reps N specifies N repetitions per experiment, Default is 25.
---training_replicas R specifies that R workers will be launched to train one
- task (for neural network algorithms). These workers will update a global
- model stored on a parameter server. Defaults to 1. If R > 1, a parameter
- server will also be launched.
-
-
-Run everything:
-exps=( pg-20M pg-topk-20M topk-20M ga-20M rand-20M )
-BIN_DIR="single_task"
-for exp in "${exps[@]}"
-do
- ./$BIN_DIR/run_eval_tasks.py \
- --exp "$exp" --iclr_tasks
-done
-"""
-
-import argparse
-from collections import namedtuple
-import subprocess
-
-
-S = namedtuple('S', ['length'])
-default_length = 100
-
-
-iclr_tasks = [
- 'reverse', 'remove-char', 'count-char', 'add', 'bool-logic', 'print-hello',
- 'echo-twice', 'echo-thrice', 'copy-reverse', 'zero-cascade', 'cascade',
- 'shift-left', 'shift-right', 'riffle', 'unriffle', 'middle-char',
- 'remove-last', 'remove-last-two', 'echo-alternating', 'echo-half', 'length',
- 'echo-second-seq', 'echo-nth-seq', 'substring', 'divide-2', 'dedup']
-
-
-regression_test_tasks = ['reverse', 'test-hill-climb']
-
-
-E = namedtuple(
- 'E',
- ['name', 'method_type', 'config', 'simplify', 'batch_size', 'max_npe'])
-
-
-def make_experiment_settings(name, **kwargs):
- # Unpack experiment info from name.
- def split_last(string, char):
- i = string.rindex(char)
- return string[:i], string[i+1:]
- def si_to_int(si_string):
- return int(
- si_string.upper().replace('K', '0'*3).replace('M', '0'*6)
- .replace('G', '0'*9))
- method_type, max_npe = split_last(name, '-')
- assert method_type
- assert max_npe
- return E(
- name=name, method_type=method_type, max_npe=si_to_int(max_npe), **kwargs)
-
-
-experiments_set = {
- make_experiment_settings(
- 'pg-20M',
- config='entropy_beta=0.05,lr=0.0001,topk_loss_hparam=0.0,topk=0,'
- 'pi_loss_hparam=1.0,alpha=0.0',
- simplify=False,
- batch_size=64),
- make_experiment_settings(
- 'pg-topk-20M',
- config='entropy_beta=0.01,lr=0.0001,topk_loss_hparam=50.0,topk=10,'
- 'pi_loss_hparam=1.0,alpha=0.0',
- simplify=False,
- batch_size=64),
- make_experiment_settings(
- 'topk-20M',
- config='entropy_beta=0.01,lr=0.0001,topk_loss_hparam=200.0,topk=10,'
- 'pi_loss_hparam=0.0,alpha=0.0',
- simplify=False,
- batch_size=64),
- make_experiment_settings(
- 'topk-0ent-20M',
- config='entropy_beta=0.000,lr=0.0001,topk_loss_hparam=200.0,topk=10,'
- 'pi_loss_hparam=0.0,alpha=0.0',
- simplify=False,
- batch_size=64),
- make_experiment_settings(
- 'ga-20M',
- config='crossover_rate=0.95,mutation_rate=0.15',
- simplify=False,
- batch_size=100), # Population size.
- make_experiment_settings(
- 'rand-20M',
- config='',
- simplify=False,
- batch_size=1),
- make_experiment_settings(
- 'simpl-500M',
- config='entropy_beta=0.05,lr=0.0001,topk_loss_hparam=0.5,topk=10,'
- 'pi_loss_hparam=1.0,alpha=0.0',
- simplify=True,
- batch_size=64),
-}
-
-experiments = {e.name: e for e in experiments_set}
-
-
-# pylint: disable=redefined-outer-name
-def parse_args(extra_args=()):
- """Parse arguments and extract task and experiment info."""
- parser = argparse.ArgumentParser(description='Run all eval tasks.')
- parser.add_argument('--exp', required=True)
- parser.add_argument('--tuning_tasks', action='store_true')
- parser.add_argument('--iclr_tasks', action='store_true')
- parser.add_argument('--regression_tests', action='store_true')
- parser.add_argument('--desc', default='v0')
- parser.add_argument('--reps', default=25)
- parser.add_argument('--task')
- parser.add_argument('--tasks', nargs='+')
- for arg_string, default in extra_args:
- parser.add_argument(arg_string, default=default)
- args = parser.parse_args()
-
- print('Running experiment: %s' % (args.exp,))
- if args.desc:
- print('Extra description: "%s"' % (args.desc,))
- if args.exp not in experiments:
- raise ValueError('Experiment name is not valid')
- experiment_name = args.exp
- experiment_settings = experiments[experiment_name]
- assert experiment_settings.name == experiment_name
-
- if args.tasks:
- print('Launching tasks from args: %s' % (args.tasks,))
- tasks = {t: S(length=default_length) for t in args.tasks}
- elif args.task:
- print('Launching single task "%s"' % args.task)
- tasks = {args.task: S(length=default_length)}
- elif args.tuning_tasks:
- print('Only running tuning tasks')
- tasks = {name: S(length=default_length)
- for name in ['reverse-tune', 'remove-char-tune']}
- elif args.iclr_tasks:
- print('Running eval tasks from ICLR paper.')
- tasks = {name: S(length=default_length) for name in iclr_tasks}
- elif args.regression_tests:
- tasks = {name: S(length=default_length) for name in regression_test_tasks}
- print('Tasks: %s' % tasks.keys())
-
- print('reps = %d' % (int(args.reps),))
-
- return args, tasks, experiment_settings
-
-
-def run(command_string):
- subprocess.call(command_string, shell=True)
-
-
-if __name__ == '__main__':
- LAUNCH_TRAINING_COMMAND = 'single_task/launch_training.sh'
- COMPILE_COMMAND = 'bazel build -c opt single_task:run.par'
-
- args, tasks, experiment_settings = parse_args(
- extra_args=(('--training_replicas', 1),))
-
- if experiment_settings.method_type in (
- 'pg', 'pg-topk', 'topk', 'topk-0ent', 'simpl'):
- # Runs PG and TopK.
-
- def make_run_cmd(job_name, task, max_npe, num_reps, code_length,
- batch_size, do_simplify, custom_config_str):
- """Constructs terminal command for launching NN based algorithms.
-
- The arguments to this function will be used to create config for the
- experiment.
-
- Args:
- job_name: Name of the job to launch. Should uniquely identify this
- experiment run.
- task: Name of the coding task to solve.
- max_npe: Maximum number of programs executed. An integer.
- num_reps: Number of times to run the experiment. An integer.
- code_length: Maximum allowed length of synthesized code.
- batch_size: Minibatch size for gradient descent.
- do_simplify: Whether to run the experiment in code simplification mode.
- A bool.
- custom_config_str: Additional config for the model config string.
-
- Returns:
- The terminal command that launches the specified experiment.
- """
- config = """
- env=c(task='{0}',correct_syntax=False),
- agent=c(
- algorithm='pg',
- policy_lstm_sizes=[35,35],value_lstm_sizes=[35,35],
- grad_clip_threshold=50.0,param_init_factor=0.5,regularizer=0.0,
- softmax_tr=1.0,optimizer='rmsprop',ema_baseline_decay=0.99,
- eos_token={3},{4}),
- timestep_limit={1},batch_size={2}
- """.replace(' ', '').replace('\n', '').format(
- task, code_length, batch_size, do_simplify, custom_config_str)
- num_ps = 0 if args.training_replicas == 1 else 1
- return (
- r'{0} --job_name={1} --config="{2}" --max_npe={3} '
- '--num_repetitions={4} --num_workers={5} --num_ps={6} '
- '--stop_on_success={7}'
- .format(LAUNCH_TRAINING_COMMAND, job_name, config, max_npe, num_reps,
- args.training_replicas, num_ps, str(not do_simplify).lower()))
-
- else:
- # Runs GA and Rand.
- assert experiment_settings.method_type in ('ga', 'rand')
-
- def make_run_cmd(job_name, task, max_npe, num_reps, code_length,
- batch_size, do_simplify, custom_config_str):
- """Constructs terminal command for launching GA or uniform random search.
-
- The arguments to this function will be used to create config for the
- experiment.
-
- Args:
- job_name: Name of the job to launch. Should uniquely identify this
- experiment run.
- task: Name of the coding task to solve.
- max_npe: Maximum number of programs executed. An integer.
- num_reps: Number of times to run the experiment. An integer.
- code_length: Maximum allowed length of synthesized code.
- batch_size: Minibatch size for gradient descent.
- do_simplify: Whether to run the experiment in code simplification mode.
- A bool.
- custom_config_str: Additional config for the model config string.
-
- Returns:
- The terminal command that launches the specified experiment.
- """
- assert not do_simplify
- if custom_config_str:
- custom_config_str = ',' + custom_config_str
- config = """
- env=c(task='{0}',correct_syntax=False),
- agent=c(
- algorithm='{4}'
- {3}),
- timestep_limit={1},batch_size={2}
- """.replace(' ', '').replace('\n', '').format(
- task, code_length, batch_size, custom_config_str,
- experiment_settings.method_type)
- num_workers = num_reps # Do each rep in parallel.
- return (
- r'{0} --job_name={1} --config="{2}" --max_npe={3} '
- '--num_repetitions={4} --num_workers={5} --num_ps={6} '
- '--stop_on_success={7}'
- .format(LAUNCH_TRAINING_COMMAND, job_name, config, max_npe, num_reps,
- num_workers, 0, str(not do_simplify).lower()))
-
- print('Compiling...')
- run(COMPILE_COMMAND)
-
- print('Launching %d coding tasks...' % len(tasks))
- for task, task_settings in tasks.iteritems():
- name = 'bf_rl_iclr'
- desc = '{0}.{1}_{2}'.format(args.desc, experiment_settings.name, task)
- job_name = '{}.{}'.format(name, desc)
- print('Job name: %s' % job_name)
- reps = int(args.reps) if not experiment_settings.simplify else 1
- run_cmd = make_run_cmd(
- job_name, task, experiment_settings.max_npe, reps,
- task_settings.length, experiment_settings.batch_size,
- experiment_settings.simplify,
- experiment_settings.config)
- print('Running command:\n' + run_cmd)
- run(run_cmd)
-
- print('Done.')
-# pylint: enable=redefined-outer-name
diff --git a/research/brain_coder/single_task/test_tasks.py b/research/brain_coder/single_task/test_tasks.py
deleted file mode 100644
index fb07a12653ebad6b38dc3786e749d3e8bf2b2072..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/test_tasks.py
+++ /dev/null
@@ -1,127 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Tasks that test correctness of algorithms."""
-
-from six.moves import xrange
-from common import reward as reward_lib # brain coder
-from single_task import misc # brain coder
-
-
-class BasicTaskManager(object):
- """Wraps a generic reward function."""
-
- def __init__(self, reward_fn):
- self.reward_fn = reward_fn
- self.good_reward = 1.0
-
- def _score_string(self, string):
- actions = misc.bf_string_to_tokens(string)
- reward, correct = self.reward_fn(actions)
- return misc.RewardInfo(
- episode_rewards=[0.0] * (len(string) - 1) + [reward],
- input_case=None,
- correct_output=None,
- code_output=actions,
- input_type=None,
- output_type=misc.IOType.integer,
- reason='correct' if correct else 'wrong')
-
- def rl_batch(self, batch_size):
- reward_fns = [self._score_string] * batch_size
- return reward_fns
-
-
-class Trie(object):
- """Trie for sequences."""
- EOS = ()
-
- def __init__(self):
- self.trie = {}
-
- def insert(self, sequence):
- d = self.trie
- for e in sequence:
- if e not in d:
- d[e] = {}
- d = d[e]
- d[self.EOS] = True # Terminate sequence.
-
- def prefix_match(self, sequence):
- """Return prefix of `sequence` which exists in the trie."""
- d = self.trie
- index = 0
- for i, e in enumerate(sequence + [self.EOS]):
- index = i
- if e in d:
- d = d[e]
- if e == self.EOS:
- return sequence, True
- else:
- break
- return sequence[:index], False
-
- def next_choices(self, sequence):
- d = self.trie
- for e in sequence:
- if e in d:
- d = d[e]
- else:
- raise ValueError('Sequence not a prefix: %s' % (sequence,))
- return d.keys()
-
-
-class HillClimbingTask(object):
- """Simple task that tests reward hill climbing ability.
-
- There are a set of paths (sequences of tokens) which are rewarded. The total
- reward for a path is proportional to its length, so the longest path is the
- target. Shorter paths can be dead ends.
- """
-
- def __init__(self):
- # Paths are sequences of sub-sequences. Here we form unique sub-sequences
- # out of 3 arbitrary ints. We use sub-sequences instead of single entities
- # to make the task harder by making the episodes last longer, i.e. more
- # for the agent to remember.
- a = (1, 2, 3)
- b = (4, 5, 6)
- c = (7, 8, 7)
- d = (6, 5, 4)
- e = (3, 2, 1)
- f = (8, 5, 1)
- g = (6, 4, 2)
- h = (1, 8, 3)
- self.paths = Trie()
- self.paths.insert([a, b, h])
- self.paths.insert([a, b, c, d, e, f, g, h])
- self.paths.insert([a, b, c, d, e, b, a])
- self.paths.insert([a, b, g, h])
- self.paths.insert([a, e, f, g])
- self.correct_sequence = misc.flatten([a, b, c, d, e, f, g, h])
-
- def distance_fn(a, b):
- len_diff = abs(len(a) - len(b))
- return sum(reward_lib.mod_abs_diff(ai - 1, bi - 1, 8)
- for ai, bi in zip(a, b)) + len_diff * 4 # 8 / 2 = 4
- self.distance_fn = distance_fn
-
- def __call__(self, actions):
- # Compute reward for action sequence.
- actions = [a for a in actions if a > 0]
- sequence = [tuple(actions[i: i + 3]) for i in xrange(0, len(actions), 3)]
- prefix, complete = self.paths.prefix_match(sequence)
- if complete:
- return float(len(prefix)), actions == self.correct_sequence
- if len(prefix) == len(sequence):
- return float(len(prefix)), False
- next_pred = sequence[len(prefix)]
- choices = self.paths.next_choices(prefix)
- if choices == [()]:
- return (len(prefix) - len(next_pred) / 3.0), False
- min_dist = min(self.distance_fn(c, next_pred) for c in choices)
- # +1 reward for each element in the sequence correct, plus fraction torwards
- # closest next element.
- # Maximum distance possible is num_actions * base / 2 = 3 * 8 / 2 = 12
- return (len(prefix) + (1 - min_dist / 12.0)), False
diff --git a/research/brain_coder/single_task/test_tasks_test.py b/research/brain_coder/single_task/test_tasks_test.py
deleted file mode 100644
index bc905c6936de4c686e6cac1203c65c36bd7a0b16..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/test_tasks_test.py
+++ /dev/null
@@ -1,63 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-"""Tests for test_tasks."""
-
-import numpy as np
-import tensorflow as tf
-
-from single_task import misc # brain coder
-from single_task import test_tasks # brain coder
-
-
-def get_reward(reward_fn, candidate):
- return sum(reward_fn(misc.bf_tokens_to_string(candidate)).episode_rewards)
-
-
-class TestTasksTest(tf.test.TestCase):
-
- def testHillClimbingTask(self):
- task = test_tasks.BasicTaskManager(test_tasks.HillClimbingTask())
- reward_fns = task.rl_batch(1)
- reward_fn = reward_fns[0]
- self.assertTrue(np.isclose(get_reward(reward_fn, [1, 2, 0]), 8 / 12.))
- self.assertTrue(np.isclose(get_reward(reward_fn, [1, 2, 2, 0]), 11 / 12.))
- self.assertTrue(np.isclose(get_reward(reward_fn, [1, 2, 3, 0]), 1.0))
- self.assertTrue(
- np.isclose(get_reward(reward_fn, [1, 2, 3, 4, 5, 2, 0]), 1. + 8 / 12.))
- self.assertTrue(
- np.isclose(get_reward(reward_fn, [1, 2, 3, 4, 5, 6, 0]), 2.0))
- self.assertTrue(
- np.isclose(get_reward(reward_fn, [1, 2, 3, 4, 5, 6, 1, 8, 3, 0]), 3.0))
- self.assertTrue(
- np.isclose(get_reward(reward_fn, [1, 2, 3, 4, 5, 6, 7, 8, 7, 0]), 3.0))
- self.assertTrue(
- np.isclose(get_reward(reward_fn, [1, 2, 3, 4, 5, 6, 1, 8, 3, 1, 0]),
- 3.0 - 4 / 12.))
- self.assertTrue(
- np.isclose(
- get_reward(reward_fn, [1, 2, 3, 4, 5, 6, 1, 8, 3, 1, 1, 1, 1, 0]),
- 2.0))
- self.assertTrue(
- np.isclose(get_reward(reward_fn, [1, 2, 3, 4, 5, 6, 7, 8, 7, 3, 0]),
- 3.0 + 1 / 12.))
- self.assertTrue(
- np.isclose(
- get_reward(reward_fn, [1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1,
- 8, 5, 1, 6, 4, 2, 1, 8, 3, 0]),
- 8.0))
- self.assertTrue(
- np.isclose(
- get_reward(reward_fn, [1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3, 2, 1,
- 8, 5, 1, 6, 4, 2, 1, 8, 3, 1, 1, 0]),
- 8.0 - 8 / 12.))
- self.assertTrue(
- np.isclose(get_reward(reward_fn, [1, 2, 3, 4, 5, 6, 7, 8, 7, 6, 5, 4, 3,
- 2, 1, 8, 5, 1, 6, 4, 2, 1, 8, 3, 1, 1,
- 1, 1, 1, 1, 1, 0]),
- 7.0))
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/brain_coder/single_task/tune.py b/research/brain_coder/single_task/tune.py
deleted file mode 100644
index 3473b5e94bd3c1f737a18f0187790d5df2d7a2aa..0000000000000000000000000000000000000000
--- a/research/brain_coder/single_task/tune.py
+++ /dev/null
@@ -1,262 +0,0 @@
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-r"""Run grid search.
-
-Look at launch_tuning.sh for details on how to tune at scale.
-
-Usage example:
-Tune with one worker on the local machine.
-
-CONFIG="agent=c(algorithm='pg'),"
-CONFIG+="env=c(task_cycle=['reverse-tune', 'remove-tune'])"
-HPARAM_SPACE_TYPE="pg"
-OUT_DIR="/tmp/bf_pg_tune"
-MAX_NPE=5000000
-NUM_REPETITIONS=50
-rm -rf $OUT_DIR
-mkdir $OUT_DIR
-bazel run -c opt single_task:tune -- \
- --alsologtostderr \
- --config="$CONFIG" \
- --max_npe="$MAX_NPE" \
- --num_repetitions="$NUM_REPETITIONS" \
- --logdir="$OUT_DIR" \
- --summary_interval=1 \
- --model_v=0 \
- --hparam_space="$HPARAM_SPACE_TYPE" \
- --tuner_id=0 \
- --num_tuners=1 \
- 2>&1 >"$OUT_DIR/tuner_0.log"
-learning/brain/tensorboard/tensorboard.sh --port 12345 --logdir "$OUT_DIR"
-"""
-
-import ast
-import os
-
-from absl import app
-from absl import flags
-from absl import logging
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-from single_task import defaults # brain coder
-from single_task import run as run_lib # brain coder
-
-FLAGS = flags.FLAGS
-flags.DEFINE_integer(
- 'tuner_id', 0,
- 'The unique ID for this tuning worker.')
-flags.DEFINE_integer(
- 'num_tuners', 1,
- 'How many tuners are there.')
-flags.DEFINE_string(
- 'hparam_space', 'default',
- 'String name which denotes the hparam space to tune over. This is '
- 'algorithm dependent.')
-flags.DEFINE_string(
- 'fixed_hparams', '',
- 'HParams string. Used to fix hparams during tuning.')
-flags.DEFINE_float(
- 'success_rate_objective_weight', 1.0,
- 'How much to weight success rate vs num programs seen. By default, only '
- 'success rate is optimized (this is the setting used in the paper).')
-
-
-def parse_hparams_string(hparams_str):
- hparams = {}
- for term in hparams_str.split(','):
- if not term:
- continue
- name, value = term.split('=')
- hparams[name.strip()] = ast.literal_eval(value)
- return hparams
-
-
-def int_to_multibase(n, bases):
- digits = [0] * len(bases)
- for i, b in enumerate(bases):
- n, d = divmod(n, b)
- digits[i] = d
- return digits
-
-
-def hparams_for_index(index, tuning_space):
- keys = sorted(tuning_space.keys())
- indices = int_to_multibase(index, [len(tuning_space[k]) for k in keys])
- return tf.contrib.training.HParams(
- **{k: tuning_space[k][i] for k, i in zip(keys, indices)})
-
-
-def run_tuner_loop(ns):
- """Run tuning loop for this worker."""
- is_chief = FLAGS.task_id == 0
- tuning_space = ns.define_tuner_hparam_space(
- hparam_space_type=FLAGS.hparam_space)
- fixed_hparams = parse_hparams_string(FLAGS.fixed_hparams)
- for name, value in fixed_hparams.iteritems():
- tuning_space[name] = [value]
- tuning_space_size = np.prod([len(values) for values in tuning_space.values()])
-
- num_local_trials, remainder = divmod(tuning_space_size, FLAGS.num_tuners)
- if FLAGS.tuner_id < remainder:
- num_local_trials += 1
- starting_trial_id = (
- num_local_trials * FLAGS.tuner_id + min(remainder, FLAGS.tuner_id))
-
- logging.info('tuning_space_size: %d', tuning_space_size)
- logging.info('num_local_trials: %d', num_local_trials)
- logging.info('starting_trial_id: %d', starting_trial_id)
-
- for local_trial_index in xrange(num_local_trials):
- trial_config = defaults.default_config_with_updates(FLAGS.config)
- global_trial_index = local_trial_index + starting_trial_id
- trial_name = 'trial_' + str(global_trial_index)
- trial_dir = os.path.join(FLAGS.logdir, trial_name)
- hparams = hparams_for_index(global_trial_index, tuning_space)
- ns.write_hparams_to_config(
- trial_config, hparams, hparam_space_type=FLAGS.hparam_space)
-
- results_list = ns.run_training(
- config=trial_config, tuner=None, logdir=trial_dir, is_chief=is_chief,
- trial_name=trial_name)
-
- if not is_chief:
- # Only chief worker needs to write tuning results to disk.
- continue
-
- objective, metrics = compute_tuning_objective(
- results_list, hparams, trial_name, num_trials=tuning_space_size)
- logging.info('metrics:\n%s', metrics)
- logging.info('objective: %s', objective)
- logging.info('programs_seen_fraction: %s',
- metrics['programs_seen_fraction'])
- logging.info('success_rate: %s', metrics['success_rate'])
- logging.info('success_rate_objective_weight: %s',
- FLAGS.success_rate_objective_weight)
-
- tuning_results_file = os.path.join(trial_dir, 'tuning_results.txt')
- with tf.gfile.FastGFile(tuning_results_file, 'a') as writer:
- writer.write(str(metrics) + '\n')
-
- logging.info('Trial %s complete.', trial_name)
-
-
-def compute_tuning_objective(results_list, hparams, trial_name, num_trials):
- """Compute tuning objective and metrics given results and trial information.
-
- Args:
- results_list: List of results dicts read from disk. These are written by
- workers.
- hparams: tf.contrib.training.HParams instance containing the hparams used
- in this trial (only the hparams which are being tuned).
- trial_name: Name of this trial. Used to create a trial directory.
- num_trials: Total number of trials that need to be run. This is saved in the
- metrics dict for future reference.
-
- Returns:
- objective: The objective computed for this trial. Choose the hparams for the
- trial with the largest objective value.
- metrics: Information about this trial. A dict.
- """
- found_solution = [r['found_solution'] for r in results_list]
- successful_program_counts = [
- r['npe'] for r in results_list if r['found_solution']]
-
- success_rate = sum(found_solution) / float(len(results_list))
-
- max_programs = FLAGS.max_npe # Per run.
- all_program_counts = [
- r['npe'] if r['found_solution'] else max_programs
- for r in results_list]
- programs_seen_fraction = (
- float(sum(all_program_counts))
- / (max_programs * len(all_program_counts)))
-
- # min/max/avg stats are over successful runs.
- metrics = {
- 'num_runs': len(results_list),
- 'num_succeeded': sum(found_solution),
- 'success_rate': success_rate,
- 'programs_seen_fraction': programs_seen_fraction,
- 'avg_programs': np.mean(successful_program_counts),
- 'max_possible_programs_per_run': max_programs,
- 'global_step': sum([r['num_batches'] for r in results_list]),
- 'hparams': hparams.values(),
- 'trial_name': trial_name,
- 'num_trials': num_trials}
-
- # Report stats per tasks.
- tasks = [r['task'] for r in results_list]
- for task in set(tasks):
- task_list = [r for r in results_list if r['task'] == task]
- found_solution = [r['found_solution'] for r in task_list]
- successful_rewards = [
- r['best_reward'] for r in task_list
- if r['found_solution']]
- successful_num_batches = [
- r['num_batches']
- for r in task_list if r['found_solution']]
- successful_program_counts = [
- r['npe'] for r in task_list if r['found_solution']]
- metrics_append = {
- task + '__num_runs': len(task_list),
- task + '__num_succeeded': sum(found_solution),
- task + '__success_rate': (
- sum(found_solution) / float(len(task_list)))}
- metrics.update(metrics_append)
- if any(found_solution):
- metrics_append = {
- task + '__min_reward': min(successful_rewards),
- task + '__max_reward': max(successful_rewards),
- task + '__avg_reward': np.median(successful_rewards),
- task + '__min_programs': min(successful_program_counts),
- task + '__max_programs': max(successful_program_counts),
- task + '__avg_programs': np.mean(successful_program_counts),
- task + '__min_batches': min(successful_num_batches),
- task + '__max_batches': max(successful_num_batches),
- task + '__avg_batches': np.mean(successful_num_batches)}
- metrics.update(metrics_append)
-
- # Objective will be maximized.
- # Maximize success rate, minimize num programs seen.
- # Max objective is always 1.
- weight = FLAGS.success_rate_objective_weight
- objective = (
- weight * success_rate
- + (1 - weight) * (1 - programs_seen_fraction))
- metrics['objective'] = objective
-
- return objective, metrics
-
-
-def main(argv):
- del argv
-
- logging.set_verbosity(FLAGS.log_level)
-
- if not FLAGS.logdir:
- raise ValueError('logdir flag must be provided.')
- if FLAGS.num_workers <= 0:
- raise ValueError('num_workers flag must be greater than 0.')
- if FLAGS.task_id < 0:
- raise ValueError('task_id flag must be greater than or equal to 0.')
- if FLAGS.task_id >= FLAGS.num_workers:
- raise ValueError(
- 'task_id flag must be strictly less than num_workers flag.')
- if FLAGS.num_tuners <= 0:
- raise ValueError('num_tuners flag must be greater than 0.')
- if FLAGS.tuner_id < 0:
- raise ValueError('tuner_id flag must be greater than or equal to 0.')
- if FLAGS.tuner_id >= FLAGS.num_tuners:
- raise ValueError(
- 'tuner_id flag must be strictly less than num_tuners flag.')
-
- ns, _ = run_lib.get_namespace(FLAGS.config)
- run_tuner_loop(ns)
-
-
-if __name__ == '__main__':
- app.run(main)
diff --git a/research/cognitive_mapping_and_planning/.gitignore b/research/cognitive_mapping_and_planning/.gitignore
deleted file mode 100644
index cbc6a8f0271075171ffdf3c2bc5fb9c528b08fc6..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-deps
-*.pyc
-lib*.so
-lib*.so*
diff --git a/research/cognitive_mapping_and_planning/README.md b/research/cognitive_mapping_and_planning/README.md
deleted file mode 100644
index 4457bafbb4d229998a01dadc46efe41f4ba1a3e0..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/README.md
+++ /dev/null
@@ -1,127 +0,0 @@
-
-
-
-
-# Cognitive Mapping and Planning for Visual Navigation
-**Saurabh Gupta, James Davidson, Sergey Levine, Rahul Sukthankar, Jitendra Malik**
-
-**Computer Vision and Pattern Recognition (CVPR) 2017.**
-
-**[ArXiv](https://arxiv.org/abs/1702.03920),
-[Project Website](https://sites.google.com/corp/view/cognitive-mapping-and-planning/)**
-
-### Citing
-If you find this code base and models useful in your research, please consider
-citing the following paper:
- ```
- @inproceedings{gupta2017cognitive,
- title={Cognitive Mapping and Planning for Visual Navigation},
- author={Gupta, Saurabh and Davidson, James and Levine, Sergey and
- Sukthankar, Rahul and Malik, Jitendra},
- booktitle={CVPR},
- year={2017}
- }
- ```
-
-### Contents
-1. [Requirements: software](#requirements-software)
-2. [Requirements: data](#requirements-data)
-3. [Test Pre-trained Models](#test-pre-trained-models)
-4. [Train your Own Models](#train-your-own-models)
-
-### Requirements: software
-1. Python Virtual Env Setup: All code is implemented in Python but depends on a
- small number of python packages and a couple of C libraries. We recommend
- using virtual environment for installing these python packages and python
- bindings for these C libraries.
- ```Shell
- VENV_DIR=venv
- pip install virtualenv
- virtualenv $VENV_DIR
- source $VENV_DIR/bin/activate
-
- # You may need to upgrade pip for installing openv-python.
- pip install --upgrade pip
- # Install simple dependencies.
- pip install -r requirements.txt
-
- # Patch bugs in dependencies.
- sh patches/apply_patches.sh
- ```
-
-2. Install [Tensorflow](https://www.tensorflow.org/) inside this virtual
- environment. You will need to use one of the latest nightly builds
- (see instructions [here](https://github.com/tensorflow/tensorflow#installation)).
-
-3. Swiftshader: We use
- [Swiftshader](https://github.com/google/swiftshader.git), a CPU based
- renderer to render the meshes. It is possible to use other renderers,
- replace `SwiftshaderRenderer` in `render/swiftshader_renderer.py` with
- bindings to your renderer.
- ```Shell
- mkdir -p deps
- git clone --recursive https://github.com/google/swiftshader.git deps/swiftshader-src
- cd deps/swiftshader-src && git checkout 91da6b00584afd7dcaed66da88e2b617429b3950
- git submodule update
- mkdir build && cd build && cmake .. && make -j 16 libEGL libGLESv2
- cd ../../../
- cp deps/swiftshader-src/build/libEGL* libEGL.so.1
- cp deps/swiftshader-src/build/libGLESv2* libGLESv2.so.2
- ```
-
-4. PyAssimp: We use [PyAssimp](https://github.com/assimp/assimp.git) to load
- meshes. It is possible to use other libraries to load meshes, replace
- `Shape` `render/swiftshader_renderer.py` with bindings to your library for
- loading meshes.
- ```Shell
- mkdir -p deps
- git clone https://github.com/assimp/assimp.git deps/assimp-src
- cd deps/assimp-src
- git checkout 2afeddd5cb63d14bc77b53740b38a54a97d94ee8
- cmake CMakeLists.txt -G 'Unix Makefiles' && make -j 16
- cd port/PyAssimp && python setup.py install
- cd ../../../..
- cp deps/assimp-src/lib/libassimp* .
- ```
-
-5. graph-tool: We use [graph-tool](https://git.skewed.de/count0/graph-tool)
- library for graph processing.
- ```Shell
- mkdir -p deps
- # If the following git clone command fails, you can also download the source
- # from https://downloads.skewed.de/graph-tool/graph-tool-2.2.44.tar.bz2
- git clone https://git.skewed.de/count0/graph-tool deps/graph-tool-src
- cd deps/graph-tool-src && git checkout 178add3a571feb6666f4f119027705d95d2951ab
- bash autogen.sh
- ./configure --disable-cairo --disable-sparsehash --prefix=$HOME/.local
- make -j 16
- make install
- cd ../../
- ```
-
-### Requirements: data
-1. Download the Stanford 3D Indoor Spaces Dataset (S3DIS Dataset) and ImageNet
- Pre-trained models for initializing different models. Follow instructions in
- `data/README.md`
-
-### Test Pre-trained Models
-1. Download pre-trained models. See `output/README.md`.
-
-2. Test models using `scripts/script_test_pretrained_models.sh`.
-
-### Train Your Own Models
-All models were trained asynchronously with 16 workers each worker using data
-from a single floor. The default hyper-parameters correspond to this setting.
-See [distributed training with
-Tensorflow](https://www.tensorflow.org/deploy/distributed) for setting up
-distributed training. Training with a single worker is possible with the current
-code base but will require some minor changes to allow each worker to load all
-training environments.
-
-### Contact
-For questions or issues open an issue on the tensorflow/models [issues
-tracker](https://github.com/tensorflow/models/issues). Please assign issues to
-@s-gupta.
-
-### Credits
-This code was written by Saurabh Gupta (@s-gupta).
diff --git a/research/cognitive_mapping_and_planning/__init__.py b/research/cognitive_mapping_and_planning/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/cognitive_mapping_and_planning/cfgs/__init__.py b/research/cognitive_mapping_and_planning/cfgs/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/cognitive_mapping_and_planning/cfgs/config_cmp.py b/research/cognitive_mapping_and_planning/cfgs/config_cmp.py
deleted file mode 100644
index 715eee2b973cb66f816ecdb65bbcc3abdd8a9483..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/cfgs/config_cmp.py
+++ /dev/null
@@ -1,283 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import os, sys
-import numpy as np
-from tensorflow.python.platform import app
-from tensorflow.python.platform import flags
-import logging
-import src.utils as utils
-import cfgs.config_common as cc
-
-
-import tensorflow as tf
-
-
-rgb_resnet_v2_50_path = 'data/init_models/resnet_v2_50/model.ckpt-5136169'
-d_resnet_v2_50_path = 'data/init_models/distill_rgb_to_d_resnet_v2_50/model.ckpt-120002'
-
-def get_default_args():
- summary_args = utils.Foo(display_interval=1, test_iters=26,
- arop_full_summary_iters=14)
-
- control_args = utils.Foo(train=False, test=False,
- force_batchnorm_is_training_at_test=False,
- reset_rng_seed=False, only_eval_when_done=False,
- test_mode=None)
- return summary_args, control_args
-
-def get_default_cmp_args():
- batch_norm_param = {'center': True, 'scale': True,
- 'activation_fn':tf.nn.relu}
-
- mapper_arch_args = utils.Foo(
- dim_reduce_neurons=64,
- fc_neurons=[1024, 1024],
- fc_out_size=8,
- fc_out_neurons=64,
- encoder='resnet_v2_50',
- deconv_neurons=[64, 32, 16, 8, 4, 2],
- deconv_strides=[2, 2, 2, 2, 2, 2],
- deconv_layers_per_block=2,
- deconv_kernel_size=4,
- fc_dropout=0.5,
- combine_type='wt_avg_logits',
- batch_norm_param=batch_norm_param)
-
- readout_maps_arch_args = utils.Foo(
- num_neurons=[],
- strides=[],
- kernel_size=None,
- layers_per_block=None)
-
- arch_args = utils.Foo(
- vin_val_neurons=8, vin_action_neurons=8, vin_ks=3, vin_share_wts=False,
- pred_neurons=[64, 64], pred_batch_norm_param=batch_norm_param,
- conv_on_value_map=0, fr_neurons=16, fr_ver='v2', fr_inside_neurons=64,
- fr_stride=1, crop_remove_each=30, value_crop_size=4,
- action_sample_type='sample', action_sample_combine_type='one_or_other',
- sample_gt_prob_type='inverse_sigmoid_decay', dagger_sample_bn_false=True,
- vin_num_iters=36, isd_k=750., use_agent_loc=False, multi_scale=True,
- readout_maps=False, rom_arch=readout_maps_arch_args)
-
- return arch_args, mapper_arch_args
-
-def get_arch_vars(arch_str):
- if arch_str == '': vals = []
- else: vals = arch_str.split('_')
- ks = ['var1', 'var2', 'var3']
- ks = ks[:len(vals)]
-
- # Exp Ver.
- if len(vals) == 0: ks.append('var1'); vals.append('v0')
- # custom arch.
- if len(vals) == 1: ks.append('var2'); vals.append('')
- # map scape for projection baseline.
- if len(vals) == 2: ks.append('var3'); vals.append('fr2')
-
- assert(len(vals) == 3)
-
- vars = utils.Foo()
- for k, v in zip(ks, vals):
- setattr(vars, k, v)
-
- logging.error('arch_vars: %s', vars)
- return vars
-
-def process_arch_str(args, arch_str):
- # This function modifies args.
- args.arch, args.mapper_arch = get_default_cmp_args()
-
- arch_vars = get_arch_vars(arch_str)
-
- args.navtask.task_params.outputs.ego_maps = True
- args.navtask.task_params.outputs.ego_goal_imgs = True
- args.navtask.task_params.outputs.egomotion = True
- args.navtask.task_params.toy_problem = False
-
- if arch_vars.var1 == 'lmap':
- args = process_arch_learned_map(args, arch_vars)
-
- elif arch_vars.var1 == 'pmap':
- args = process_arch_projected_map(args, arch_vars)
-
- else:
- logging.fatal('arch_vars.var1 should be lmap or pmap, but is %s', arch_vars.var1)
- assert(False)
-
- return args
-
-def process_arch_learned_map(args, arch_vars):
- # Multiscale vision based system.
- args.navtask.task_params.input_type = 'vision'
- args.navtask.task_params.outputs.images = True
-
- if args.navtask.camera_param.modalities[0] == 'rgb':
- args.solver.pretrained_path = rgb_resnet_v2_50_path
- elif args.navtask.camera_param.modalities[0] == 'depth':
- args.solver.pretrained_path = d_resnet_v2_50_path
-
- if arch_vars.var2 == 'Ssc':
- sc = 1./args.navtask.task_params.step_size
- args.arch.vin_num_iters = 40
- args.navtask.task_params.map_scales = [sc]
- max_dist = args.navtask.task_params.max_dist * \
- args.navtask.task_params.num_goals
- args.navtask.task_params.map_crop_sizes = [2*max_dist]
-
- args.arch.fr_stride = 1
- args.arch.vin_action_neurons = 8
- args.arch.vin_val_neurons = 3
- args.arch.fr_inside_neurons = 32
-
- args.mapper_arch.pad_map_with_zeros_each = [24]
- args.mapper_arch.deconv_neurons = [64, 32, 16]
- args.mapper_arch.deconv_strides = [1, 2, 1]
-
- elif (arch_vars.var2 == 'Msc' or arch_vars.var2 == 'MscROMms' or
- arch_vars.var2 == 'MscROMss' or arch_vars.var2 == 'MscNoVin'):
- # Code for multi-scale planner.
- args.arch.vin_num_iters = 8
- args.arch.crop_remove_each = 4
- args.arch.value_crop_size = 8
-
- sc = 1./args.navtask.task_params.step_size
- max_dist = args.navtask.task_params.max_dist * \
- args.navtask.task_params.num_goals
- n_scales = np.log2(float(max_dist) / float(args.arch.vin_num_iters))
- n_scales = int(np.ceil(n_scales)+1)
-
- args.navtask.task_params.map_scales = \
- list(sc*(0.5**(np.arange(n_scales))[::-1]))
- args.navtask.task_params.map_crop_sizes = [16 for x in range(n_scales)]
-
- args.arch.fr_stride = 1
- args.arch.vin_action_neurons = 8
- args.arch.vin_val_neurons = 3
- args.arch.fr_inside_neurons = 32
-
- args.mapper_arch.pad_map_with_zeros_each = [0 for _ in range(n_scales)]
- args.mapper_arch.deconv_neurons = [64*n_scales, 32*n_scales, 16*n_scales]
- args.mapper_arch.deconv_strides = [1, 2, 1]
-
- if arch_vars.var2 == 'MscNoVin':
- # No planning version.
- args.arch.fr_stride = [1, 2, 1, 2]
- args.arch.vin_action_neurons = None
- args.arch.vin_val_neurons = 16
- args.arch.fr_inside_neurons = 32
-
- args.arch.crop_remove_each = 0
- args.arch.value_crop_size = 4
- args.arch.vin_num_iters = 0
-
- elif arch_vars.var2 == 'MscROMms' or arch_vars.var2 == 'MscROMss':
- # Code with read outs, MscROMms flattens and reads out,
- # MscROMss does not flatten and produces output at multiple scales.
- args.navtask.task_params.outputs.readout_maps = True
- args.navtask.task_params.map_resize_method = 'antialiasing'
- args.arch.readout_maps = True
-
- if arch_vars.var2 == 'MscROMms':
- args.arch.rom_arch.num_neurons = [64, 1]
- args.arch.rom_arch.kernel_size = 4
- args.arch.rom_arch.strides = [2,2]
- args.arch.rom_arch.layers_per_block = 2
-
- args.navtask.task_params.readout_maps_crop_sizes = [64]
- args.navtask.task_params.readout_maps_scales = [sc]
-
- elif arch_vars.var2 == 'MscROMss':
- args.arch.rom_arch.num_neurons = \
- [64, len(args.navtask.task_params.map_scales)]
- args.arch.rom_arch.kernel_size = 4
- args.arch.rom_arch.strides = [1,1]
- args.arch.rom_arch.layers_per_block = 1
-
- args.navtask.task_params.readout_maps_crop_sizes = \
- args.navtask.task_params.map_crop_sizes
- args.navtask.task_params.readout_maps_scales = \
- args.navtask.task_params.map_scales
-
- else:
- logging.fatal('arch_vars.var2 not one of Msc, MscROMms, MscROMss, MscNoVin.')
- assert(False)
-
- map_channels = args.mapper_arch.deconv_neurons[-1] / \
- (2*len(args.navtask.task_params.map_scales))
- args.navtask.task_params.map_channels = map_channels
-
- return args
-
-def process_arch_projected_map(args, arch_vars):
- # Single scale vision based system which does not use a mapper but instead
- # uses an analytically estimated map.
- ds = int(arch_vars.var3[2])
- args.navtask.task_params.input_type = 'analytical_counts'
- args.navtask.task_params.outputs.analytical_counts = True
-
- assert(args.navtask.task_params.modalities[0] == 'depth')
- args.navtask.camera_param.img_channels = None
-
- analytical_counts = utils.Foo(map_sizes=[512/ds],
- xy_resolution=[5.*ds],
- z_bins=[[-10, 10, 150, 200]],
- non_linearity=[arch_vars.var2])
- args.navtask.task_params.analytical_counts = analytical_counts
-
- sc = 1./ds
- args.arch.vin_num_iters = 36
- args.navtask.task_params.map_scales = [sc]
- args.navtask.task_params.map_crop_sizes = [512/ds]
-
- args.arch.fr_stride = [1,2]
- args.arch.vin_action_neurons = 8
- args.arch.vin_val_neurons = 3
- args.arch.fr_inside_neurons = 32
-
- map_channels = len(analytical_counts.z_bins[0]) + 1
- args.navtask.task_params.map_channels = map_channels
- args.solver.freeze_conv = False
-
- return args
-
-def get_args_for_config(config_name):
- args = utils.Foo()
-
- args.summary, args.control = get_default_args()
-
- exp_name, mode_str = config_name.split('+')
- arch_str, solver_str, navtask_str = exp_name.split('.')
- logging.error('config_name: %s', config_name)
- logging.error('arch_str: %s', arch_str)
- logging.error('navtask_str: %s', navtask_str)
- logging.error('solver_str: %s', solver_str)
- logging.error('mode_str: %s', mode_str)
-
- args.solver = cc.process_solver_str(solver_str)
- args.navtask = cc.process_navtask_str(navtask_str)
-
- args = process_arch_str(args, arch_str)
- args.arch.isd_k = args.solver.isd_k
-
- # Train, test, etc.
- mode, imset = mode_str.split('_')
- args = cc.adjust_args_for_mode(args, mode)
- args.navtask.building_names = args.navtask.dataset.get_split(imset)
- args.control.test_name = '{:s}_on_{:s}'.format(mode, imset)
-
- # Log the arguments
- logging.error('%s', args)
- return args
diff --git a/research/cognitive_mapping_and_planning/cfgs/config_common.py b/research/cognitive_mapping_and_planning/cfgs/config_common.py
deleted file mode 100644
index 440bf5b72f87a1eeca38e22f33b22e82de7345c0..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/cfgs/config_common.py
+++ /dev/null
@@ -1,261 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import os
-import numpy as np
-import logging
-import src.utils as utils
-import datasets.nav_env_config as nec
-from datasets import factory
-
-def adjust_args_for_mode(args, mode):
- if mode == 'train':
- args.control.train = True
-
- elif mode == 'val1':
- # Same settings as for training, to make sure nothing wonky is happening
- # there.
- args.control.test = True
- args.control.test_mode = 'val'
- args.navtask.task_params.batch_size = 32
-
- elif mode == 'val2':
- # No data augmentation, not sampling but taking the argmax action, not
- # sampling from the ground truth at all.
- args.control.test = True
- args.arch.action_sample_type = 'argmax'
- args.arch.sample_gt_prob_type = 'zero'
- args.navtask.task_params.data_augment = \
- utils.Foo(lr_flip=0, delta_angle=0, delta_xy=0, relight=False,
- relight_fast=False, structured=False)
- args.control.test_mode = 'val'
- args.navtask.task_params.batch_size = 32
-
- elif mode == 'bench':
- # Actually testing the agent in settings that are kept same between
- # different runs.
- args.navtask.task_params.batch_size = 16
- args.control.test = True
- args.arch.action_sample_type = 'argmax'
- args.arch.sample_gt_prob_type = 'zero'
- args.navtask.task_params.data_augment = \
- utils.Foo(lr_flip=0, delta_angle=0, delta_xy=0, relight=False,
- relight_fast=False, structured=False)
- args.summary.test_iters = 250
- args.control.only_eval_when_done = True
- args.control.reset_rng_seed = True
- args.control.test_mode = 'test'
- else:
- logging.fatal('Unknown mode: %s.', mode)
- assert(False)
- return args
-
-def get_solver_vars(solver_str):
- if solver_str == '': vals = [];
- else: vals = solver_str.split('_')
- ks = ['clip', 'dlw', 'long', 'typ', 'isdk', 'adam_eps', 'init_lr'];
- ks = ks[:len(vals)]
-
- # Gradient clipping or not.
- if len(vals) == 0: ks.append('clip'); vals.append('noclip');
- # data loss weight.
- if len(vals) == 1: ks.append('dlw'); vals.append('dlw20')
- # how long to train for.
- if len(vals) == 2: ks.append('long'); vals.append('nolong')
- # Adam
- if len(vals) == 3: ks.append('typ'); vals.append('adam2')
- # reg loss wt
- if len(vals) == 4: ks.append('rlw'); vals.append('rlw1')
- # isd_k
- if len(vals) == 5: ks.append('isdk'); vals.append('isdk415') # 415, inflexion at 2.5k.
- # adam eps
- if len(vals) == 6: ks.append('adam_eps'); vals.append('aeps1en8')
- # init lr
- if len(vals) == 7: ks.append('init_lr'); vals.append('lr1en3')
-
- assert(len(vals) == 8)
-
- vars = utils.Foo()
- for k, v in zip(ks, vals):
- setattr(vars, k, v)
- logging.error('solver_vars: %s', vars)
- return vars
-
-def process_solver_str(solver_str):
- solver = utils.Foo(
- seed=0, learning_rate_decay=None, clip_gradient_norm=None, max_steps=None,
- initial_learning_rate=None, momentum=None, steps_per_decay=None,
- logdir=None, sync=False, adjust_lr_sync=True, wt_decay=0.0001,
- data_loss_wt=None, reg_loss_wt=None, freeze_conv=True, num_workers=1,
- task=0, ps_tasks=0, master='local', typ=None, momentum2=None,
- adam_eps=None)
-
- # Clobber with overrides from solver str.
- solver_vars = get_solver_vars(solver_str)
-
- solver.data_loss_wt = float(solver_vars.dlw[3:].replace('x', '.'))
- solver.adam_eps = float(solver_vars.adam_eps[4:].replace('x', '.').replace('n', '-'))
- solver.initial_learning_rate = float(solver_vars.init_lr[2:].replace('x', '.').replace('n', '-'))
- solver.reg_loss_wt = float(solver_vars.rlw[3:].replace('x', '.'))
- solver.isd_k = float(solver_vars.isdk[4:].replace('x', '.'))
-
- long = solver_vars.long
- if long == 'long':
- solver.steps_per_decay = 40000
- solver.max_steps = 120000
- elif long == 'long2':
- solver.steps_per_decay = 80000
- solver.max_steps = 120000
- elif long == 'nolong' or long == 'nol':
- solver.steps_per_decay = 20000
- solver.max_steps = 60000
- else:
- logging.fatal('solver_vars.long should be long, long2, nolong or nol.')
- assert(False)
-
- clip = solver_vars.clip
- if clip == 'noclip' or clip == 'nocl':
- solver.clip_gradient_norm = 0
- elif clip[:4] == 'clip':
- solver.clip_gradient_norm = float(clip[4:].replace('x', '.'))
- else:
- logging.fatal('Unknown solver_vars.clip: %s', clip)
- assert(False)
-
- typ = solver_vars.typ
- if typ == 'adam':
- solver.typ = 'adam'
- solver.momentum = 0.9
- solver.momentum2 = 0.999
- solver.learning_rate_decay = 1.0
- elif typ == 'adam2':
- solver.typ = 'adam'
- solver.momentum = 0.9
- solver.momentum2 = 0.999
- solver.learning_rate_decay = 0.1
- elif typ == 'sgd':
- solver.typ = 'sgd'
- solver.momentum = 0.99
- solver.momentum2 = None
- solver.learning_rate_decay = 0.1
- else:
- logging.fatal('Unknown solver_vars.typ: %s', typ)
- assert(False)
-
- logging.error('solver: %s', solver)
- return solver
-
-def get_navtask_vars(navtask_str):
- if navtask_str == '': vals = []
- else: vals = navtask_str.split('_')
-
- ks_all = ['dataset_name', 'modality', 'task', 'history', 'max_dist',
- 'num_steps', 'step_size', 'n_ori', 'aux_views', 'data_aug']
- ks = ks_all[:len(vals)]
-
- # All data or not.
- if len(vals) == 0: ks.append('dataset_name'); vals.append('sbpd')
- # modality
- if len(vals) == 1: ks.append('modality'); vals.append('rgb')
- # semantic task?
- if len(vals) == 2: ks.append('task'); vals.append('r2r')
- # number of history frames.
- if len(vals) == 3: ks.append('history'); vals.append('h0')
- # max steps
- if len(vals) == 4: ks.append('max_dist'); vals.append('32')
- # num steps
- if len(vals) == 5: ks.append('num_steps'); vals.append('40')
- # step size
- if len(vals) == 6: ks.append('step_size'); vals.append('8')
- # n_ori
- if len(vals) == 7: ks.append('n_ori'); vals.append('4')
- # Auxiliary views.
- if len(vals) == 8: ks.append('aux_views'); vals.append('nv0')
- # Normal data augmentation as opposed to structured data augmentation (if set
- # to straug.
- if len(vals) == 9: ks.append('data_aug'); vals.append('straug')
-
- assert(len(vals) == 10)
- for i in range(len(ks)):
- assert(ks[i] == ks_all[i])
-
- vars = utils.Foo()
- for k, v in zip(ks, vals):
- setattr(vars, k, v)
- logging.error('navtask_vars: %s', vals)
- return vars
-
-def process_navtask_str(navtask_str):
- navtask = nec.nav_env_base_config()
-
- # Clobber with overrides from strings.
- navtask_vars = get_navtask_vars(navtask_str)
-
- navtask.task_params.n_ori = int(navtask_vars.n_ori)
- navtask.task_params.max_dist = int(navtask_vars.max_dist)
- navtask.task_params.num_steps = int(navtask_vars.num_steps)
- navtask.task_params.step_size = int(navtask_vars.step_size)
- navtask.task_params.data_augment.delta_xy = int(navtask_vars.step_size)/2.
- n_aux_views_each = int(navtask_vars.aux_views[2])
- aux_delta_thetas = np.concatenate((np.arange(n_aux_views_each) + 1,
- -1 -np.arange(n_aux_views_each)))
- aux_delta_thetas = aux_delta_thetas*np.deg2rad(navtask.camera_param.fov)
- navtask.task_params.aux_delta_thetas = aux_delta_thetas
-
- if navtask_vars.data_aug == 'aug':
- navtask.task_params.data_augment.structured = False
- elif navtask_vars.data_aug == 'straug':
- navtask.task_params.data_augment.structured = True
- else:
- logging.fatal('Unknown navtask_vars.data_aug %s.', navtask_vars.data_aug)
- assert(False)
-
- navtask.task_params.num_history_frames = int(navtask_vars.history[1:])
- navtask.task_params.n_views = 1+navtask.task_params.num_history_frames
-
- navtask.task_params.goal_channels = int(navtask_vars.n_ori)
-
- if navtask_vars.task == 'hard':
- navtask.task_params.type = 'rng_rejection_sampling_many'
- navtask.task_params.rejection_sampling_M = 2000
- navtask.task_params.min_dist = 10
- elif navtask_vars.task == 'r2r':
- navtask.task_params.type = 'room_to_room_many'
- elif navtask_vars.task == 'ST':
- # Semantic task at hand.
- navtask.task_params.goal_channels = \
- len(navtask.task_params.semantic_task.class_map_names)
- navtask.task_params.rel_goal_loc_dim = \
- len(navtask.task_params.semantic_task.class_map_names)
- navtask.task_params.type = 'to_nearest_obj_acc'
- else:
- logging.fatal('navtask_vars.task: should be hard or r2r, ST')
- assert(False)
-
- if navtask_vars.modality == 'rgb':
- navtask.camera_param.modalities = ['rgb']
- navtask.camera_param.img_channels = 3
- elif navtask_vars.modality == 'd':
- navtask.camera_param.modalities = ['depth']
- navtask.camera_param.img_channels = 2
-
- navtask.task_params.img_height = navtask.camera_param.height
- navtask.task_params.img_width = navtask.camera_param.width
- navtask.task_params.modalities = navtask.camera_param.modalities
- navtask.task_params.img_channels = navtask.camera_param.img_channels
- navtask.task_params.img_fov = navtask.camera_param.fov
-
- navtask.dataset = factory.get_dataset(navtask_vars.dataset_name)
- return navtask
diff --git a/research/cognitive_mapping_and_planning/cfgs/config_distill.py b/research/cognitive_mapping_and_planning/cfgs/config_distill.py
deleted file mode 100644
index 53be2f8a5f12ee701a53c1c354079659da6958d4..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/cfgs/config_distill.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import pprint
-import copy
-import os
-from tensorflow.python.platform import app
-from tensorflow.python.platform import flags
-import logging
-import src.utils as utils
-import cfgs.config_common as cc
-
-
-import tensorflow as tf
-
-rgb_resnet_v2_50_path = 'cache/resnet_v2_50_inception_preprocessed/model.ckpt-5136169'
-
-def get_default_args():
- robot = utils.Foo(radius=15, base=10, height=140, sensor_height=120,
- camera_elevation_degree=-15)
-
- camera_param = utils.Foo(width=225, height=225, z_near=0.05, z_far=20.0,
- fov=60., modalities=['rgb', 'depth'])
-
- env = utils.Foo(padding=10, resolution=5, num_point_threshold=2,
- valid_min=-10, valid_max=200, n_samples_per_face=200)
-
- data_augment = utils.Foo(lr_flip=0, delta_angle=1, delta_xy=4, relight=False,
- relight_fast=False, structured=False)
-
- task_params = utils.Foo(num_actions=4, step_size=4, num_steps=0,
- batch_size=32, room_seed=0, base_class='Building',
- task='mapping', n_ori=6, data_augment=data_augment,
- output_transform_to_global_map=False,
- output_canonical_map=False,
- output_incremental_transform=False,
- output_free_space=False, move_type='shortest_path',
- toy_problem=0)
-
- buildinger_args = utils.Foo(building_names=['area1_gates_wingA_floor1_westpart'],
- env_class=None, robot=robot,
- task_params=task_params, env=env,
- camera_param=camera_param)
-
- solver_args = utils.Foo(seed=0, learning_rate_decay=0.1,
- clip_gradient_norm=0, max_steps=120000,
- initial_learning_rate=0.001, momentum=0.99,
- steps_per_decay=40000, logdir=None, sync=False,
- adjust_lr_sync=True, wt_decay=0.0001,
- data_loss_wt=1.0, reg_loss_wt=1.0,
- num_workers=1, task=0, ps_tasks=0, master='local')
-
- summary_args = utils.Foo(display_interval=1, test_iters=100)
-
- control_args = utils.Foo(train=False, test=False,
- force_batchnorm_is_training_at_test=False)
-
- arch_args = utils.Foo(rgb_encoder='resnet_v2_50', d_encoder='resnet_v2_50')
-
- return utils.Foo(solver=solver_args,
- summary=summary_args, control=control_args, arch=arch_args,
- buildinger=buildinger_args)
-
-def get_vars(config_name):
- vars = config_name.split('_')
- if len(vars) == 1: # All data or not.
- vars.append('noall')
- if len(vars) == 2: # n_ori
- vars.append('4')
- logging.error('vars: %s', vars)
- return vars
-
-def get_args_for_config(config_name):
- args = get_default_args()
- config_name, mode = config_name.split('+')
- vars = get_vars(config_name)
-
- logging.info('config_name: %s, mode: %s', config_name, mode)
-
- args.buildinger.task_params.n_ori = int(vars[2])
- args.solver.freeze_conv = True
- args.solver.pretrained_path = rgb_resnet_v2_50_path
- args.buildinger.task_params.img_channels = 5
- args.solver.data_loss_wt = 0.00001
-
- if vars[0] == 'v0':
- None
- else:
- logging.error('config_name: %s undefined', config_name)
-
- args.buildinger.task_params.height = args.buildinger.camera_param.height
- args.buildinger.task_params.width = args.buildinger.camera_param.width
- args.buildinger.task_params.modalities = args.buildinger.camera_param.modalities
-
- if vars[1] == 'all':
- args = cc.get_args_for_mode_building_all(args, mode)
- elif vars[1] == 'noall':
- args = cc.get_args_for_mode_building(args, mode)
-
- # Log the arguments
- logging.error('%s', args)
- return args
diff --git a/research/cognitive_mapping_and_planning/cfgs/config_vision_baseline.py b/research/cognitive_mapping_and_planning/cfgs/config_vision_baseline.py
deleted file mode 100644
index 3cc64fe594ab025fbcfb41543302fa42c7fc0074..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/cfgs/config_vision_baseline.py
+++ /dev/null
@@ -1,173 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import pprint
-import os
-import numpy as np
-from tensorflow.python.platform import app
-from tensorflow.python.platform import flags
-import logging
-import src.utils as utils
-import cfgs.config_common as cc
-import datasets.nav_env_config as nec
-
-
-import tensorflow as tf
-
-FLAGS = flags.FLAGS
-
-get_solver_vars = cc.get_solver_vars
-get_navtask_vars = cc.get_navtask_vars
-
-
-rgb_resnet_v2_50_path = 'data/init_models/resnet_v2_50/model.ckpt-5136169'
-d_resnet_v2_50_path = 'data/init_models/distill_rgb_to_d_resnet_v2_50/model.ckpt-120002'
-
-def get_default_args():
- summary_args = utils.Foo(display_interval=1, test_iters=26,
- arop_full_summary_iters=14)
-
- control_args = utils.Foo(train=False, test=False,
- force_batchnorm_is_training_at_test=False,
- reset_rng_seed=False, only_eval_when_done=False,
- test_mode=None)
- return summary_args, control_args
-
-def get_default_baseline_args():
- batch_norm_param = {'center': True, 'scale': True,
- 'activation_fn':tf.nn.relu}
- arch_args = utils.Foo(
- pred_neurons=[], goal_embed_neurons=[], img_embed_neurons=[],
- batch_norm_param=batch_norm_param, dim_reduce_neurons=64, combine_type='',
- encoder='resnet_v2_50', action_sample_type='sample',
- action_sample_combine_type='one_or_other',
- sample_gt_prob_type='inverse_sigmoid_decay', dagger_sample_bn_false=True,
- isd_k=750., use_visit_count=False, lstm_output=False, lstm_ego=False,
- lstm_img=False, fc_dropout=0.0, embed_goal_for_state=False,
- lstm_output_init_state_from_goal=False)
- return arch_args
-
-def get_arch_vars(arch_str):
- if arch_str == '': vals = []
- else: vals = arch_str.split('_')
-
- ks = ['ver', 'lstm_dim', 'dropout']
-
- # Exp Ver
- if len(vals) == 0: vals.append('v0')
- # LSTM dimentsions
- if len(vals) == 1: vals.append('lstm2048')
- # Dropout
- if len(vals) == 2: vals.append('noDO')
-
- assert(len(vals) == 3)
-
- vars = utils.Foo()
- for k, v in zip(ks, vals):
- setattr(vars, k, v)
-
- logging.error('arch_vars: %s', vars)
- return vars
-
-def process_arch_str(args, arch_str):
- # This function modifies args.
- args.arch = get_default_baseline_args()
- arch_vars = get_arch_vars(arch_str)
-
- args.navtask.task_params.outputs.rel_goal_loc = True
- args.navtask.task_params.input_type = 'vision'
- args.navtask.task_params.outputs.images = True
-
- if args.navtask.camera_param.modalities[0] == 'rgb':
- args.solver.pretrained_path = rgb_resnet_v2_50_path
- elif args.navtask.camera_param.modalities[0] == 'depth':
- args.solver.pretrained_path = d_resnet_v2_50_path
- else:
- logging.fatal('Neither of rgb or d')
-
- if arch_vars.dropout == 'DO':
- args.arch.fc_dropout = 0.5
-
- args.tfcode = 'B'
-
- exp_ver = arch_vars.ver
- if exp_ver == 'v0':
- # Multiplicative interaction between goal loc and image features.
- args.arch.combine_type = 'multiply'
- args.arch.pred_neurons = [256, 256]
- args.arch.goal_embed_neurons = [64, 8]
- args.arch.img_embed_neurons = [1024, 512, 256*8]
-
- elif exp_ver == 'v1':
- # Additive interaction between goal and image features.
- args.arch.combine_type = 'add'
- args.arch.pred_neurons = [256, 256]
- args.arch.goal_embed_neurons = [64, 256]
- args.arch.img_embed_neurons = [1024, 512, 256]
-
- elif exp_ver == 'v2':
- # LSTM at the output on top of multiple interactions.
- args.arch.combine_type = 'multiply'
- args.arch.goal_embed_neurons = [64, 8]
- args.arch.img_embed_neurons = [1024, 512, 256*8]
- args.arch.lstm_output = True
- args.arch.lstm_output_dim = int(arch_vars.lstm_dim[4:])
- args.arch.pred_neurons = [256] # The other is inside the LSTM.
-
- elif exp_ver == 'v0blind':
- # LSTM only on the goal location.
- args.arch.combine_type = 'goalonly'
- args.arch.goal_embed_neurons = [64, 256]
- args.arch.img_embed_neurons = [2] # I dont know what it will do otherwise.
- args.arch.lstm_output = True
- args.arch.lstm_output_dim = 256
- args.arch.pred_neurons = [256] # The other is inside the LSTM.
-
- else:
- logging.fatal('exp_ver: %s undefined', exp_ver)
- assert(False)
-
- # Log the arguments
- logging.error('%s', args)
- return args
-
-def get_args_for_config(config_name):
- args = utils.Foo()
-
- args.summary, args.control = get_default_args()
-
- exp_name, mode_str = config_name.split('+')
- arch_str, solver_str, navtask_str = exp_name.split('.')
- logging.error('config_name: %s', config_name)
- logging.error('arch_str: %s', arch_str)
- logging.error('navtask_str: %s', navtask_str)
- logging.error('solver_str: %s', solver_str)
- logging.error('mode_str: %s', mode_str)
-
- args.solver = cc.process_solver_str(solver_str)
- args.navtask = cc.process_navtask_str(navtask_str)
-
- args = process_arch_str(args, arch_str)
- args.arch.isd_k = args.solver.isd_k
-
- # Train, test, etc.
- mode, imset = mode_str.split('_')
- args = cc.adjust_args_for_mode(args, mode)
- args.navtask.building_names = args.navtask.dataset.get_split(imset)
- args.control.test_name = '{:s}_on_{:s}'.format(mode, imset)
-
- # Log the arguments
- logging.error('%s', args)
- return args
diff --git a/research/cognitive_mapping_and_planning/data/.gitignore b/research/cognitive_mapping_and_planning/data/.gitignore
deleted file mode 100644
index 2b6d5e46652d14a9c0a8025dbcccfc2dd4376e4a..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/data/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-stanford_building_parser_dataset_raw
-stanford_building_parser_dataset
-init_models
diff --git a/research/cognitive_mapping_and_planning/data/README.md b/research/cognitive_mapping_and_planning/data/README.md
deleted file mode 100644
index a8928345351dac19c0e12fd33f99dd2aa600e23b..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/data/README.md
+++ /dev/null
@@ -1,33 +0,0 @@
-This directory contains the data needed for training and benchmarking various
-navigation models.
-
-1. Download the data from the [dataset website]
- (http://buildingparser.stanford.edu/dataset.html).
- 1. [Raw meshes](https://goo.gl/forms/2YSPaO2UKmn5Td5m2). We need the meshes
- which are in the noXYZ folder. Download the tar files and place them in
- the `stanford_building_parser_dataset_raw` folder. You need to download
- `area_1_noXYZ.tar`, `area_3_noXYZ.tar`, `area_5a_noXYZ.tar`,
- `area_5b_noXYZ.tar`, `area_6_noXYZ.tar` for training and
- `area_4_noXYZ.tar` for evaluation.
- 2. [Annotations](https://goo.gl/forms/4SoGp4KtH1jfRqEj2) for setting up
- tasks. We will need the file called `Stanford3dDataset_v1.2.zip`. Place
- the file in the directory `stanford_building_parser_dataset_raw`.
-
-2. Preprocess the data.
- 1. Extract meshes using `scripts/script_preprocess_meshes_S3DIS.sh`. After
- this `ls data/stanford_building_parser_dataset/mesh` should have 6
- folders `area1`, `area3`, `area4`, `area5a`, `area5b`, `area6`, with
- textures and obj files within each directory.
- 2. Extract out room information and semantics from zip file using
- `scripts/script_preprocess_annoations_S3DIS.sh`. After this there should
- be `room-dimension` and `class-maps` folder in
- `data/stanford_building_parser_dataset`. (If you find this script to
- crash because of an exception in np.loadtxt while processing
- `Area_5/office_19/Annotations/ceiling_1.txt`, there is a special
- character on line 323474, that should be removed manually.)
-
-3. Download ImageNet Pre-trained models. We used ResNet-v2-50 for representing
- images. For RGB images this is pre-trained on ImageNet. For Depth images we
- [distill](https://arxiv.org/abs/1507.00448) the RGB model to depth images
- using paired RGB-D images. Both there models are available through
- `scripts/script_download_init_models.sh`
diff --git a/research/cognitive_mapping_and_planning/datasets/__init__.py b/research/cognitive_mapping_and_planning/datasets/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/cognitive_mapping_and_planning/datasets/factory.py b/research/cognitive_mapping_and_planning/datasets/factory.py
deleted file mode 100644
index 3f7b5c0a602dbacf9619dc1c2ec98e94200428b6..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/datasets/factory.py
+++ /dev/null
@@ -1,113 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-r"""Wrapper for selecting the navigation environment that we want to train and
-test on.
-"""
-import numpy as np
-import os, glob
-import platform
-
-import logging
-from tensorflow.python.platform import app
-from tensorflow.python.platform import flags
-
-import render.swiftshader_renderer as renderer
-import src.file_utils as fu
-import src.utils as utils
-
-def get_dataset(dataset_name):
- if dataset_name == 'sbpd':
- dataset = StanfordBuildingParserDataset(dataset_name)
- else:
- logging.fatal('Not one of sbpd')
- return dataset
-
-class Loader():
- def get_data_dir():
- pass
-
- def get_meta_data(self, file_name, data_dir=None):
- if data_dir is None:
- data_dir = self.get_data_dir()
- full_file_name = os.path.join(data_dir, 'meta', file_name)
- assert(fu.exists(full_file_name)), \
- '{:s} does not exist'.format(full_file_name)
- ext = os.path.splitext(full_file_name)[1]
- if ext == '.txt':
- ls = []
- with fu.fopen(full_file_name, 'r') as f:
- for l in f:
- ls.append(l.rstrip())
- elif ext == '.pkl':
- ls = utils.load_variables(full_file_name)
- return ls
-
- def load_building(self, name, data_dir=None):
- if data_dir is None:
- data_dir = self.get_data_dir()
- out = {}
- out['name'] = name
- out['data_dir'] = data_dir
- out['room_dimension_file'] = os.path.join(data_dir, 'room-dimension',
- name+'.pkl')
- out['class_map_folder'] = os.path.join(data_dir, 'class-maps')
- return out
-
- def load_building_meshes(self, building):
- dir_name = os.path.join(building['data_dir'], 'mesh', building['name'])
- mesh_file_name = glob.glob1(dir_name, '*.obj')[0]
- mesh_file_name_full = os.path.join(dir_name, mesh_file_name)
- logging.error('Loading building from obj file: %s', mesh_file_name_full)
- shape = renderer.Shape(mesh_file_name_full, load_materials=True,
- name_prefix=building['name']+'_')
- return [shape]
-
-class StanfordBuildingParserDataset(Loader):
- def __init__(self, ver):
- self.ver = ver
- self.data_dir = None
-
- def get_data_dir(self):
- if self.data_dir is None:
- self.data_dir = 'data/stanford_building_parser_dataset/'
- return self.data_dir
-
- def get_benchmark_sets(self):
- return self._get_benchmark_sets()
-
- def get_split(self, split_name):
- if self.ver == 'sbpd':
- return self._get_split(split_name)
- else:
- logging.fatal('Unknown version.')
-
- def _get_benchmark_sets(self):
- sets = ['train1', 'val', 'test']
- return sets
-
- def _get_split(self, split_name):
- train = ['area1', 'area5a', 'area5b', 'area6']
- train1 = ['area1']
- val = ['area3']
- test = ['area4']
-
- sets = {}
- sets['train'] = train
- sets['train1'] = train1
- sets['val'] = val
- sets['test'] = test
- sets['all'] = sorted(list(set(train + val + test)))
- return sets[split_name]
diff --git a/research/cognitive_mapping_and_planning/datasets/nav_env.py b/research/cognitive_mapping_and_planning/datasets/nav_env.py
deleted file mode 100644
index 5710e26dcb113121d99400cb060104224dd91749..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/datasets/nav_env.py
+++ /dev/null
@@ -1,1465 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-r"""Navidation Environment. Includes the following classes along with some
-helper functions.
- Building: Loads buildings, computes traversibility, exposes functionality for
- rendering images.
-
- GridWorld: Base class which implements functionality for moving an agent on a
- grid world.
-
- NavigationEnv: Base class which generates navigation problems on a grid world.
-
- VisualNavigationEnv: Builds upon NavigationEnv and Building to provide
- interface that is used externally to train the agent.
-
- MeshMapper: Class used for distilling the model, testing the mapper.
-
- BuildingMultiplexer: Wrapper class that instantiates a VisualNavigationEnv for
- each building and multiplexes between them as needed.
-"""
-
-import numpy as np
-import os
-import re
-import matplotlib.pyplot as plt
-
-import graph_tool as gt
-import graph_tool.topology
-
-from tensorflow.python.platform import gfile
-import logging
-import src.file_utils as fu
-import src.utils as utils
-import src.graph_utils as gu
-import src.map_utils as mu
-import src.depth_utils as du
-import render.swiftshader_renderer as sru
-from render.swiftshader_renderer import SwiftshaderRenderer
-import cv2
-
-label_nodes_with_class = gu.label_nodes_with_class
-label_nodes_with_class_geodesic = gu.label_nodes_with_class_geodesic
-get_distance_node_list = gu.get_distance_node_list
-convert_to_graph_tool = gu.convert_to_graph_tool
-generate_graph = gu.generate_graph
-get_hardness_distribution = gu.get_hardness_distribution
-rng_next_goal_rejection_sampling = gu.rng_next_goal_rejection_sampling
-rng_next_goal = gu.rng_next_goal
-rng_room_to_room = gu.rng_room_to_room
-rng_target_dist_field = gu.rng_target_dist_field
-
-compute_traversibility = mu.compute_traversibility
-make_map = mu.make_map
-resize_maps = mu.resize_maps
-pick_largest_cc = mu.pick_largest_cc
-get_graph_origin_loc = mu.get_graph_origin_loc
-generate_egocentric_maps = mu.generate_egocentric_maps
-generate_goal_images = mu.generate_goal_images
-get_map_to_predict = mu.get_map_to_predict
-
-bin_points = du.bin_points
-make_geocentric = du.make_geocentric
-get_point_cloud_from_z = du.get_point_cloud_from_z
-get_camera_matrix = du.get_camera_matrix
-
-def _get_semantic_maps(folder_name, building_name, map, flip):
- # Load file from the cache.
- file_name = '{:s}_{:d}_{:d}_{:d}_{:d}_{:d}_{:d}.pkl'
- file_name = file_name.format(building_name, map.size[0], map.size[1],
- map.origin[0], map.origin[1], map.resolution,
- flip)
- file_name = os.path.join(folder_name, file_name)
- logging.info('Loading semantic maps from %s.', file_name)
-
- if fu.exists(file_name):
- a = utils.load_variables(file_name)
- maps = a['maps'] #HxWx#C
- cats = a['cats']
- else:
- logging.error('file_name: %s not found.', file_name)
- maps = None
- cats = None
- return maps, cats
-
-def _select_classes(all_maps, all_cats, cats_to_use):
- inds = []
- for c in cats_to_use:
- ind = all_cats.index(c)
- inds.append(ind)
- out_maps = all_maps[:,:,inds]
- return out_maps
-
-def _get_room_dimensions(file_name, resolution, origin, flip=False):
- if fu.exists(file_name):
- a = utils.load_variables(file_name)['room_dimension']
- names = a.keys()
- dims = np.concatenate(a.values(), axis=0).reshape((-1,6))
- ind = np.argsort(names)
- dims = dims[ind,:]
- names = [names[x] for x in ind]
- if flip:
- dims_new = dims*1
- dims_new[:,1] = -dims[:,4]
- dims_new[:,4] = -dims[:,1]
- dims = dims_new*1
-
- dims = dims*100.
- dims[:,0] = dims[:,0] - origin[0]
- dims[:,1] = dims[:,1] - origin[1]
- dims[:,3] = dims[:,3] - origin[0]
- dims[:,4] = dims[:,4] - origin[1]
- dims = dims / resolution
- out = {'names': names, 'dims': dims}
- else:
- out = None
- return out
-
-def _filter_rooms(room_dims, room_regex):
- pattern = re.compile(room_regex)
- ind = []
- for i, name in enumerate(room_dims['names']):
- if pattern.match(name):
- ind.append(i)
- new_room_dims = {}
- new_room_dims['names'] = [room_dims['names'][i] for i in ind]
- new_room_dims['dims'] = room_dims['dims'][ind,:]*1
- return new_room_dims
-
-def _label_nodes_with_room_id(xyt, room_dims):
- # Label the room with the ID into things.
- node_room_id = -1*np.ones((xyt.shape[0], 1))
- dims = room_dims['dims']
- for x, name in enumerate(room_dims['names']):
- all_ = np.concatenate((xyt[:,[0]] >= dims[x,0],
- xyt[:,[0]] <= dims[x,3],
- xyt[:,[1]] >= dims[x,1],
- xyt[:,[1]] <= dims[x,4]), axis=1)
- node_room_id[np.all(all_, axis=1), 0] = x
- return node_room_id
-
-def get_path_ids(start_node_id, end_node_id, pred_map):
- id = start_node_id
- path = [id]
- while id != end_node_id:
- id = pred_map[id]
- path.append(id)
- return path
-
-def image_pre(images, modalities):
- # Assumes images are ...xHxWxC.
- # We always assume images are RGB followed by Depth.
- if 'depth' in modalities:
- d = images[...,-1][...,np.newaxis]*1.
- d[d < 0.01] = np.NaN; isnan = np.isnan(d);
- d = 100./d; d[isnan] = 0.;
- images = np.concatenate((images[...,:-1], d, isnan), axis=images.ndim-1)
- if 'rgb' in modalities:
- images[...,:3] = images[...,:3]*1. - 128
- return images
-
-def _get_relative_goal_loc(goal_loc, loc, theta):
- r = np.sqrt(np.sum(np.square(goal_loc - loc), axis=1))
- t = np.arctan2(goal_loc[:,1] - loc[:,1], goal_loc[:,0] - loc[:,0])
- t = t-theta[:,0] + np.pi/2
- return np.expand_dims(r,axis=1), np.expand_dims(t, axis=1)
-
-def _gen_perturbs(rng, batch_size, num_steps, lr_flip, delta_angle, delta_xy,
- structured):
- perturbs = []
- for i in range(batch_size):
- # Doing things one by one for each episode in this batch. This way this
- # remains replicatable even when we change the batch size.
- p = np.zeros((num_steps+1, 4))
- if lr_flip:
- # Flip the whole trajectory.
- p[:,3] = rng.rand(1)-0.5
- if delta_angle > 0:
- if structured:
- p[:,2] = (rng.rand(1)-0.5)* delta_angle
- else:
- p[:,2] = (rng.rand(p.shape[0])-0.5)* delta_angle
- if delta_xy > 0:
- if structured:
- p[:,:2] = (rng.rand(1, 2)-0.5)*delta_xy
- else:
- p[:,:2] = (rng.rand(p.shape[0], 2)-0.5)*delta_xy
- perturbs.append(p)
- return perturbs
-
-def get_multiplexer_class(args, task_number):
- assert(args.task_params.base_class == 'Building')
- logging.info('Returning BuildingMultiplexer')
- R = BuildingMultiplexer(args, task_number)
- return R
-
-class GridWorld():
- def __init__(self):
- """Class members that will be assigned by any class that actually uses this
- class."""
- self.restrict_to_largest_cc = None
- self.robot = None
- self.env = None
- self.category_list = None
- self.traversible = None
-
- def get_loc_axis(self, node, delta_theta, perturb=None):
- """Based on the node orientation returns X, and Y axis. Used to sample the
- map in egocentric coordinate frame.
- """
- if type(node) == tuple:
- node = np.array([node])
- if perturb is None:
- perturb = np.zeros((node.shape[0], 4))
- xyt = self.to_actual_xyt_vec(node)
- x = xyt[:,[0]] + perturb[:,[0]]
- y = xyt[:,[1]] + perturb[:,[1]]
- t = xyt[:,[2]] + perturb[:,[2]]
- theta = t*delta_theta
- loc = np.concatenate((x,y), axis=1)
- x_axis = np.concatenate((np.cos(theta), np.sin(theta)), axis=1)
- y_axis = np.concatenate((np.cos(theta+np.pi/2.), np.sin(theta+np.pi/2.)),
- axis=1)
- # Flip the sampled map where need be.
- y_axis[np.where(perturb[:,3] > 0)[0], :] *= -1.
- return loc, x_axis, y_axis, theta
-
- def to_actual_xyt(self, pqr):
- """Converts from node to location on the map."""
- (p, q, r) = pqr
- if self.task.n_ori == 6:
- out = (p - q * 0.5 + self.task.origin_loc[0],
- q * np.sqrt(3.) / 2. + self.task.origin_loc[1], r)
- elif self.task.n_ori == 4:
- out = (p + self.task.origin_loc[0],
- q + self.task.origin_loc[1], r)
- return out
-
- def to_actual_xyt_vec(self, pqr):
- """Converts from node array to location array on the map."""
- p = pqr[:,0][:, np.newaxis]
- q = pqr[:,1][:, np.newaxis]
- r = pqr[:,2][:, np.newaxis]
- if self.task.n_ori == 6:
- out = np.concatenate((p - q * 0.5 + self.task.origin_loc[0],
- q * np.sqrt(3.) / 2. + self.task.origin_loc[1],
- r), axis=1)
- elif self.task.n_ori == 4:
- out = np.concatenate((p + self.task.origin_loc[0],
- q + self.task.origin_loc[1],
- r), axis=1)
- return out
-
- def raw_valid_fn_vec(self, xyt):
- """Returns if the given set of nodes is valid or not."""
- height = self.traversible.shape[0]
- width = self.traversible.shape[1]
- x = np.round(xyt[:,[0]]).astype(np.int32)
- y = np.round(xyt[:,[1]]).astype(np.int32)
- is_inside = np.all(np.concatenate((x >= 0, y >= 0,
- x < width, y < height), axis=1), axis=1)
- x = np.minimum(np.maximum(x, 0), width-1)
- y = np.minimum(np.maximum(y, 0), height-1)
- ind = np.ravel_multi_index((y,x), self.traversible.shape)
- is_traversible = self.traversible.ravel()[ind]
-
- is_valid = np.all(np.concatenate((is_inside[:,np.newaxis], is_traversible),
- axis=1), axis=1)
- return is_valid
-
-
- def valid_fn_vec(self, pqr):
- """Returns if the given set of nodes is valid or not."""
- xyt = self.to_actual_xyt_vec(np.array(pqr))
- height = self.traversible.shape[0]
- width = self.traversible.shape[1]
- x = np.round(xyt[:,[0]]).astype(np.int32)
- y = np.round(xyt[:,[1]]).astype(np.int32)
- is_inside = np.all(np.concatenate((x >= 0, y >= 0,
- x < width, y < height), axis=1), axis=1)
- x = np.minimum(np.maximum(x, 0), width-1)
- y = np.minimum(np.maximum(y, 0), height-1)
- ind = np.ravel_multi_index((y,x), self.traversible.shape)
- is_traversible = self.traversible.ravel()[ind]
-
- is_valid = np.all(np.concatenate((is_inside[:,np.newaxis], is_traversible),
- axis=1), axis=1)
- return is_valid
-
- def get_feasible_actions(self, node_ids):
- """Returns the feasible set of actions from the current node."""
- a = np.zeros((len(node_ids), self.task_params.num_actions), dtype=np.int32)
- gtG = self.task.gtG
- next_node = []
- for i, c in enumerate(node_ids):
- neigh = gtG.vertex(c).out_neighbours()
- neigh_edge = gtG.vertex(c).out_edges()
- nn = {}
- for n, e in zip(neigh, neigh_edge):
- _ = gtG.ep['action'][e]
- a[i,_] = 1
- nn[_] = int(n)
- next_node.append(nn)
- return a, next_node
-
- def take_action(self, current_node_ids, action):
- """Returns the new node after taking the action action. Stays at the current
- node if the action is invalid."""
- actions, next_node_ids = self.get_feasible_actions(current_node_ids)
- new_node_ids = []
- for i, (c,a) in enumerate(zip(current_node_ids, action)):
- if actions[i,a] == 1:
- new_node_ids.append(next_node_ids[i][a])
- else:
- new_node_ids.append(c)
- return new_node_ids
-
- def set_r_obj(self, r_obj):
- """Sets the SwiftshaderRenderer object used for rendering."""
- self.r_obj = r_obj
-
-class Building(GridWorld):
- def __init__(self, building_name, robot, env,
- category_list=None, small=False, flip=False, logdir=None,
- building_loader=None):
-
- self.restrict_to_largest_cc = True
- self.robot = robot
- self.env = env
- self.logdir = logdir
-
- # Load the building meta data.
- building = building_loader.load_building(building_name)
- if small:
- building['mesh_names'] = building['mesh_names'][:5]
-
- # New code.
- shapess = building_loader.load_building_meshes(building)
- if flip:
- for shapes in shapess:
- shapes.flip_shape()
-
- vs = []
- for shapes in shapess:
- vs.append(shapes.get_vertices()[0])
- vs = np.concatenate(vs, axis=0)
- map = make_map(env.padding, env.resolution, vertex=vs, sc=100.)
- map = compute_traversibility(
- map, robot.base, robot.height, robot.radius, env.valid_min,
- env.valid_max, env.num_point_threshold, shapess=shapess, sc=100.,
- n_samples_per_face=env.n_samples_per_face)
-
- room_dims = _get_room_dimensions(building['room_dimension_file'],
- env.resolution, map.origin, flip=flip)
- class_maps, class_map_names = _get_semantic_maps(
- building['class_map_folder'], building_name, map, flip)
-
- self.class_maps = class_maps
- self.class_map_names = class_map_names
- self.building = building
- self.shapess = shapess
- self.map = map
- self.traversible = map.traversible*1
- self.building_name = building_name
- self.room_dims = room_dims
- self.flipped = flip
- self.renderer_entitiy_ids = []
-
- if self.restrict_to_largest_cc:
- self.traversible = pick_largest_cc(self.traversible)
-
- def load_building_into_scene(self):
- # Loads the scene.
- self.renderer_entitiy_ids += self.r_obj.load_shapes(self.shapess)
- # Free up memory, we dont need the mesh or the materials anymore.
- self.shapess = None
-
- def add_entity_at_nodes(self, nodes, height, shape):
- xyt = self.to_actual_xyt_vec(nodes)
- nxy = xyt[:,:2]*1.
- nxy = nxy * self.map.resolution
- nxy = nxy + self.map.origin
- Ts = np.concatenate((nxy, nxy[:,:1]), axis=1)
- Ts[:,2] = height; Ts = Ts / 100.;
-
- # Merge all the shapes into a single shape and add that shape.
- shape.replicate_shape(Ts)
- entity_ids = self.r_obj.load_shapes([shape])
- self.renderer_entitiy_ids += entity_ids
- return entity_ids
-
- def add_shapes(self, shapes):
- scene = self.r_obj.viz.scene()
- for shape in shapes:
- scene.AddShape(shape)
-
- def add_materials(self, materials):
- scene = self.r_obj.viz.scene()
- for material in materials:
- scene.AddOrUpdateMaterial(material)
-
- def set_building_visibility(self, visibility):
- self.r_obj.set_entity_visible(self.renderer_entitiy_ids, visibility)
-
- def render_nodes(self, nodes, perturb=None, aux_delta_theta=0.):
- self.set_building_visibility(True)
- if perturb is None:
- perturb = np.zeros((len(nodes), 4))
-
- imgs = []
- r = 2
- elevation_z = r * np.tan(np.deg2rad(self.robot.camera_elevation_degree))
-
- for i in range(len(nodes)):
- xyt = self.to_actual_xyt(nodes[i])
- lookat_theta = 3.0 * np.pi / 2.0 - (xyt[2]+perturb[i,2]+aux_delta_theta) * (self.task.delta_theta)
- nxy = np.array([xyt[0]+perturb[i,0], xyt[1]+perturb[i,1]]).reshape(1, -1)
- nxy = nxy * self.map.resolution
- nxy = nxy + self.map.origin
- camera_xyz = np.zeros((1, 3))
- camera_xyz[...] = [nxy[0, 0], nxy[0, 1], self.robot.sensor_height]
- camera_xyz = camera_xyz / 100.
- lookat_xyz = np.array([-r * np.sin(lookat_theta),
- -r * np.cos(lookat_theta), elevation_z])
- lookat_xyz = lookat_xyz + camera_xyz[0, :]
- self.r_obj.position_camera(camera_xyz[0, :].tolist(),
- lookat_xyz.tolist(), [0.0, 0.0, 1.0])
- img = self.r_obj.render(take_screenshot=True, output_type=0)
- img = [x for x in img if x is not None]
- img = np.concatenate(img, axis=2).astype(np.float32)
- if perturb[i,3]>0:
- img = img[:,::-1,:]
- imgs.append(img)
-
- self.set_building_visibility(False)
- return imgs
-
-
-class MeshMapper(Building):
- def __init__(self, robot, env, task_params, building_name, category_list,
- flip, logdir=None, building_loader=None):
- Building.__init__(self, building_name, robot, env, category_list,
- small=task_params.toy_problem, flip=flip, logdir=logdir,
- building_loader=building_loader)
- self.task_params = task_params
- self.task = None
- self._preprocess_for_task(self.task_params.building_seed)
-
- def _preprocess_for_task(self, seed):
- if self.task is None or self.task.seed != seed:
- rng = np.random.RandomState(seed)
- origin_loc = get_graph_origin_loc(rng, self.traversible)
- self.task = utils.Foo(seed=seed, origin_loc=origin_loc,
- n_ori=self.task_params.n_ori)
- G = generate_graph(self.valid_fn_vec,
- self.task_params.step_size, self.task.n_ori,
- (0, 0, 0))
- gtG, nodes, nodes_to_id = convert_to_graph_tool(G)
- self.task.gtG = gtG
- self.task.nodes = nodes
- self.task.delta_theta = 2.0*np.pi/(self.task.n_ori*1.)
- self.task.nodes_to_id = nodes_to_id
- logging.info('Building %s, #V=%d, #E=%d', self.building_name,
- self.task.nodes.shape[0], self.task.gtG.num_edges())
-
- if self.logdir is not None:
- write_traversible = cv2.applyColorMap(self.traversible.astype(np.uint8)*255, cv2.COLORMAP_JET)
- img_path = os.path.join(self.logdir,
- '{:s}_{:d}_graph.png'.format(self.building_name,
- seed))
- node_xyt = self.to_actual_xyt_vec(self.task.nodes)
- plt.set_cmap('jet');
- fig, ax = utils.subplot(plt, (1,1), (12,12))
- ax.plot(node_xyt[:,0], node_xyt[:,1], 'm.')
- ax.imshow(self.traversible, origin='lower');
- ax.set_axis_off(); ax.axis('equal');
- ax.set_title('{:s}, {:d}, {:d}'.format(self.building_name,
- self.task.nodes.shape[0],
- self.task.gtG.num_edges()))
- if self.room_dims is not None:
- for i, r in enumerate(self.room_dims['dims']*1):
- min_ = r[:3]*1
- max_ = r[3:]*1
- xmin, ymin, zmin = min_
- xmax, ymax, zmax = max_
-
- ax.plot([xmin, xmax, xmax, xmin, xmin],
- [ymin, ymin, ymax, ymax, ymin], 'g')
- with fu.fopen(img_path, 'w') as f:
- fig.savefig(f, bbox_inches='tight', transparent=True, pad_inches=0)
- plt.close(fig)
-
-
- def _gen_rng(self, rng):
- # instances is a list of list of node_ids.
- if self.task_params.move_type == 'circle':
- _, _, _, _, paths = rng_target_dist_field(self.task_params.batch_size,
- self.task.gtG, rng, 0, 1,
- compute_path=True)
- instances_ = paths
-
- instances = []
- for instance_ in instances_:
- instance = instance_
- for i in range(self.task_params.num_steps):
- instance.append(self.take_action([instance[-1]], [1])[0])
- instances.append(instance)
-
- elif self.task_params.move_type == 'shortest_path':
- _, _, _, _, paths = rng_target_dist_field(self.task_params.batch_size,
- self.task.gtG, rng,
- self.task_params.num_steps,
- self.task_params.num_steps+1,
- compute_path=True)
- instances = paths
-
- elif self.task_params.move_type == 'circle+forward':
- _, _, _, _, paths = rng_target_dist_field(self.task_params.batch_size,
- self.task.gtG, rng, 0, 1,
- compute_path=True)
- instances_ = paths
- instances = []
- for instance_ in instances_:
- instance = instance_
- for i in range(self.task_params.n_ori-1):
- instance.append(self.take_action([instance[-1]], [1])[0])
- while len(instance) <= self.task_params.num_steps:
- while self.take_action([instance[-1]], [3])[0] == instance[-1] and len(instance) <= self.task_params.num_steps:
- instance.append(self.take_action([instance[-1]], [2])[0])
- if len(instance) <= self.task_params.num_steps:
- instance.append(self.take_action([instance[-1]], [3])[0])
- instances.append(instance)
-
- # Do random perturbation if needed.
- perturbs = _gen_perturbs(rng, self.task_params.batch_size,
- self.task_params.num_steps,
- self.task_params.data_augment.lr_flip,
- self.task_params.data_augment.delta_angle,
- self.task_params.data_augment.delta_xy,
- self.task_params.data_augment.structured)
- return instances, perturbs
-
- def worker(self, instances, perturbs):
- # Output the images and the free space.
-
- # Make the instances be all the same length.
- for i in range(len(instances)):
- for j in range(self.task_params.num_steps - len(instances[i]) + 1):
- instances[i].append(instances[i][-1])
- if perturbs[i].shape[0] < self.task_params.num_steps+1:
- p = np.zeros((self.task_params.num_steps+1, 4))
- p[:perturbs[i].shape[0], :] = perturbs[i]
- p[perturbs[i].shape[0]:, :] = perturbs[i][-1,:]
- perturbs[i] = p
-
- instances_ = []
- for instance in instances:
- instances_ = instances_ + instance
- perturbs_ = np.concatenate(perturbs, axis=0)
-
- instances_nodes = self.task.nodes[instances_,:]
- instances_nodes = [tuple(x) for x in instances_nodes]
-
- imgs_ = self.render_nodes(instances_nodes, perturbs_)
- imgs = []; next = 0;
- for instance in instances:
- img_i = []
- for _ in instance:
- img_i.append(imgs_[next])
- next = next+1
- imgs.append(img_i)
- imgs = np.array(imgs)
-
- # Render out the maps in the egocentric view for all nodes and not just the
- # last node.
- all_nodes = []
- for x in instances:
- all_nodes = all_nodes + x
- all_perturbs = np.concatenate(perturbs, axis=0)
- loc, x_axis, y_axis, theta = self.get_loc_axis(
- self.task.nodes[all_nodes, :]*1, delta_theta=self.task.delta_theta,
- perturb=all_perturbs)
- fss = None
- valids = None
- loc_on_map = None
- theta_on_map = None
- cum_fs = None
- cum_valid = None
- incremental_locs = None
- incremental_thetas = None
-
- if self.task_params.output_free_space:
- fss, valids = get_map_to_predict(loc, x_axis, y_axis,
- map=self.traversible*1.,
- map_size=self.task_params.map_size)
- fss = np.array(fss) > 0.5
- fss = np.reshape(fss, [self.task_params.batch_size,
- self.task_params.num_steps+1,
- self.task_params.map_size,
- self.task_params.map_size])
- valids = np.reshape(np.array(valids), fss.shape)
-
- if self.task_params.output_transform_to_global_map:
- # Output the transform to the global map.
- loc_on_map = np.reshape(loc*1, [self.task_params.batch_size,
- self.task_params.num_steps+1, -1])
- # Converting to location wrt to first location so that warping happens
- # properly.
- theta_on_map = np.reshape(theta*1, [self.task_params.batch_size,
- self.task_params.num_steps+1, -1])
-
- if self.task_params.output_incremental_transform:
- # Output the transform to the global map.
- incremental_locs_ = np.reshape(loc*1, [self.task_params.batch_size,
- self.task_params.num_steps+1, -1])
- incremental_locs_[:,1:,:] -= incremental_locs_[:,:-1,:]
- t0 = -np.pi/2+np.reshape(theta*1, [self.task_params.batch_size,
- self.task_params.num_steps+1, -1])
- t = t0*1
- incremental_locs = incremental_locs_*1
- incremental_locs[:,:,0] = np.sum(incremental_locs_ * np.concatenate((np.cos(t), np.sin(t)), axis=-1), axis=-1)
- incremental_locs[:,:,1] = np.sum(incremental_locs_ * np.concatenate((np.cos(t+np.pi/2), np.sin(t+np.pi/2)), axis=-1), axis=-1)
- incremental_locs[:,0,:] = incremental_locs_[:,0,:]
- # print incremental_locs_[0,:,:], incremental_locs[0,:,:], t0[0,:,:]
-
- incremental_thetas = np.reshape(theta*1, [self.task_params.batch_size,
- self.task_params.num_steps+1,
- -1])
- incremental_thetas[:,1:,:] += -incremental_thetas[:,:-1,:]
-
- if self.task_params.output_canonical_map:
- loc_ = loc[0::(self.task_params.num_steps+1), :]
- x_axis = np.zeros_like(loc_); x_axis[:,1] = 1
- y_axis = np.zeros_like(loc_); y_axis[:,0] = -1
- cum_fs, cum_valid = get_map_to_predict(loc_, x_axis, y_axis,
- map=self.traversible*1.,
- map_size=self.task_params.map_size)
- cum_fs = np.array(cum_fs) > 0.5
- cum_fs = np.reshape(cum_fs, [self.task_params.batch_size, 1,
- self.task_params.map_size,
- self.task_params.map_size])
- cum_valid = np.reshape(np.array(cum_valid), cum_fs.shape)
-
-
- inputs = {'fs_maps': fss,
- 'valid_maps': valids,
- 'imgs': imgs,
- 'loc_on_map': loc_on_map,
- 'theta_on_map': theta_on_map,
- 'cum_fs_maps': cum_fs,
- 'cum_valid_maps': cum_valid,
- 'incremental_thetas': incremental_thetas,
- 'incremental_locs': incremental_locs}
- return inputs
-
- def pre(self, inputs):
- inputs['imgs'] = image_pre(inputs['imgs'], self.task_params.modalities)
- if inputs['loc_on_map'] is not None:
- inputs['loc_on_map'] = inputs['loc_on_map'] - inputs['loc_on_map'][:,[0],:]
- if inputs['theta_on_map'] is not None:
- inputs['theta_on_map'] = np.pi/2. - inputs['theta_on_map']
- return inputs
-
-def _nav_env_reset_helper(type, rng, nodes, batch_size, gtG, max_dist,
- num_steps, num_goals, data_augment, **kwargs):
- """Generates and returns a new episode."""
- max_compute = max_dist + 4*num_steps
- if type == 'general':
- start_node_ids, end_node_ids, dist, pred_map, paths = \
- rng_target_dist_field(batch_size, gtG, rng, max_dist, max_compute,
- nodes=nodes, compute_path=False)
- target_class = None
-
- elif type == 'room_to_room_many':
- goal_node_ids = []; dists = [];
- node_room_ids = kwargs['node_room_ids']
- # Sample the first one
- start_node_ids_, end_node_ids_, dist_, _, _ = rng_room_to_room(
- batch_size, gtG, rng, max_dist, max_compute,
- node_room_ids=node_room_ids, nodes=nodes)
- start_node_ids = start_node_ids_
- goal_node_ids.append(end_node_ids_)
- dists.append(dist_)
- for n in range(num_goals-1):
- start_node_ids_, end_node_ids_, dist_, _, _ = rng_next_goal(
- goal_node_ids[n], batch_size, gtG, rng, max_dist,
- max_compute, node_room_ids=node_room_ids, nodes=nodes,
- dists_from_start_node=dists[n])
- goal_node_ids.append(end_node_ids_)
- dists.append(dist_)
- target_class = None
-
- elif type == 'rng_rejection_sampling_many':
- num_goals = num_goals
- goal_node_ids = []; dists = [];
-
- n_ori = kwargs['n_ori']
- step_size = kwargs['step_size']
- min_dist = kwargs['min_dist']
- sampling_distribution = kwargs['sampling_distribution']
- target_distribution = kwargs['target_distribution']
- rejection_sampling_M = kwargs['rejection_sampling_M']
- distribution_bins = kwargs['distribution_bins']
-
- for n in range(num_goals):
- if n == 0: input_nodes = None
- else: input_nodes = goal_node_ids[n-1]
- start_node_ids_, end_node_ids_, dist_, _, _, _, _ = rng_next_goal_rejection_sampling(
- input_nodes, batch_size, gtG, rng, max_dist, min_dist,
- max_compute, sampling_distribution, target_distribution, nodes,
- n_ori, step_size, distribution_bins, rejection_sampling_M)
- if n == 0: start_node_ids = start_node_ids_
- goal_node_ids.append(end_node_ids_)
- dists.append(dist_)
- target_class = None
-
- elif type == 'room_to_room_back':
- num_goals = num_goals
- assert(num_goals == 2), 'num_goals must be 2.'
- goal_node_ids = []; dists = [];
- node_room_ids = kwargs['node_room_ids']
- # Sample the first one.
- start_node_ids_, end_node_ids_, dist_, _, _ = rng_room_to_room(
- batch_size, gtG, rng, max_dist, max_compute,
- node_room_ids=node_room_ids, nodes=nodes)
- start_node_ids = start_node_ids_
- goal_node_ids.append(end_node_ids_)
- dists.append(dist_)
-
- # Set second goal to be starting position, and compute distance to the start node.
- goal_node_ids.append(start_node_ids)
- dist = []
- for i in range(batch_size):
- dist_ = gt.topology.shortest_distance(
- gt.GraphView(gtG, reversed=True),
- source=gtG.vertex(start_node_ids[i]), target=None)
- dist_ = np.array(dist_.get_array())
- dist.append(dist_)
- dists.append(dist)
- target_class = None
-
- elif type[:14] == 'to_nearest_obj':
- # Generate an episode by sampling one of the target classes (with
- # probability proportional to the number of nodes in the world).
- # With the sampled class sample a node that is within some distance from
- # the sampled class.
- class_nodes = kwargs['class_nodes']
- sampling = kwargs['sampling']
- dist_to_class = kwargs['dist_to_class']
-
- assert(num_goals == 1), 'Only supports a single goal.'
- ind = rng.choice(class_nodes.shape[0], size=batch_size)
- target_class = class_nodes[ind,1]
- start_node_ids = []; dists = []; goal_node_ids = [];
-
- for t in target_class:
- if sampling == 'uniform':
- max_dist = max_dist
- cnts = np.bincount(dist_to_class[t], minlength=max_dist+1)*1.
- cnts[max_dist+1:] = 0
- p_each = 1./ cnts / (max_dist+1.)
- p_each[cnts == 0] = 0
- p = p_each[dist_to_class[t]]*1.; p = p/np.sum(p)
- start_node_id = rng.choice(p.shape[0], size=1, p=p)[0]
- else:
- logging.fatal('Sampling not one of uniform.')
- start_node_ids.append(start_node_id)
- dists.append(dist_to_class[t])
- # Dummy goal node, same as the start node, so that vis is better.
- goal_node_ids.append(start_node_id)
- dists = [dists]
- goal_node_ids = [goal_node_ids]
-
- return start_node_ids, goal_node_ids, dists, target_class
-
-
-class NavigationEnv(GridWorld, Building):
- """Wrapper around GridWorld which sets up navigation tasks.
- """
- def _debug_save_hardness(self, seed):
- out_path = os.path.join(self.logdir, '{:s}_{:d}_hardness.png'.format(self.building_name, seed))
- batch_size = 4000
- rng = np.random.RandomState(0)
- start_node_ids, end_node_ids, dists, pred_maps, paths, hardnesss, gt_dists = \
- rng_next_goal_rejection_sampling(
- None, batch_size, self.task.gtG, rng, self.task_params.max_dist,
- self.task_params.min_dist, self.task_params.max_dist,
- self.task.sampling_distribution, self.task.target_distribution,
- self.task.nodes, self.task_params.n_ori, self.task_params.step_size,
- self.task.distribution_bins, self.task.rejection_sampling_M)
- bins = self.task.distribution_bins
- n_bins = self.task.n_bins
- with plt.style.context('ggplot'):
- fig, axes = utils.subplot(plt, (1,2), (10,10))
- ax = axes[0]
- _ = ax.hist(hardnesss, bins=bins, weights=np.ones_like(hardnesss)/len(hardnesss))
- ax.plot(bins[:-1]+0.5/n_bins, self.task.target_distribution, 'g')
- ax.plot(bins[:-1]+0.5/n_bins, self.task.sampling_distribution, 'b')
- ax.grid('on')
-
- ax = axes[1]
- _ = ax.hist(gt_dists, bins=np.arange(self.task_params.max_dist+1))
- ax.grid('on')
- ax.set_title('Mean: {:0.2f}, Median: {:0.2f}'.format(np.mean(gt_dists),
- np.median(gt_dists)))
- with fu.fopen(out_path, 'w') as f:
- fig.savefig(f, bbox_inches='tight', transparent=True, pad_inches=0)
-
- def _debug_save_map_nodes(self, seed):
- """Saves traversible space along with nodes generated on the graph. Takes
- the seed as input."""
- img_path = os.path.join(self.logdir, '{:s}_{:d}_graph.png'.format(self.building_name, seed))
- node_xyt = self.to_actual_xyt_vec(self.task.nodes)
- plt.set_cmap('jet');
- fig, ax = utils.subplot(plt, (1,1), (12,12))
- ax.plot(node_xyt[:,0], node_xyt[:,1], 'm.')
- ax.set_axis_off(); ax.axis('equal');
-
- if self.room_dims is not None:
- for i, r in enumerate(self.room_dims['dims']*1):
- min_ = r[:3]*1
- max_ = r[3:]*1
- xmin, ymin, zmin = min_
- xmax, ymax, zmax = max_
-
- ax.plot([xmin, xmax, xmax, xmin, xmin],
- [ymin, ymin, ymax, ymax, ymin], 'g')
- ax.imshow(self.traversible, origin='lower');
- with fu.fopen(img_path, 'w') as f:
- fig.savefig(f, bbox_inches='tight', transparent=True, pad_inches=0)
-
- def _debug_semantic_maps(self, seed):
- """Saves traversible space along with nodes generated on the graph. Takes
- the seed as input."""
- for i, cls in enumerate(self.task_params.semantic_task.class_map_names):
- img_path = os.path.join(self.logdir, '{:s}_flip{:d}_{:s}_graph.png'.format(self.building_name, seed, cls))
- maps = self.traversible*1.
- maps += 0.5*(self.task.class_maps_dilated[:,:,i])
- write_traversible = (maps*1.+1.)/3.0
- write_traversible = (write_traversible*255.).astype(np.uint8)[:,:,np.newaxis]
- write_traversible = write_traversible + np.zeros((1,1,3), dtype=np.uint8)
- fu.write_image(img_path, write_traversible[::-1,:,:])
-
- def _preprocess_for_task(self, seed):
- """Sets up the task field for doing navigation on the grid world."""
- if self.task is None or self.task.seed != seed:
- rng = np.random.RandomState(seed)
- origin_loc = get_graph_origin_loc(rng, self.traversible)
- self.task = utils.Foo(seed=seed, origin_loc=origin_loc,
- n_ori=self.task_params.n_ori)
- G = generate_graph(self.valid_fn_vec, self.task_params.step_size,
- self.task.n_ori, (0, 0, 0))
- gtG, nodes, nodes_to_id = convert_to_graph_tool(G)
- self.task.gtG = gtG
- self.task.nodes = nodes
- self.task.delta_theta = 2.0*np.pi/(self.task.n_ori*1.)
- self.task.nodes_to_id = nodes_to_id
-
- logging.info('Building %s, #V=%d, #E=%d', self.building_name,
- self.task.nodes.shape[0], self.task.gtG.num_edges())
- type = self.task_params.type
- if type == 'general':
- # Do nothing
- _ = None
-
- elif type == 'room_to_room_many' or type == 'room_to_room_back':
- if type == 'room_to_room_back':
- assert(self.task_params.num_goals == 2), 'num_goals must be 2.'
-
- self.room_dims = _filter_rooms(self.room_dims, self.task_params.room_regex)
- xyt = self.to_actual_xyt_vec(self.task.nodes)
- self.task.node_room_ids = _label_nodes_with_room_id(xyt, self.room_dims)
- self.task.reset_kwargs = {'node_room_ids': self.task.node_room_ids}
-
- elif type == 'rng_rejection_sampling_many':
- n_bins = 20
- rejection_sampling_M = self.task_params.rejection_sampling_M
- min_dist = self.task_params.min_dist
- bins = np.arange(n_bins+1)/(n_bins*1.)
- target_d = np.zeros(n_bins); target_d[...] = 1./n_bins;
-
- sampling_d = get_hardness_distribution(
- self.task.gtG, self.task_params.max_dist, self.task_params.min_dist,
- np.random.RandomState(0), 4000, bins, self.task.nodes,
- self.task_params.n_ori, self.task_params.step_size)
-
- self.task.reset_kwargs = {'distribution_bins': bins,
- 'target_distribution': target_d,
- 'sampling_distribution': sampling_d,
- 'rejection_sampling_M': rejection_sampling_M,
- 'n_bins': n_bins,
- 'n_ori': self.task_params.n_ori,
- 'step_size': self.task_params.step_size,
- 'min_dist': self.task_params.min_dist}
- self.task.n_bins = n_bins
- self.task.distribution_bins = bins
- self.task.target_distribution = target_d
- self.task.sampling_distribution = sampling_d
- self.task.rejection_sampling_M = rejection_sampling_M
-
- if self.logdir is not None:
- self._debug_save_hardness(seed)
-
- elif type[:14] == 'to_nearest_obj':
- self.room_dims = _filter_rooms(self.room_dims, self.task_params.room_regex)
- xyt = self.to_actual_xyt_vec(self.task.nodes)
-
- self.class_maps = _select_classes(self.class_maps,
- self.class_map_names,
- self.task_params.semantic_task.class_map_names)*1
- self.class_map_names = self.task_params.semantic_task.class_map_names
- nodes_xyt = self.to_actual_xyt_vec(np.array(self.task.nodes))
-
- tt = utils.Timer(); tt.tic();
- if self.task_params.type == 'to_nearest_obj_acc':
- self.task.class_maps_dilated, self.task.node_class_label = label_nodes_with_class_geodesic(
- nodes_xyt, self.class_maps,
- self.task_params.semantic_task.pix_distance+8, self.map.traversible,
- ff_cost=1., fo_cost=1., oo_cost=4., connectivity=8.)
-
- dists = []
- for i in range(len(self.class_map_names)):
- class_nodes_ = np.where(self.task.node_class_label[:,i])[0]
- dists.append(get_distance_node_list(gtG, source_nodes=class_nodes_, direction='to'))
- self.task.dist_to_class = dists
- a_, b_ = np.where(self.task.node_class_label)
- self.task.class_nodes = np.concatenate((a_[:,np.newaxis], b_[:,np.newaxis]), axis=1)
-
- if self.logdir is not None:
- self._debug_semantic_maps(seed)
-
- self.task.reset_kwargs = {'sampling': self.task_params.semantic_task.sampling,
- 'class_nodes': self.task.class_nodes,
- 'dist_to_class': self.task.dist_to_class}
-
- if self.logdir is not None:
- self._debug_save_map_nodes(seed)
-
- def reset(self, rngs):
- rng = rngs[0]; rng_perturb = rngs[1];
- nodes = self.task.nodes
- tp = self.task_params
-
- start_node_ids, goal_node_ids, dists, target_class = \
- _nav_env_reset_helper(tp.type, rng, self.task.nodes, tp.batch_size,
- self.task.gtG, tp.max_dist, tp.num_steps,
- tp.num_goals, tp.data_augment,
- **(self.task.reset_kwargs))
-
- start_nodes = [tuple(nodes[_,:]) for _ in start_node_ids]
- goal_nodes = [[tuple(nodes[_,:]) for _ in __] for __ in goal_node_ids]
- data_augment = tp.data_augment
- perturbs = _gen_perturbs(rng_perturb, tp.batch_size,
- (tp.num_steps+1)*tp.num_goals,
- data_augment.lr_flip, data_augment.delta_angle,
- data_augment.delta_xy, data_augment.structured)
- perturbs = np.array(perturbs) # batch x steps x 4
- end_perturbs = perturbs[:,-(tp.num_goals):,:]*1 # fixed perturb for the goal.
- perturbs = perturbs[:,:-(tp.num_goals),:]*1
-
- history = -np.ones((tp.batch_size, tp.num_steps*tp.num_goals), dtype=np.int32)
- self.episode = utils.Foo(
- start_nodes=start_nodes, start_node_ids=start_node_ids,
- goal_nodes=goal_nodes, goal_node_ids=goal_node_ids, dist_to_goal=dists,
- perturbs=perturbs, goal_perturbs=end_perturbs, history=history,
- target_class=target_class, history_frames=[])
- return start_node_ids
-
- def take_action(self, current_node_ids, action, step_number):
- """In addition to returning the action, also returns the reward that the
- agent receives."""
- goal_number = step_number / self.task_params.num_steps
- new_node_ids = GridWorld.take_action(self, current_node_ids, action)
- rewards = []
- for i, n in enumerate(new_node_ids):
- reward = 0
- if n == self.episode.goal_node_ids[goal_number][i]:
- reward = self.task_params.reward_at_goal
- reward = reward - self.task_params.reward_time_penalty
- rewards.append(reward)
- return new_node_ids, rewards
-
-
- def get_optimal_action(self, current_node_ids, step_number):
- """Returns the optimal action from the current node."""
- goal_number = step_number / self.task_params.num_steps
- gtG = self.task.gtG
- a = np.zeros((len(current_node_ids), self.task_params.num_actions), dtype=np.int32)
- d_dict = self.episode.dist_to_goal[goal_number]
- for i, c in enumerate(current_node_ids):
- neigh = gtG.vertex(c).out_neighbours()
- neigh_edge = gtG.vertex(c).out_edges()
- ds = np.array([d_dict[i][int(x)] for x in neigh])
- ds_min = np.min(ds)
- for i_, e in enumerate(neigh_edge):
- if ds[i_] == ds_min:
- _ = gtG.ep['action'][e]
- a[i, _] = 1
- return a
-
- def get_targets(self, current_node_ids, step_number):
- """Returns the target actions from the current node."""
- action = self.get_optimal_action(current_node_ids, step_number)
- action = np.expand_dims(action, axis=1)
- return vars(utils.Foo(action=action))
-
- def get_targets_name(self):
- """Returns the list of names of the targets."""
- return ['action']
-
- def cleanup(self):
- self.episode = None
-
-class VisualNavigationEnv(NavigationEnv):
- """Class for doing visual navigation in environments. Functions for computing
- features on states, etc.
- """
- def __init__(self, robot, env, task_params, category_list=None,
- building_name=None, flip=False, logdir=None,
- building_loader=None, r_obj=None):
- tt = utils.Timer()
- tt.tic()
- Building.__init__(self, building_name, robot, env, category_list,
- small=task_params.toy_problem, flip=flip, logdir=logdir,
- building_loader=building_loader)
-
- self.set_r_obj(r_obj)
- self.task_params = task_params
- self.task = None
- self.episode = None
- self._preprocess_for_task(self.task_params.building_seed)
- if hasattr(self.task_params, 'map_scales'):
- self.task.scaled_maps = resize_maps(
- self.traversible.astype(np.float32)*1, self.task_params.map_scales,
- self.task_params.map_resize_method)
- else:
- logging.fatal('VisualNavigationEnv does not support scale_f anymore.')
- self.task.readout_maps_scaled = resize_maps(
- self.traversible.astype(np.float32)*1,
- self.task_params.readout_maps_scales,
- self.task_params.map_resize_method)
- tt.toc(log_at=1, log_str='VisualNavigationEnv __init__: ')
-
- def get_weight(self):
- return self.task.nodes.shape[0]
-
- def get_common_data(self):
- goal_nodes = self.episode.goal_nodes
- start_nodes = self.episode.start_nodes
- perturbs = self.episode.perturbs
- goal_perturbs = self.episode.goal_perturbs
- target_class = self.episode.target_class
-
- goal_locs = []; rel_goal_locs = [];
- for i in range(len(goal_nodes)):
- end_nodes = goal_nodes[i]
- goal_loc, _, _, goal_theta = self.get_loc_axis(
- np.array(end_nodes), delta_theta=self.task.delta_theta,
- perturb=goal_perturbs[:,i,:])
-
- # Compute the relative location to all goals from the starting location.
- loc, _, _, theta = self.get_loc_axis(np.array(start_nodes),
- delta_theta=self.task.delta_theta,
- perturb=perturbs[:,0,:])
- r_goal, t_goal = _get_relative_goal_loc(goal_loc*1., loc, theta)
- rel_goal_loc = np.concatenate((r_goal*np.cos(t_goal), r_goal*np.sin(t_goal),
- np.cos(goal_theta-theta),
- np.sin(goal_theta-theta)), axis=1)
- rel_goal_locs.append(np.expand_dims(rel_goal_loc, axis=1))
- goal_locs.append(np.expand_dims(goal_loc, axis=1))
-
- map = self.traversible*1.
- maps = np.repeat(np.expand_dims(np.expand_dims(map, axis=0), axis=0),
- self.task_params.batch_size, axis=0)*1
- if self.task_params.type[:14] == 'to_nearest_obj':
- for i in range(self.task_params.batch_size):
- maps[i,0,:,:] += 0.5*(self.task.class_maps_dilated[:,:,target_class[i]])
-
- rel_goal_locs = np.concatenate(rel_goal_locs, axis=1)
- goal_locs = np.concatenate(goal_locs, axis=1)
- maps = np.expand_dims(maps, axis=-1)
-
- if self.task_params.type[:14] == 'to_nearest_obj':
- rel_goal_locs = np.zeros((self.task_params.batch_size, 1,
- len(self.task_params.semantic_task.class_map_names)),
- dtype=np.float32)
- goal_locs = np.zeros((self.task_params.batch_size, 1, 2),
- dtype=np.float32)
- for i in range(self.task_params.batch_size):
- t = target_class[i]
- rel_goal_locs[i,0,t] = 1.
- goal_locs[i,0,0] = t
- goal_locs[i,0,1] = np.NaN
-
- return vars(utils.Foo(orig_maps=maps, goal_loc=goal_locs,
- rel_goal_loc_at_start=rel_goal_locs))
-
- def pre_common_data(self, inputs):
- return inputs
-
-
- def get_features(self, current_node_ids, step_number):
- task_params = self.task_params
- goal_number = step_number / self.task_params.num_steps
- end_nodes = self.task.nodes[self.episode.goal_node_ids[goal_number],:]*1
- current_nodes = self.task.nodes[current_node_ids,:]*1
- end_perturbs = self.episode.goal_perturbs[:,goal_number,:][:,np.newaxis,:]
- perturbs = self.episode.perturbs
- target_class = self.episode.target_class
-
- # Append to history.
- self.episode.history[:,step_number] = np.array(current_node_ids)
-
- # Render out the images from current node.
- outs = {}
-
- if self.task_params.outputs.images:
- imgs_all = []
- imgs = self.render_nodes([tuple(x) for x in current_nodes],
- perturb=perturbs[:,step_number,:])
- imgs_all.append(imgs)
- aux_delta_thetas = self.task_params.aux_delta_thetas
- for i in range(len(aux_delta_thetas)):
- imgs = self.render_nodes([tuple(x) for x in current_nodes],
- perturb=perturbs[:,step_number,:],
- aux_delta_theta=aux_delta_thetas[i])
- imgs_all.append(imgs)
- imgs_all = np.array(imgs_all) # A x B x H x W x C
- imgs_all = np.transpose(imgs_all, axes=[1,0,2,3,4])
- imgs_all = np.expand_dims(imgs_all, axis=1) # B x N x A x H x W x C
- if task_params.num_history_frames > 0:
- if step_number == 0:
- # Append the same frame 4 times
- for i in range(task_params.num_history_frames+1):
- self.episode.history_frames.insert(0, imgs_all*1.)
- self.episode.history_frames.insert(0, imgs_all)
- self.episode.history_frames.pop()
- imgs_all_with_history = np.concatenate(self.episode.history_frames, axis=2)
- else:
- imgs_all_with_history = imgs_all
- outs['imgs'] = imgs_all_with_history # B x N x A x H x W x C
-
- if self.task_params.outputs.node_ids:
- outs['node_ids'] = np.array(current_node_ids).reshape((-1,1,1))
- outs['perturbs'] = np.expand_dims(perturbs[:,step_number, :]*1., axis=1)
-
- if self.task_params.outputs.analytical_counts:
- assert(self.task_params.modalities == ['depth'])
- d = image_pre(outs['imgs']*1., self.task_params.modalities)
- cm = get_camera_matrix(self.task_params.img_width,
- self.task_params.img_height,
- self.task_params.img_fov)
- XYZ = get_point_cloud_from_z(100./d[...,0], cm)
- XYZ = make_geocentric(XYZ*100., self.robot.sensor_height,
- self.robot.camera_elevation_degree)
- for i in range(len(self.task_params.analytical_counts.map_sizes)):
- non_linearity = self.task_params.analytical_counts.non_linearity[i]
- count, isvalid = bin_points(XYZ*1.,
- map_size=self.task_params.analytical_counts.map_sizes[i],
- xy_resolution=self.task_params.analytical_counts.xy_resolution[i],
- z_bins=self.task_params.analytical_counts.z_bins[i])
- assert(count.shape[2] == 1), 'only works for n_views equal to 1.'
- count = count[:,:,0,:,:,:]
- isvalid = isvalid[:,:,0,:,:,:]
- if non_linearity == 'none':
- None
- elif non_linearity == 'min10':
- count = np.minimum(count, 10.)
- elif non_linearity == 'sqrt':
- count = np.sqrt(count)
- else:
- logging.fatal('Undefined non_linearity.')
- outs['analytical_counts_{:d}'.format(i)] = count
-
- # Compute the goal location in the cordinate frame of the robot.
- if self.task_params.outputs.rel_goal_loc:
- if self.task_params.type[:14] != 'to_nearest_obj':
- loc, _, _, theta = self.get_loc_axis(current_nodes,
- delta_theta=self.task.delta_theta,
- perturb=perturbs[:,step_number,:])
- goal_loc, _, _, goal_theta = self.get_loc_axis(end_nodes,
- delta_theta=self.task.delta_theta,
- perturb=end_perturbs[:,0,:])
- r_goal, t_goal = _get_relative_goal_loc(goal_loc, loc, theta)
-
- rel_goal_loc = np.concatenate((r_goal*np.cos(t_goal), r_goal*np.sin(t_goal),
- np.cos(goal_theta-theta),
- np.sin(goal_theta-theta)), axis=1)
- outs['rel_goal_loc'] = np.expand_dims(rel_goal_loc, axis=1)
- elif self.task_params.type[:14] == 'to_nearest_obj':
- rel_goal_loc = np.zeros((self.task_params.batch_size, 1,
- len(self.task_params.semantic_task.class_map_names)),
- dtype=np.float32)
- for i in range(self.task_params.batch_size):
- t = target_class[i]
- rel_goal_loc[i,0,t] = 1.
- outs['rel_goal_loc'] = rel_goal_loc
-
- # Location on map to plot the trajectory during validation.
- if self.task_params.outputs.loc_on_map:
- loc, x_axis, y_axis, theta = self.get_loc_axis(current_nodes,
- delta_theta=self.task.delta_theta,
- perturb=perturbs[:,step_number,:])
- outs['loc_on_map'] = np.expand_dims(loc, axis=1)
-
- # Compute gt_dist to goal
- if self.task_params.outputs.gt_dist_to_goal:
- gt_dist_to_goal = np.zeros((len(current_node_ids), 1), dtype=np.float32)
- for i, n in enumerate(current_node_ids):
- gt_dist_to_goal[i,0] = self.episode.dist_to_goal[goal_number][i][n]
- outs['gt_dist_to_goal'] = np.expand_dims(gt_dist_to_goal, axis=1)
-
- # Free space in front of you, map and goal as images.
- if self.task_params.outputs.ego_maps:
- loc, x_axis, y_axis, theta = self.get_loc_axis(current_nodes,
- delta_theta=self.task.delta_theta,
- perturb=perturbs[:,step_number,:])
- maps = generate_egocentric_maps(self.task.scaled_maps,
- self.task_params.map_scales,
- self.task_params.map_crop_sizes, loc,
- x_axis, y_axis, theta)
-
- for i in range(len(self.task_params.map_scales)):
- outs['ego_maps_{:d}'.format(i)] = \
- np.expand_dims(np.expand_dims(maps[i], axis=1), axis=-1)
-
- if self.task_params.outputs.readout_maps:
- loc, x_axis, y_axis, theta = self.get_loc_axis(current_nodes,
- delta_theta=self.task.delta_theta,
- perturb=perturbs[:,step_number,:])
- maps = generate_egocentric_maps(self.task.readout_maps_scaled,
- self.task_params.readout_maps_scales,
- self.task_params.readout_maps_crop_sizes,
- loc, x_axis, y_axis, theta)
- for i in range(len(self.task_params.readout_maps_scales)):
- outs['readout_maps_{:d}'.format(i)] = \
- np.expand_dims(np.expand_dims(maps[i], axis=1), axis=-1)
-
- # Images for the goal.
- if self.task_params.outputs.ego_goal_imgs:
- if self.task_params.type[:14] != 'to_nearest_obj':
- loc, x_axis, y_axis, theta = self.get_loc_axis(current_nodes,
- delta_theta=self.task.delta_theta,
- perturb=perturbs[:,step_number,:])
- goal_loc, _, _, _ = self.get_loc_axis(end_nodes,
- delta_theta=self.task.delta_theta,
- perturb=end_perturbs[:,0,:])
- rel_goal_orientation = np.mod(
- np.int32(current_nodes[:,2:] - end_nodes[:,2:]), self.task_params.n_ori)
- goal_dist, goal_theta = _get_relative_goal_loc(goal_loc, loc, theta)
- goals = generate_goal_images(self.task_params.map_scales,
- self.task_params.map_crop_sizes,
- self.task_params.n_ori, goal_dist,
- goal_theta, rel_goal_orientation)
- for i in range(len(self.task_params.map_scales)):
- outs['ego_goal_imgs_{:d}'.format(i)] = np.expand_dims(goals[i], axis=1)
-
- elif self.task_params.type[:14] == 'to_nearest_obj':
- for i in range(len(self.task_params.map_scales)):
- num_classes = len(self.task_params.semantic_task.class_map_names)
- outs['ego_goal_imgs_{:d}'.format(i)] = np.zeros((self.task_params.batch_size, 1,
- self.task_params.map_crop_sizes[i],
- self.task_params.map_crop_sizes[i],
- self.task_params.goal_channels))
- for i in range(self.task_params.batch_size):
- t = target_class[i]
- for j in range(len(self.task_params.map_scales)):
- outs['ego_goal_imgs_{:d}'.format(j)][i,:,:,:,t] = 1.
-
- # Incremental locs and theta (for map warping), always in the original scale
- # of the map, the subequent steps in the tf code scale appropriately.
- # Scaling is done by just multiplying incremental_locs appropriately.
- if self.task_params.outputs.egomotion:
- if step_number == 0:
- # Zero Ego Motion
- incremental_locs = np.zeros((self.task_params.batch_size, 1, 2), dtype=np.float32)
- incremental_thetas = np.zeros((self.task_params.batch_size, 1, 1), dtype=np.float32)
- else:
- previous_nodes = self.task.nodes[self.episode.history[:,step_number-1], :]*1
- loc, _, _, theta = self.get_loc_axis(current_nodes,
- delta_theta=self.task.delta_theta,
- perturb=perturbs[:,step_number,:])
- previous_loc, _, _, previous_theta = self.get_loc_axis(
- previous_nodes, delta_theta=self.task.delta_theta,
- perturb=perturbs[:,step_number-1,:])
-
- incremental_locs_ = np.reshape(loc-previous_loc, [self.task_params.batch_size, 1, -1])
-
- t = -np.pi/2+np.reshape(theta*1, [self.task_params.batch_size, 1, -1])
- incremental_locs = incremental_locs_*1
- incremental_locs[:,:,0] = np.sum(incremental_locs_ *
- np.concatenate((np.cos(t), np.sin(t)),
- axis=-1), axis=-1)
- incremental_locs[:,:,1] = np.sum(incremental_locs_ *
- np.concatenate((np.cos(t+np.pi/2),
- np.sin(t+np.pi/2)),
- axis=-1), axis=-1)
- incremental_thetas = np.reshape(theta-previous_theta,
- [self.task_params.batch_size, 1, -1])
- outs['incremental_locs'] = incremental_locs
- outs['incremental_thetas'] = incremental_thetas
-
- if self.task_params.outputs.visit_count:
- # Output the visit count for this state, how many times has the current
- # state been visited, and how far in the history was the last visit
- # (except this one)
- visit_count = np.zeros((self.task_params.batch_size, 1), dtype=np.int32)
- last_visit = -np.ones((self.task_params.batch_size, 1), dtype=np.int32)
- if step_number >= 1:
- h = self.episode.history[:,:(step_number)]
- visit_count[:,0] = np.sum(h == np.array(current_node_ids).reshape([-1,1]),
- axis=1)
- last_visit[:,0] = np.argmax(h[:,::-1] == np.array(current_node_ids).reshape([-1,1]),
- axis=1) + 1
- last_visit[visit_count == 0] = -1 # -1 if not visited.
- outs['visit_count'] = np.expand_dims(visit_count, axis=1)
- outs['last_visit'] = np.expand_dims(last_visit, axis=1)
- return outs
-
- def get_features_name(self):
- f = []
- if self.task_params.outputs.images:
- f.append('imgs')
- if self.task_params.outputs.rel_goal_loc:
- f.append('rel_goal_loc')
- if self.task_params.outputs.loc_on_map:
- f.append('loc_on_map')
- if self.task_params.outputs.gt_dist_to_goal:
- f.append('gt_dist_to_goal')
- if self.task_params.outputs.ego_maps:
- for i in range(len(self.task_params.map_scales)):
- f.append('ego_maps_{:d}'.format(i))
- if self.task_params.outputs.readout_maps:
- for i in range(len(self.task_params.readout_maps_scales)):
- f.append('readout_maps_{:d}'.format(i))
- if self.task_params.outputs.ego_goal_imgs:
- for i in range(len(self.task_params.map_scales)):
- f.append('ego_goal_imgs_{:d}'.format(i))
- if self.task_params.outputs.egomotion:
- f.append('incremental_locs')
- f.append('incremental_thetas')
- if self.task_params.outputs.visit_count:
- f.append('visit_count')
- f.append('last_visit')
- if self.task_params.outputs.analytical_counts:
- for i in range(len(self.task_params.analytical_counts.map_sizes)):
- f.append('analytical_counts_{:d}'.format(i))
- if self.task_params.outputs.node_ids:
- f.append('node_ids')
- f.append('perturbs')
- return f
-
- def pre_features(self, inputs):
- if self.task_params.outputs.images:
- inputs['imgs'] = image_pre(inputs['imgs'], self.task_params.modalities)
- return inputs
-
-class BuildingMultiplexer():
- def __init__(self, args, task_number):
- params = vars(args)
- for k in params.keys():
- setattr(self, k, params[k])
- self.task_number = task_number
- self._pick_data(task_number)
- logging.info('Env Class: %s.', self.env_class)
- if self.task_params.task == 'planning':
- self._setup_planner()
- elif self.task_params.task == 'mapping':
- self._setup_mapper()
- elif self.task_params.task == 'map+plan':
- self._setup_mapper()
- else:
- logging.error('Undefined task: %s'.format(self.task_params.task))
-
- def _pick_data(self, task_number):
- logging.error('Input Building Names: %s', self.building_names)
- self.flip = [np.mod(task_number / len(self.building_names), 2) == 1]
- id = np.mod(task_number, len(self.building_names))
- self.building_names = [self.building_names[id]]
- self.task_params.building_seed = task_number
- logging.error('BuildingMultiplexer: Picked Building Name: %s', self.building_names)
- self.building_names = self.building_names[0].split('+')
- self.flip = [self.flip[0] for _ in self.building_names]
- logging.error('BuildingMultiplexer: Picked Building Name: %s', self.building_names)
- logging.error('BuildingMultiplexer: Flipping Buildings: %s', self.flip)
- logging.error('BuildingMultiplexer: Set building_seed: %d', self.task_params.building_seed)
- self.num_buildings = len(self.building_names)
- logging.error('BuildingMultiplexer: Num buildings: %d', self.num_buildings)
-
- def _setup_planner(self):
- # Load building env class.
- self.buildings = []
- for i, building_name in enumerate(self.building_names):
- b = self.env_class(robot=self.robot, env=self.env,
- task_params=self.task_params,
- building_name=building_name, flip=self.flip[i],
- logdir=self.logdir, building_loader=self.dataset)
- self.buildings.append(b)
-
- def _setup_mapper(self):
- # Set up the renderer.
- cp = self.camera_param
- rgb_shader, d_shader = sru.get_shaders(cp.modalities)
- r_obj = SwiftshaderRenderer()
- r_obj.init_display(width=cp.width, height=cp.height, fov=cp.fov,
- z_near=cp.z_near, z_far=cp.z_far, rgb_shader=rgb_shader,
- d_shader=d_shader)
- self.r_obj = r_obj
- r_obj.clear_scene()
-
- # Load building env class.
- self.buildings = []
- wt = []
- for i, building_name in enumerate(self.building_names):
- b = self.env_class(robot=self.robot, env=self.env,
- task_params=self.task_params,
- building_name=building_name, flip=self.flip[i],
- logdir=self.logdir, building_loader=self.dataset,
- r_obj=r_obj)
- wt.append(b.get_weight())
- b.load_building_into_scene()
- b.set_building_visibility(False)
- self.buildings.append(b)
- wt = np.array(wt).astype(np.float32)
- wt = wt / np.sum(wt+0.0001)
- self.building_sampling_weights = wt
-
- def sample_building(self, rng):
- if self.num_buildings == 1:
- building_id = rng.choice(range(len(self.building_names)))
- else:
- building_id = rng.choice(self.num_buildings,
- p=self.building_sampling_weights)
- b = self.buildings[building_id]
- instances = b._gen_rng(rng)
- self._building_id = building_id
- return self.buildings[building_id], instances
-
- def sample_env(self, rngs):
- rng = rngs[0];
- if self.num_buildings == 1:
- building_id = rng.choice(range(len(self.building_names)))
- else:
- building_id = rng.choice(self.num_buildings,
- p=self.building_sampling_weights)
- return self.buildings[building_id]
-
- def pre(self, inputs):
- return self.buildings[self._building_id].pre(inputs)
-
- def __del__(self):
- self.r_obj.clear_scene()
- logging.error('Clearing scene.')
diff --git a/research/cognitive_mapping_and_planning/datasets/nav_env_config.py b/research/cognitive_mapping_and_planning/datasets/nav_env_config.py
deleted file mode 100644
index 3d71c5767c4dc0ed9f05cce5c1790f11ede3778a..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/datasets/nav_env_config.py
+++ /dev/null
@@ -1,127 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Configs for stanford navigation environment.
-
-Base config for stanford navigation enviornment.
-"""
-import numpy as np
-import src.utils as utils
-import datasets.nav_env as nav_env
-
-def nav_env_base_config():
- """Returns the base config for stanford navigation environment.
-
- Returns:
- Base config for stanford navigation environment.
- """
- robot = utils.Foo(radius=15,
- base=10,
- height=140,
- sensor_height=120,
- camera_elevation_degree=-15)
-
- env = utils.Foo(padding=10,
- resolution=5,
- num_point_threshold=2,
- valid_min=-10,
- valid_max=200,
- n_samples_per_face=200)
-
- camera_param = utils.Foo(width=225,
- height=225,
- z_near=0.05,
- z_far=20.0,
- fov=60.,
- modalities=['rgb'],
- img_channels=3)
-
- data_augment = utils.Foo(lr_flip=0,
- delta_angle=0.5,
- delta_xy=4,
- relight=True,
- relight_fast=False,
- structured=False) # if True, uses the same perturb for the whole episode.
-
- outputs = utils.Foo(images=True,
- rel_goal_loc=False,
- loc_on_map=True,
- gt_dist_to_goal=True,
- ego_maps=False,
- ego_goal_imgs=False,
- egomotion=False,
- visit_count=False,
- analytical_counts=False,
- node_ids=True,
- readout_maps=False)
-
- # class_map_names=['board', 'chair', 'door', 'sofa', 'table']
- class_map_names = ['chair', 'door', 'table']
- semantic_task = utils.Foo(class_map_names=class_map_names, pix_distance=16,
- sampling='uniform')
-
- # time per iteration for cmp is 0.82 seconds per episode with 3.4s overhead per batch.
- task_params = utils.Foo(max_dist=32,
- step_size=8,
- num_steps=40,
- num_actions=4,
- batch_size=4,
- building_seed=0,
- num_goals=1,
- img_height=None,
- img_width=None,
- img_channels=None,
- modalities=None,
- outputs=outputs,
- map_scales=[1.],
- map_crop_sizes=[64],
- rel_goal_loc_dim=4,
- base_class='Building',
- task='map+plan',
- n_ori=4,
- type='room_to_room_many',
- data_augment=data_augment,
- room_regex='^((?!hallway).)*$',
- toy_problem=False,
- map_channels=1,
- gt_coverage=False,
- input_type='maps',
- full_information=False,
- aux_delta_thetas=[],
- semantic_task=semantic_task,
- num_history_frames=0,
- node_ids_dim=1,
- perturbs_dim=4,
- map_resize_method='linear_noantialiasing',
- readout_maps_channels=1,
- readout_maps_scales=[],
- readout_maps_crop_sizes=[],
- n_views=1,
- reward_time_penalty=0.1,
- reward_at_goal=1.,
- discount_factor=0.99,
- rejection_sampling_M=100,
- min_dist=None)
-
- navtask_args = utils.Foo(
- building_names=['area1_gates_wingA_floor1_westpart'],
- env_class=nav_env.VisualNavigationEnv,
- robot=robot,
- task_params=task_params,
- env=env,
- camera_param=camera_param,
- cache_rooms=True)
- return navtask_args
-
diff --git a/research/cognitive_mapping_and_planning/matplotlibrc b/research/cognitive_mapping_and_planning/matplotlibrc
deleted file mode 100644
index ed5097572ae68680d0c9afdf510968e1c3d175d4..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/matplotlibrc
+++ /dev/null
@@ -1 +0,0 @@
-backend : agg
diff --git a/research/cognitive_mapping_and_planning/output/.gitignore b/research/cognitive_mapping_and_planning/output/.gitignore
deleted file mode 100644
index a767cafbbd864d0baf76530294598e4c2be60a24..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/output/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*
diff --git a/research/cognitive_mapping_and_planning/output/README.md b/research/cognitive_mapping_and_planning/output/README.md
deleted file mode 100644
index 7518c3874390da7e2aa65a89ccdec035ca7610e8..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/output/README.md
+++ /dev/null
@@ -1,16 +0,0 @@
-### Pre-Trained Models
-
-We provide the following pre-trained models:
-
-Config Name | Checkpoint | Mean Dist. | 50%ile Dist. | 75%ile Dist. | Success %age |
-:-: | :-: | :-: | :-: | :-: | :-: |
-cmp.lmap_Msc.clip5.sbpd_d_r2r | [ckpt](http://download.tensorflow.org/models/cognitive_mapping_and_planning/2017_04_16/cmp.lmap_Msc.clip5.sbpd_d_r2r.tar) | 4.79 | 0 | 1 | 78.9 |
-cmp.lmap_Msc.clip5.sbpd_rgb_r2r | [ckpt](http://download.tensorflow.org/models/cognitive_mapping_and_planning/2017_04_16/cmp.lmap_Msc.clip5.sbpd_rgb_r2r.tar) | 7.74 | 0 | 14 | 62.4 |
-cmp.lmap_Msc.clip5.sbpd_d_ST | [ckpt](http://download.tensorflow.org/models/cognitive_mapping_and_planning/2017_04_16/cmp.lmap_Msc.clip5.sbpd_d_ST.tar) | 10.67 | 9 | 19 | 39.7 |
-cmp.lmap_Msc.clip5.sbpd_rgb_ST | [ckpt](http://download.tensorflow.org/models/cognitive_mapping_and_planning/2017_04_16/cmp.lmap_Msc.clip5.sbpd_rgb_ST.tar) | 11.27 | 10 | 19 | 35.6 |
-cmp.lmap_Msc.clip5.sbpd_d_r2r_h0_64_80 | [ckpt](http:////download.tensorflow.org/models/cognitive_mapping_and_planning/2017_04_16/cmp.lmap_Msc.clip5.sbpd_d_r2r_h0_64_80.tar) | 11.6 | 0 | 19 | 66.9 |
-bl.v2.noclip.sbpd_d_r2r | [ckpt](http://download.tensorflow.org/models/cognitive_mapping_and_planning/2017_04_16/bl.v2.noclip.sbpd_d_r2r.tar) | 5.90 | 0 | 6 | 71.2 |
-bl.v2.noclip.sbpd_rgb_r2r | [ckpt](http://download.tensorflow.org/models/cognitive_mapping_and_planning/2017_04_16/bl.v2.noclip.sbpd_rgb_r2r.tar) | 10.21 | 1 | 21 | 53.4 |
-bl.v2.noclip.sbpd_d_ST | [ckpt](http://download.tensorflow.org/models/cognitive_mapping_and_planning/2017_04_16/bl.v2.noclip.sbpd_d_ST.tar) | 13.29 | 14 | 23 | 28.0 |
-bl.v2.noclip.sbpd_rgb_ST | [ckpt](http://download.tensorflow.org/models/cognitive_mapping_and_planning/2017_04_16/bl.v2.noclip.sbpd_rgb_ST.tar) | 13.37 | 13 | 20 | 24.2 |
-bl.v2.noclip.sbpd_d_r2r_h0_64_80 | [ckpt](http:////download.tensorflow.org/models/cognitive_mapping_and_planning/2017_04_16/bl.v2.noclip.sbpd_d_r2r_h0_64_80.tar) | 15.30 | 0 | 29 | 57.9 |
diff --git a/research/cognitive_mapping_and_planning/patches/GLES2_2_0.py.patch b/research/cognitive_mapping_and_planning/patches/GLES2_2_0.py.patch
deleted file mode 100644
index de1be442d5b9fff44862d37b9329e32face2b663..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/patches/GLES2_2_0.py.patch
+++ /dev/null
@@ -1,14 +0,0 @@
-10c10
-< from OpenGL import platform, constant, arrays
----
-> from OpenGL import platform, constant, arrays, contextdata
-249a250
-> from OpenGL._bytes import _NULL_8_BYTE
-399c400
-< array = ArrayDatatype.asArray( pointer, type )
----
-> array = arrays.ArrayDatatype.asArray( pointer, type )
-405c406
-< ArrayDatatype.voidDataPointer( array )
----
-> arrays.ArrayDatatype.voidDataPointer( array )
diff --git a/research/cognitive_mapping_and_planning/patches/apply_patches.sh b/research/cognitive_mapping_and_planning/patches/apply_patches.sh
deleted file mode 100644
index 4a786058258decdfb381eff25684183d92788ebe..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/patches/apply_patches.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-echo $VIRTUAL_ENV
-patch $VIRTUAL_ENV/local/lib/python2.7/site-packages/OpenGL/GLES2/VERSION/GLES2_2_0.py patches/GLES2_2_0.py.patch
-patch $VIRTUAL_ENV/local/lib/python2.7/site-packages/OpenGL/platform/ctypesloader.py patches/ctypesloader.py.patch
diff --git a/research/cognitive_mapping_and_planning/patches/ctypesloader.py.patch b/research/cognitive_mapping_and_planning/patches/ctypesloader.py.patch
deleted file mode 100644
index 27dd43b18010dc5fdcd605b9a5d470abaa19151f..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/patches/ctypesloader.py.patch
+++ /dev/null
@@ -1,15 +0,0 @@
-45c45,46
-< return dllType( name, mode )
----
-> print './' + name
-> return dllType( './' + name, mode )
-47,48c48,53
-< err.args += (name,fullName)
-< raise
----
-> try:
-> print name
-> return dllType( name, mode )
-> except:
-> err.args += (name,fullName)
-> raise
diff --git a/research/cognitive_mapping_and_planning/render/__init__.py b/research/cognitive_mapping_and_planning/render/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/cognitive_mapping_and_planning/render/depth_rgb_encoded.fp b/research/cognitive_mapping_and_planning/render/depth_rgb_encoded.fp
deleted file mode 100644
index 23e93d27f585e93896799f177888e9c50fa03eed..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/render/depth_rgb_encoded.fp
+++ /dev/null
@@ -1,30 +0,0 @@
-// This shader computes per-pixel depth (-z coordinate in the camera space, or
-// orthogonal distance to the camera plane). The result is multiplied by the
-// `kFixedPointFraction` constant and is encoded to RGB channels as an integer
-// (R being the least significant byte).
-
-#ifdef GL_ES
-#ifdef GL_FRAGMENT_PRECISION_HIGH
-precision highp float;
-#else
-precision mediump float;
-#endif
-#endif
-
-const float kFixedPointFraction = 1000.0;
-
-varying float vDepth;
-
-void main(void) {
- float d = vDepth;
-
- // Encode the depth to RGB.
- d *= (kFixedPointFraction / 255.0);
- gl_FragColor.r = mod(d, 1.0);
- d = (d - gl_FragColor.r) / 255.0;
- gl_FragColor.g = mod(d, 1.0);
- d = (d - gl_FragColor.g) / 255.0;
- gl_FragColor.b = mod(d, 1.0);
-
- gl_FragColor.a = 1.0;
-}
diff --git a/research/cognitive_mapping_and_planning/render/depth_rgb_encoded.vp b/research/cognitive_mapping_and_planning/render/depth_rgb_encoded.vp
deleted file mode 100644
index 2db74f14aa7f253b8f544ec1ab519129f13426a0..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/render/depth_rgb_encoded.vp
+++ /dev/null
@@ -1,15 +0,0 @@
-uniform mat4 uViewMatrix;
-uniform mat4 uProjectionMatrix;
-
-attribute vec3 aPosition;
-
-varying float vDepth;
-
-void main(void) {
- vec4 worldPosition = vec4(aPosition, 1.0);
- vec4 viewPosition = uViewMatrix * worldPosition;
- gl_Position = uProjectionMatrix * viewPosition;
-
- // Orthogonal depth is simply -z in the camera space.
- vDepth = -viewPosition.z;
-}
diff --git a/research/cognitive_mapping_and_planning/render/rgb_flat_color.fp b/research/cognitive_mapping_and_planning/render/rgb_flat_color.fp
deleted file mode 100644
index c8c24d76103793d9cfa9166517177cb332d1a92c..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/render/rgb_flat_color.fp
+++ /dev/null
@@ -1,11 +0,0 @@
-precision highp float;
-varying vec4 vColor;
-varying vec2 vTextureCoord;
-
-uniform sampler2D uTexture;
-
-void main(void) {
- vec4 color = vColor;
- color = texture2D(uTexture, vTextureCoord);
- gl_FragColor = color;
-}
diff --git a/research/cognitive_mapping_and_planning/render/rgb_flat_color.vp b/research/cognitive_mapping_and_planning/render/rgb_flat_color.vp
deleted file mode 100644
index ebc79173405f7449921fd40f778fe3695aab5ea8..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/render/rgb_flat_color.vp
+++ /dev/null
@@ -1,18 +0,0 @@
-uniform mat4 uViewMatrix;
-uniform mat4 uProjectionMatrix;
-uniform vec4 uColor;
-
-attribute vec4 aColor;
-attribute vec3 aPosition;
-attribute vec2 aTextureCoord;
-
-varying vec4 vColor;
-varying vec2 vTextureCoord;
-
-void main(void) {
- vec4 worldPosition = vec4(aPosition, 1.0);
- gl_Position = uProjectionMatrix * (uViewMatrix * worldPosition);
-
- vColor = aColor * uColor;
- vTextureCoord = aTextureCoord;
-}
diff --git a/research/cognitive_mapping_and_planning/render/swiftshader_renderer.py b/research/cognitive_mapping_and_planning/render/swiftshader_renderer.py
deleted file mode 100644
index 74b1be72c11a2877231a66886d02babfd4793ce8..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/render/swiftshader_renderer.py
+++ /dev/null
@@ -1,427 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-r"""Implements loading and rendering of meshes. Contains 2 classes:
- Shape: Class that exposes high level functions for loading and manipulating
- shapes. This currently is bound to assimp
- (https://github.com/assimp/assimp). If you want to interface to a different
- library, reimplement this class with bindings to your mesh loading library.
-
- SwiftshaderRenderer: Class that renders Shapes. Currently this uses python
- bindings to OpenGL (EGL), bindings to an alternate renderer may be implemented
- here.
-"""
-
-import numpy as np, os
-import cv2, ctypes, logging, os, numpy as np
-import pyassimp as assimp
-from OpenGL.GLES2 import *
-from OpenGL.EGL import *
-import src.rotation_utils as ru
-
-__version__ = 'swiftshader_renderer'
-
-def get_shaders(modalities):
- rgb_shader = 'rgb_flat_color' if 'rgb' in modalities else None
- d_shader = 'depth_rgb_encoded' if 'depth' in modalities else None
- return rgb_shader, d_shader
-
-def sample_points_on_faces(vs, fs, rng, n_samples_per_face):
- idx = np.repeat(np.arange(fs.shape[0]), n_samples_per_face)
-
- r = rng.rand(idx.size, 2)
- r1 = r[:,:1]; r2 = r[:,1:]; sqrt_r1 = np.sqrt(r1);
-
- v1 = vs[fs[idx, 0], :]; v2 = vs[fs[idx, 1], :]; v3 = vs[fs[idx, 2], :];
- pts = (1-sqrt_r1)*v1 + sqrt_r1*(1-r2)*v2 + sqrt_r1*r2*v3
-
- v1 = vs[fs[:,0], :]; v2 = vs[fs[:, 1], :]; v3 = vs[fs[:, 2], :];
- ar = 0.5*np.sqrt(np.sum(np.cross(v1-v3, v2-v3)**2, 1))
-
- return pts, ar, idx
-
-class Shape():
- def get_pyassimp_load_options(self):
- load_flags = assimp.postprocess.aiProcess_Triangulate;
- load_flags = load_flags | assimp.postprocess.aiProcess_SortByPType;
- load_flags = load_flags | assimp.postprocess.aiProcess_OptimizeMeshes;
- load_flags = load_flags | assimp.postprocess.aiProcess_RemoveRedundantMaterials;
- load_flags = load_flags | assimp.postprocess.aiProcess_FindDegenerates;
- load_flags = load_flags | assimp.postprocess.aiProcess_GenSmoothNormals;
- load_flags = load_flags | assimp.postprocess.aiProcess_JoinIdenticalVertices;
- load_flags = load_flags | assimp.postprocess.aiProcess_ImproveCacheLocality;
- load_flags = load_flags | assimp.postprocess.aiProcess_GenUVCoords;
- load_flags = load_flags | assimp.postprocess.aiProcess_FindInvalidData;
- return load_flags
-
- def __init__(self, obj_file, material_file=None, load_materials=True,
- name_prefix='', name_suffix=''):
- if material_file is not None:
- logging.error('Ignoring material file input, reading them off obj file.')
- load_flags = self.get_pyassimp_load_options()
- scene = assimp.load(obj_file, processing=load_flags)
- filter_ind = self._filter_triangles(scene.meshes)
- self.meshes = [scene.meshes[i] for i in filter_ind]
- for m in self.meshes:
- m.name = name_prefix + m.name + name_suffix
-
- dir_name = os.path.dirname(obj_file)
- # Load materials
- materials = None
- if load_materials:
- materials = []
- for m in self.meshes:
- file_name = os.path.join(dir_name, m.material.properties[('file', 1)])
- assert(os.path.exists(file_name)), \
- 'Texture file {:s} foes not exist.'.format(file_name)
- img_rgb = cv2.imread(file_name)[::-1,:,::-1]
- if img_rgb.shape[0] != img_rgb.shape[1]:
- logging.warn('Texture image not square.')
- sz = np.maximum(img_rgb.shape[0], img_rgb.shape[1])
- sz = int(np.power(2., np.ceil(np.log2(sz))))
- img_rgb = cv2.resize(img_rgb, (sz,sz), interpolation=cv2.INTER_LINEAR)
- else:
- sz = img_rgb.shape[0]
- sz_ = int(np.power(2., np.ceil(np.log2(sz))))
- if sz != sz_:
- logging.warn('Texture image not square of power of 2 size. ' +
- 'Changing size from %d to %d.', sz, sz_)
- sz = sz_
- img_rgb = cv2.resize(img_rgb, (sz,sz), interpolation=cv2.INTER_LINEAR)
- materials.append(img_rgb)
- self.scene = scene
- self.materials = materials
-
- def _filter_triangles(self, meshes):
- select = []
- for i in range(len(meshes)):
- if meshes[i].primitivetypes == 4:
- select.append(i)
- return select
-
- def flip_shape(self):
- for m in self.meshes:
- m.vertices[:,1] = -m.vertices[:,1]
- bb = m.faces*1
- bb[:,1] = m.faces[:,2]
- bb[:,2] = m.faces[:,1]
- m.faces = bb
- # m.vertices[:,[0,1]] = m.vertices[:,[1,0]]
-
- def get_vertices(self):
- vs = []
- for m in self.meshes:
- vs.append(m.vertices)
- vss = np.concatenate(vs, axis=0)
- return vss, vs
-
- def get_faces(self):
- vs = []
- for m in self.meshes:
- v = m.faces
- vs.append(v)
- return vs
-
- def get_number_of_meshes(self):
- return len(self.meshes)
-
- def scale(self, sx=1., sy=1., sz=1.):
- pass
-
- def sample_points_on_face_of_shape(self, i, n_samples_per_face, sc):
- v = self.meshes[i].vertices*sc
- f = self.meshes[i].faces
- p, face_areas, face_idx = sample_points_on_faces(
- v, f, np.random.RandomState(0), n_samples_per_face)
- return p, face_areas, face_idx
-
- def __del__(self):
- scene = self.scene
- assimp.release(scene)
-
-class SwiftshaderRenderer():
- def __init__(self):
- self.entities = {}
-
- def init_display(self, width, height, fov, z_near, z_far, rgb_shader,
- d_shader):
- self.init_renderer_egl(width, height)
- dir_path = os.path.dirname(os.path.realpath(__file__))
- if d_shader is not None and rgb_shader is not None:
- logging.fatal('Does not support setting both rgb_shader and d_shader.')
-
- if d_shader is not None:
- assert rgb_shader is None
- shader = d_shader
- self.modality = 'depth'
-
- if rgb_shader is not None:
- assert d_shader is None
- shader = rgb_shader
- self.modality = 'rgb'
-
- self.create_shaders(os.path.join(dir_path, shader+'.vp'),
- os.path.join(dir_path, shader + '.fp'))
- aspect = width*1./(height*1.)
- self.set_camera(fov, z_near, z_far, aspect)
-
- def init_renderer_egl(self, width, height):
- major,minor = ctypes.c_long(),ctypes.c_long()
- logging.info('init_renderer_egl: EGL_DEFAULT_DISPLAY: %s', EGL_DEFAULT_DISPLAY)
-
- egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY)
- logging.info('init_renderer_egl: egl_display: %s', egl_display)
-
- eglInitialize(egl_display, major, minor)
- logging.info('init_renderer_egl: EGL_OPENGL_API, EGL_OPENGL_ES_API: %s, %s',
- EGL_OPENGL_API, EGL_OPENGL_ES_API)
- eglBindAPI(EGL_OPENGL_ES_API)
-
- num_configs = ctypes.c_long()
- configs = (EGLConfig*1)()
- local_attributes = [EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8,
- EGL_DEPTH_SIZE, 16, EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE,]
- logging.error('init_renderer_egl: local attributes: %s', local_attributes)
- local_attributes = arrays.GLintArray.asArray(local_attributes)
- success = eglChooseConfig(egl_display, local_attributes, configs, 1, num_configs)
- logging.error('init_renderer_egl: eglChooseConfig success, num_configs: %d, %d', success, num_configs.value)
- egl_config = configs[0]
-
-
- context_attributes = [EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE]
- context_attributes = arrays.GLintArray.asArray(context_attributes)
- egl_context = eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, context_attributes)
-
- buffer_attributes = [EGL_WIDTH, width, EGL_HEIGHT, height, EGL_NONE]
- buffer_attributes = arrays.GLintArray.asArray(buffer_attributes)
- egl_surface = eglCreatePbufferSurface(egl_display, egl_config, buffer_attributes)
-
-
- eglMakeCurrent(egl_display, egl_surface, egl_surface, egl_context)
- logging.error("init_renderer_egl: egl_display: %s egl_surface: %s, egl_config: %s", egl_display, egl_surface, egl_context)
-
- glViewport(0, 0, width, height);
-
- self.egl_display = egl_display
- self.egl_surface = egl_surface
- self.egl_config = egl_config
- self.egl_mapping = {}
- self.render_timer = None
- self.load_timer = None
- self.height = height
- self.width = width
-
- def create_shaders(self, v_shader_file, f_shader_file):
- v_shader = glCreateShader(GL_VERTEX_SHADER)
- with open(v_shader_file, 'r') as f:
- ls = ''
- for l in f:
- ls = ls + l
- glShaderSource(v_shader, ls)
- glCompileShader(v_shader);
- assert(glGetShaderiv(v_shader, GL_COMPILE_STATUS) == 1)
-
- f_shader = glCreateShader(GL_FRAGMENT_SHADER)
- with open(f_shader_file, 'r') as f:
- ls = ''
- for l in f:
- ls = ls + l
- glShaderSource(f_shader, ls)
- glCompileShader(f_shader);
- assert(glGetShaderiv(f_shader, GL_COMPILE_STATUS) == 1)
-
- egl_program = glCreateProgram();
- assert(egl_program)
- glAttachShader(egl_program, v_shader)
- glAttachShader(egl_program, f_shader)
- glLinkProgram(egl_program);
- assert(glGetProgramiv(egl_program, GL_LINK_STATUS) == 1)
- glUseProgram(egl_program)
-
- glBindAttribLocation(egl_program, 0, "aPosition")
- glBindAttribLocation(egl_program, 1, "aColor")
- glBindAttribLocation(egl_program, 2, "aTextureCoord")
-
- self.egl_program = egl_program
- self.egl_mapping['vertexs'] = 0
- self.egl_mapping['vertexs_color'] = 1
- self.egl_mapping['vertexs_tc'] = 2
-
- glClearColor(0.0, 0.0, 0.0, 1.0);
- # glEnable(GL_CULL_FACE); glCullFace(GL_BACK);
- glEnable(GL_DEPTH_TEST);
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
-
- def set_camera(self, fov_vertical, z_near, z_far, aspect):
- width = 2*np.tan(np.deg2rad(fov_vertical)/2.0)*z_near*aspect;
- height = 2*np.tan(np.deg2rad(fov_vertical)/2.0)*z_near;
- egl_program = self.egl_program
- c = np.eye(4, dtype=np.float32)
- c[3,3] = 0
- c[3,2] = -1
- c[2,2] = -(z_near+z_far)/(z_far-z_near)
- c[2,3] = -2.0*(z_near*z_far)/(z_far-z_near)
- c[0,0] = 2.0*z_near/width
- c[1,1] = 2.0*z_near/height
- c = c.T
-
- projection_matrix_o = glGetUniformLocation(egl_program, 'uProjectionMatrix')
- projection_matrix = np.eye(4, dtype=np.float32)
- projection_matrix[...] = c
- projection_matrix = np.reshape(projection_matrix, (-1))
- glUniformMatrix4fv(projection_matrix_o, 1, GL_FALSE, projection_matrix)
-
-
- def load_default_object(self):
- v = np.array([[0.0, 0.5, 0.0, 1.0, 1.0, 0.0, 1.0],
- [-0.5, -0.5, 0.0, 1.0, 0.0, 1.0, 1.0],
- [0.5, -0.5, 0.0, 1.0, 1.0, 1.0, 1.0]], dtype=np.float32)
- v = np.concatenate((v,v+0.1), axis=0)
- v = np.ascontiguousarray(v, dtype=np.float32)
-
- vbo = glGenBuffers(1)
- glBindBuffer (GL_ARRAY_BUFFER, vbo)
- glBufferData (GL_ARRAY_BUFFER, v.dtype.itemsize*v.size, v, GL_STATIC_DRAW)
- glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 28, ctypes.c_void_p(0))
- glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 28, ctypes.c_void_p(12))
- glEnableVertexAttribArray(0);
- glEnableVertexAttribArray(1);
-
- self.num_to_render = 6;
-
- def _actual_render(self):
- for entity_id, entity in self.entities.iteritems():
- if entity['visible']:
- vbo = entity['vbo']
- tbo = entity['tbo']
- num = entity['num']
-
- glBindBuffer(GL_ARRAY_BUFFER, vbo)
- glVertexAttribPointer(self.egl_mapping['vertexs'], 3, GL_FLOAT, GL_FALSE,
- 20, ctypes.c_void_p(0))
- glVertexAttribPointer(self.egl_mapping['vertexs_tc'], 2, GL_FLOAT,
- GL_FALSE, 20, ctypes.c_void_p(12))
- glEnableVertexAttribArray(self.egl_mapping['vertexs']);
- glEnableVertexAttribArray(self.egl_mapping['vertexs_tc']);
-
- glBindTexture(GL_TEXTURE_2D, tbo)
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glDrawArrays(GL_TRIANGLES, 0, num)
-
- def render(self, take_screenshot=False, output_type=0):
- # self.render_timer.tic()
- self._actual_render()
- # self.render_timer.toc(log_at=1000, log_str='render timer', type='time')
-
- np_rgb_img = None
- np_d_img = None
- c = 1000.
- if take_screenshot:
- if self.modality == 'rgb':
- screenshot_rgba = np.zeros((self.height, self.width, 4), dtype=np.uint8)
- glReadPixels(0, 0, self.width, self.height, GL_RGBA, GL_UNSIGNED_BYTE, screenshot_rgba)
- np_rgb_img = screenshot_rgba[::-1,:,:3];
-
- if self.modality == 'depth':
- screenshot_d = np.zeros((self.height, self.width, 4), dtype=np.uint8)
- glReadPixels(0, 0, self.width, self.height, GL_RGBA, GL_UNSIGNED_BYTE, screenshot_d)
- np_d_img = screenshot_d[::-1,:,:3];
- np_d_img = np_d_img[:,:,2]*(255.*255./c) + np_d_img[:,:,1]*(255./c) + np_d_img[:,:,0]*(1./c)
- np_d_img = np_d_img.astype(np.float32)
- np_d_img[np_d_img == 0] = np.NaN
- np_d_img = np_d_img[:,:,np.newaxis]
-
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
- return np_rgb_img, np_d_img
-
- def _load_mesh_into_gl(self, mesh, material):
- vvt = np.concatenate((mesh.vertices, mesh.texturecoords[0,:,:2]), axis=1)
- vvt = np.ascontiguousarray(vvt[mesh.faces.reshape((-1)),:], dtype=np.float32)
- num = vvt.shape[0]
- vvt = np.reshape(vvt, (-1))
-
- vbo = glGenBuffers(1)
- glBindBuffer(GL_ARRAY_BUFFER, vbo)
- glBufferData(GL_ARRAY_BUFFER, vvt.dtype.itemsize*vvt.size, vvt, GL_STATIC_DRAW)
-
- tbo = glGenTextures(1)
- glBindTexture(GL_TEXTURE_2D, tbo)
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, material.shape[1],
- material.shape[0], 0, GL_RGB, GL_UNSIGNED_BYTE,
- np.reshape(material, (-1)))
- return num, vbo, tbo
-
- def load_shapes(self, shapes):
- entities = self.entities
- entity_ids = []
- for i, shape in enumerate(shapes):
- for j in range(len(shape.meshes)):
- name = shape.meshes[j].name
- assert name not in entities, '{:s} entity already exists.'.format(name)
- num, vbo, tbo = self._load_mesh_into_gl(shape.meshes[j], shape.materials[j])
- entities[name] = {'num': num, 'vbo': vbo, 'tbo': tbo, 'visible': False}
- entity_ids.append(name)
- return entity_ids
-
- def set_entity_visible(self, entity_ids, visibility):
- for entity_id in entity_ids:
- self.entities[entity_id]['visible'] = visibility
-
- def position_camera(self, camera_xyz, lookat_xyz, up):
- camera_xyz = np.array(camera_xyz)
- lookat_xyz = np.array(lookat_xyz)
- up = np.array(up)
- lookat_to = lookat_xyz - camera_xyz
- lookat_from = np.array([0, 1., 0.])
- up_from = np.array([0, 0., 1.])
- up_to = up * 1.
- # np.set_printoptions(precision=2, suppress=True)
- # print up_from, lookat_from, up_to, lookat_to
- r = ru.rotate_camera_to_point_at(up_from, lookat_from, up_to, lookat_to)
- R = np.eye(4, dtype=np.float32)
- R[:3,:3] = r
-
- t = np.eye(4, dtype=np.float32)
- t[:3,3] = -camera_xyz
-
- view_matrix = np.dot(R.T, t)
- flip_yz = np.eye(4, dtype=np.float32)
- flip_yz[1,1] = 0; flip_yz[2,2] = 0; flip_yz[1,2] = 1; flip_yz[2,1] = -1;
- view_matrix = np.dot(flip_yz, view_matrix)
- view_matrix = view_matrix.T
- # print np.concatenate((R, t, view_matrix), axis=1)
- view_matrix = np.reshape(view_matrix, (-1))
- view_matrix_o = glGetUniformLocation(self.egl_program, 'uViewMatrix')
- glUniformMatrix4fv(view_matrix_o, 1, GL_FALSE, view_matrix)
- return None, None #camera_xyz, q
-
- def clear_scene(self):
- keys = self.entities.keys()
- for entity_id in keys:
- entity = self.entities.pop(entity_id, None)
- vbo = entity['vbo']
- tbo = entity['tbo']
- num = entity['num']
- glDeleteBuffers(1, [vbo])
- glDeleteTextures(1, [tbo])
-
- def __del__(self):
- self.clear_scene()
- eglMakeCurrent(self.egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)
- eglDestroySurface(self.egl_display, self.egl_surface)
- eglTerminate(self.egl_display)
diff --git a/research/cognitive_mapping_and_planning/requirements.txt b/research/cognitive_mapping_and_planning/requirements.txt
deleted file mode 100644
index 306c807a6c9fd9404afa1c05108e5e835e84edc6..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/requirements.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-numpy
-pillow
-PyOpenGL
-PyOpenGL-accelerate
-six
-networkx
-scikit-image
-scipy
-opencv-python
diff --git a/research/cognitive_mapping_and_planning/scripts/__init__.py b/research/cognitive_mapping_and_planning/scripts/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/cognitive_mapping_and_planning/scripts/script_distill.py b/research/cognitive_mapping_and_planning/scripts/script_distill.py
deleted file mode 100644
index 010c690412ed28011146ab44109dc099d02324e7..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/scripts/script_distill.py
+++ /dev/null
@@ -1,177 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-r""" Script to setup the grid moving agent.
-
-blaze build --define=ION_GFX_OGLES20=1 -c opt --copt=-mavx --config=cuda_clang \
- learning/brain/public/tensorflow_std_server{,_gpu} \
- experimental/users/saurabhgupta/navigation/cmp/scripts/script_distill.par \
- experimental/users/saurabhgupta/navigation/cmp/scripts/script_distill
-
-
-./blaze-bin/experimental/users/saurabhgupta/navigation/cmp/scripts/script_distill \
- --logdir=/cns/iq-d/home/saurabhgupta/output/stanford-distill/local/v0/ \
- --config_name 'v0+train' --gfs_user robot-intelligence-gpu
-
-"""
-import sys, os, numpy as np
-import copy
-import argparse, pprint
-import time
-import cProfile
-
-
-import tensorflow as tf
-from tensorflow.contrib import slim
-from tensorflow.python.framework import ops
-from tensorflow.contrib.framework.python.ops import variables
-
-import logging
-from tensorflow.python.platform import gfile
-from tensorflow.python.platform import app
-from tensorflow.python.platform import flags
-from cfgs import config_distill
-from tfcode import tf_utils
-import src.utils as utils
-import src.file_utils as fu
-import tfcode.distillation as distill
-import datasets.nav_env as nav_env
-
-FLAGS = flags.FLAGS
-
-flags.DEFINE_string('master', 'local',
- 'The name of the TensorFlow master to use.')
-flags.DEFINE_integer('ps_tasks', 0, 'The number of parameter servers. If the '
- 'value is 0, then the parameters are handled locally by '
- 'the worker.')
-flags.DEFINE_integer('task', 0, 'The Task ID. This value is used when training '
- 'with multiple workers to identify each worker.')
-
-flags.DEFINE_integer('num_workers', 1, '')
-
-flags.DEFINE_string('config_name', '', '')
-
-flags.DEFINE_string('logdir', '', '')
-
-def main(_):
- args = config_distill.get_args_for_config(FLAGS.config_name)
- args.logdir = FLAGS.logdir
- args.solver.num_workers = FLAGS.num_workers
- args.solver.task = FLAGS.task
- args.solver.ps_tasks = FLAGS.ps_tasks
- args.solver.master = FLAGS.master
-
- args.buildinger.env_class = nav_env.MeshMapper
- fu.makedirs(args.logdir)
- args.buildinger.logdir = args.logdir
- R = nav_env.get_multiplexor_class(args.buildinger, args.solver.task)
-
- if False:
- pr = cProfile.Profile()
- pr.enable()
- rng = np.random.RandomState(0)
- for i in range(1):
- b, instances_perturbs = R.sample_building(rng)
- inputs = b.worker(*(instances_perturbs))
- for j in range(inputs['imgs'].shape[0]):
- p = os.path.join('tmp', '{:d}.png'.format(j))
- img = inputs['imgs'][j,0,:,:,:3]*1
- img = (img).astype(np.uint8)
- fu.write_image(p, img)
- print(inputs['imgs'].shape)
- inputs = R.pre(inputs)
- pr.disable()
- pr.print_stats(2)
-
- if args.control.train:
- if not gfile.Exists(args.logdir):
- gfile.MakeDirs(args.logdir)
-
- m = utils.Foo()
- m.tf_graph = tf.Graph()
-
- config = tf.ConfigProto()
- config.device_count['GPU'] = 1
- config.gpu_options.allow_growth = True
- config.gpu_options.per_process_gpu_memory_fraction = 0.8
-
- with m.tf_graph.as_default():
- with tf.device(tf.train.replica_device_setter(args.solver.ps_tasks)):
- m = distill.setup_to_run(m, args, is_training=True,
- batch_norm_is_training=True)
-
- train_step_kwargs = distill.setup_train_step_kwargs_mesh(
- m, R, os.path.join(args.logdir, 'train'),
- rng_seed=args.solver.task, is_chief=args.solver.task==0, iters=1,
- train_display_interval=args.summary.display_interval)
-
- final_loss = slim.learning.train(
- train_op=m.train_op,
- logdir=args.logdir,
- master=args.solver.master,
- is_chief=args.solver.task == 0,
- number_of_steps=args.solver.max_steps,
- train_step_fn=tf_utils.train_step_custom,
- train_step_kwargs=train_step_kwargs,
- global_step=m.global_step_op,
- init_op=m.init_op,
- init_fn=m.init_fn,
- sync_optimizer=m.sync_optimizer,
- saver=m.saver_op,
- summary_op=None, session_config=config)
-
- if args.control.test:
- m = utils.Foo()
- m.tf_graph = tf.Graph()
- checkpoint_dir = os.path.join(format(args.logdir))
- with m.tf_graph.as_default():
- m = distill.setup_to_run(m, args, is_training=False,
- batch_norm_is_training=args.control.force_batchnorm_is_training_at_test)
-
- train_step_kwargs = distill.setup_train_step_kwargs_mesh(
- m, R, os.path.join(args.logdir, args.control.test_name),
- rng_seed=args.solver.task+1, is_chief=args.solver.task==0,
- iters=args.summary.test_iters, train_display_interval=None)
-
- sv = slim.learning.supervisor.Supervisor(
- graph=ops.get_default_graph(), logdir=None, init_op=m.init_op,
- summary_op=None, summary_writer=None, global_step=None, saver=m.saver_op)
-
- last_checkpoint = None
- while True:
- last_checkpoint = slim.evaluation.wait_for_new_checkpoint(checkpoint_dir, last_checkpoint)
- checkpoint_iter = int(os.path.basename(last_checkpoint).split('-')[1])
- start = time.time()
- logging.info('Starting evaluation at %s using checkpoint %s.',
- time.strftime('%Y-%m-%d-%H:%M:%S', time.localtime()),
- last_checkpoint)
-
- config = tf.ConfigProto()
- config.device_count['GPU'] = 1
- config.gpu_options.allow_growth = True
- config.gpu_options.per_process_gpu_memory_fraction = 0.8
-
- with sv.managed_session(args.solver.master,config=config,
- start_standard_services=False) as sess:
- sess.run(m.init_op)
- sv.saver.restore(sess, last_checkpoint)
- sv.start_queue_runners(sess)
- vals, _ = tf_utils.train_step_custom(
- sess, None, m.global_step_op, train_step_kwargs, mode='val')
- if checkpoint_iter >= args.solver.max_steps:
- break
-
-if __name__ == '__main__':
- app.run()
diff --git a/research/cognitive_mapping_and_planning/scripts/script_download_init_models.sh b/research/cognitive_mapping_and_planning/scripts/script_download_init_models.sh
deleted file mode 100644
index 1900bd0b03566d29dac8a8de5f4fce623be98a92..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/scripts/script_download_init_models.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-# Script to download models to initialize the RGB and D models for training.We
-# use ResNet-v2-50 for both modalities.
-
-mkdir -p data/init_models
-cd data/init_models
-
-# RGB Models are initialized by pre-training on ImageNet.
-mkdir -p resnet_v2_50
-RGB_URL="http://download.tensorflow.org/models/resnet_v2_50_2017_04_14.tar.gz"
-wget $RGB_URL
-tar -xf resnet_v2_50_2017_04_14.tar.gz -C resnet_v2_50
-
-# Depth models are initialized by distilling the RGB model to D images using
-# Cross-Modal Distillation (https://arxiv.org/abs/1507.00448).
-mkdir -p distill_rgb_to_d_resnet_v2_50
-D_URL="http://download.tensorflow.org/models/cognitive_mapping_and_planning/2017_04_16/distill_rgb_to_d_resnet_v2_50.tar"
-wget $D_URL
-tar -xf distill_rgb_to_d_resnet_v2_50.tar -C distill_rgb_to_d_resnet_v2_50
diff --git a/research/cognitive_mapping_and_planning/scripts/script_env_vis.py b/research/cognitive_mapping_and_planning/scripts/script_env_vis.py
deleted file mode 100644
index 3690ff484fea9344db6fbe20ac54731200f0c84e..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/scripts/script_env_vis.py
+++ /dev/null
@@ -1,186 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""A simple python function to walk in the enviornments that we have created.
-PYTHONPATH='.' PYOPENGL_PLATFORM=egl python scripts/script_env_vis.py \
- --dataset_name sbpd --building_name area3
-"""
-import sys
-import numpy as np
-import matplotlib
-matplotlib.use('TkAgg')
-from PIL import ImageTk, Image
-import Tkinter as tk
-import logging
-from tensorflow.python.platform import app
-from tensorflow.python.platform import flags
-
-import datasets.nav_env_config as nec
-import datasets.nav_env as nav_env
-import cv2
-from datasets import factory
-import render.swiftshader_renderer as renderer
-
-SwiftshaderRenderer = renderer.SwiftshaderRenderer
-VisualNavigationEnv = nav_env.VisualNavigationEnv
-
-FLAGS = flags.FLAGS
-flags.DEFINE_string('dataset_name', 'sbpd', 'Name of the dataset.')
-flags.DEFINE_float('fov', 60., 'Field of view')
-flags.DEFINE_integer('image_size', 512, 'Size of the image.')
-flags.DEFINE_string('building_name', '', 'Name of the building.')
-
-def get_args():
- navtask = nec.nav_env_base_config()
- navtask.task_params.type = 'rng_rejection_sampling_many'
- navtask.task_params.rejection_sampling_M = 2000
- navtask.task_params.min_dist = 10
- sz = FLAGS.image_size
- navtask.camera_param.fov = FLAGS.fov
- navtask.camera_param.height = sz
- navtask.camera_param.width = sz
- navtask.task_params.img_height = sz
- navtask.task_params.img_width = sz
-
- # navtask.task_params.semantic_task.class_map_names = ['chair', 'door', 'table']
- # navtask.task_params.type = 'to_nearest_obj_acc'
-
- logging.info('navtask: %s', navtask)
- return navtask
-
-def load_building(dataset_name, building_name):
- dataset = factory.get_dataset(dataset_name)
-
- navtask = get_args()
- cp = navtask.camera_param
- rgb_shader, d_shader = renderer.get_shaders(cp.modalities)
- r_obj = SwiftshaderRenderer()
- r_obj.init_display(width=cp.width, height=cp.height,
- fov=cp.fov, z_near=cp.z_near, z_far=cp.z_far,
- rgb_shader=rgb_shader, d_shader=d_shader)
- r_obj.clear_scene()
- b = VisualNavigationEnv(robot=navtask.robot, env=navtask.env,
- task_params=navtask.task_params,
- building_name=building_name, flip=False,
- logdir=None, building_loader=dataset,
- r_obj=r_obj)
- b.load_building_into_scene()
- b.set_building_visibility(False)
- return b
-
-def walk_through(b):
- # init agent at a random location in the environment.
- init_env_state = b.reset([np.random.RandomState(0), np.random.RandomState(0)])
-
- global current_node
- rng = np.random.RandomState(0)
- current_node = rng.choice(b.task.nodes.shape[0])
-
- root = tk.Tk()
- image = b.render_nodes(b.task.nodes[[current_node],:])[0]
- print(image.shape)
- image = image.astype(np.uint8)
- im = Image.fromarray(image)
- im = ImageTk.PhotoImage(im)
- panel = tk.Label(root, image=im)
-
- map_size = b.traversible.shape
- sc = np.max(map_size)/256.
- loc = np.array([[map_size[1]/2., map_size[0]/2.]])
- x_axis = np.zeros_like(loc); x_axis[:,1] = sc
- y_axis = np.zeros_like(loc); y_axis[:,0] = -sc
- cum_fs, cum_valid = nav_env.get_map_to_predict(loc, x_axis, y_axis,
- map=b.traversible*1.,
- map_size=256)
- cum_fs = cum_fs[0]
- cum_fs = cv2.applyColorMap((cum_fs*255).astype(np.uint8), cv2.COLORMAP_JET)
- im = Image.fromarray(cum_fs)
- im = ImageTk.PhotoImage(im)
- panel_overhead = tk.Label(root, image=im)
-
- def refresh():
- global current_node
- image = b.render_nodes(b.task.nodes[[current_node],:])[0]
- image = image.astype(np.uint8)
- im = Image.fromarray(image)
- im = ImageTk.PhotoImage(im)
- panel.configure(image=im)
- panel.image = im
-
- def left_key(event):
- global current_node
- current_node = b.take_action([current_node], [2], 1)[0][0]
- refresh()
-
- def up_key(event):
- global current_node
- current_node = b.take_action([current_node], [3], 1)[0][0]
- refresh()
-
- def right_key(event):
- global current_node
- current_node = b.take_action([current_node], [1], 1)[0][0]
- refresh()
-
- def quit(event):
- root.destroy()
-
- panel_overhead.grid(row=4, column=5, rowspan=1, columnspan=1,
- sticky=tk.W+tk.E+tk.N+tk.S)
- panel.bind('', left_key)
- panel.bind('', up_key)
- panel.bind('', right_key)
- panel.bind('q', quit)
- panel.focus_set()
- panel.grid(row=0, column=0, rowspan=5, columnspan=5,
- sticky=tk.W+tk.E+tk.N+tk.S)
- root.mainloop()
-
-def simple_window():
- root = tk.Tk()
-
- image = np.zeros((128, 128, 3), dtype=np.uint8)
- image[32:96, 32:96, 0] = 255
- im = Image.fromarray(image)
- im = ImageTk.PhotoImage(im)
-
- image = np.zeros((128, 128, 3), dtype=np.uint8)
- image[32:96, 32:96, 1] = 255
- im2 = Image.fromarray(image)
- im2 = ImageTk.PhotoImage(im2)
-
- panel = tk.Label(root, image=im)
-
- def left_key(event):
- panel.configure(image=im2)
- panel.image = im2
-
- def quit(event):
- sys.exit()
-
- panel.bind('', left_key)
- panel.bind('', left_key)
- panel.bind('', left_key)
- panel.bind('q', quit)
- panel.focus_set()
- panel.pack(side = "bottom", fill = "both", expand = "yes")
- root.mainloop()
-
-def main(_):
- b = load_building(FLAGS.dataset_name, FLAGS.building_name)
- walk_through(b)
-
-if __name__ == '__main__':
- app.run()
diff --git a/research/cognitive_mapping_and_planning/scripts/script_nav_agent_release.py b/research/cognitive_mapping_and_planning/scripts/script_nav_agent_release.py
deleted file mode 100644
index dab2819a6fcf100cb2e385e45b7aa694c4c5f033..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/scripts/script_nav_agent_release.py
+++ /dev/null
@@ -1,253 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-r""" Script to train and test the grid navigation agent.
-Usage:
- 1. Testing a model.
- CUDA_VISIBLE_DEVICES=0 LD_LIBRARY_PATH=/opt/cuda-8.0/lib64:/opt/cudnnv51/lib64 \
- PYTHONPATH='.' PYOPENGL_PLATFORM=egl python scripts/script_nav_agent_release.py \
- --config_name cmp.lmap_Msc.clip5.sbpd_d_r2r+bench_test \
- --logdir output/cmp.lmap_Msc.clip5.sbpd_d_r2r
-
- 2. Training a model (locally).
- CUDA_VISIBLE_DEVICES=0 LD_LIBRARY_PATH=/opt/cuda-8.0/lib64:/opt/cudnnv51/lib64 \
- PYTHONPATH='.' PYOPENGL_PLATFORM=egl python scripts/script_nav_agent_release.py \
- --config_name cmp.lmap_Msc.clip5.sbpd_d_r2r+train_train \
- --logdir output/cmp.lmap_Msc.clip5.sbpd_d_r2r_
-
- 3. Training a model (distributed).
- # See https://www.tensorflow.org/deploy/distributed on how to setup distributed
- # training.
- CUDA_VISIBLE_DEVICES=0 LD_LIBRARY_PATH=/opt/cuda-8.0/lib64:/opt/cudnnv51/lib64 \
- PYTHONPATH='.' PYOPENGL_PLATFORM=egl python scripts/script_nav_agent_release.py \
- --config_name cmp.lmap_Msc.clip5.sbpd_d_r2r+train_train \
- --logdir output/cmp.lmap_Msc.clip5.sbpd_d_r2r_ \
- --ps_tasks $num_ps --master $master_name --task $worker_id
-"""
-
-import sys, os, numpy as np
-import copy
-import argparse, pprint
-import time
-import cProfile
-import platform
-
-
-import tensorflow as tf
-from tensorflow.contrib import slim
-from tensorflow.python.framework import ops
-from tensorflow.contrib.framework.python.ops import variables
-
-import logging
-from tensorflow.python.platform import gfile
-from tensorflow.python.platform import app
-from tensorflow.python.platform import flags
-from cfgs import config_cmp
-from cfgs import config_vision_baseline
-import datasets.nav_env as nav_env
-import src.file_utils as fu
-import src.utils as utils
-import tfcode.cmp as cmp
-from tfcode import tf_utils
-from tfcode import vision_baseline_lstm
-
-FLAGS = flags.FLAGS
-
-flags.DEFINE_string('master', '',
- 'The address of the tensorflow master')
-flags.DEFINE_integer('ps_tasks', 0, 'The number of parameter servers. If the '
- 'value is 0, then the parameters are handled locally by '
- 'the worker.')
-flags.DEFINE_integer('task', 0, 'The Task ID. This value is used when training '
- 'with multiple workers to identify each worker.')
-
-flags.DEFINE_integer('num_workers', 1, '')
-
-flags.DEFINE_string('config_name', '', '')
-
-flags.DEFINE_string('logdir', '', '')
-
-flags.DEFINE_integer('solver_seed', 0, '')
-
-flags.DEFINE_integer('delay_start_iters', 20, '')
-
-logging.basicConfig(level=logging.INFO)
-
-def main(_):
- _launcher(FLAGS.config_name, FLAGS.logdir)
-
-def _launcher(config_name, logdir):
- args = _setup_args(config_name, logdir)
-
- fu.makedirs(args.logdir)
-
- if args.control.train:
- _train(args)
-
- if args.control.test:
- _test(args)
-
-def get_args_for_config(config_name):
- configs = config_name.split('.')
- type = configs[0]
- config_name = '.'.join(configs[1:])
- if type == 'cmp':
- args = config_cmp.get_args_for_config(config_name)
- args.setup_to_run = cmp.setup_to_run
- args.setup_train_step_kwargs = cmp.setup_train_step_kwargs
-
- elif type == 'bl':
- args = config_vision_baseline.get_args_for_config(config_name)
- args.setup_to_run = vision_baseline_lstm.setup_to_run
- args.setup_train_step_kwargs = vision_baseline_lstm.setup_train_step_kwargs
-
- else:
- logging.fatal('Unknown type: {:s}'.format(type))
- return args
-
-def _setup_args(config_name, logdir):
- args = get_args_for_config(config_name)
- args.solver.num_workers = FLAGS.num_workers
- args.solver.task = FLAGS.task
- args.solver.ps_tasks = FLAGS.ps_tasks
- args.solver.master = FLAGS.master
- args.solver.seed = FLAGS.solver_seed
- args.logdir = logdir
- args.navtask.logdir = None
- return args
-
-def _train(args):
- container_name = ""
-
- R = lambda: nav_env.get_multiplexer_class(args.navtask, args.solver.task)
- m = utils.Foo()
- m.tf_graph = tf.Graph()
-
- config = tf.ConfigProto()
- config.device_count['GPU'] = 1
-
- with m.tf_graph.as_default():
- with tf.device(tf.train.replica_device_setter(args.solver.ps_tasks,
- merge_devices=True)):
- with tf.container(container_name):
- m = args.setup_to_run(m, args, is_training=True,
- batch_norm_is_training=True, summary_mode='train')
-
- train_step_kwargs = args.setup_train_step_kwargs(
- m, R(), os.path.join(args.logdir, 'train'), rng_seed=args.solver.task,
- is_chief=args.solver.task==0,
- num_steps=args.navtask.task_params.num_steps*args.navtask.task_params.num_goals, iters=1,
- train_display_interval=args.summary.display_interval,
- dagger_sample_bn_false=args.arch.dagger_sample_bn_false)
-
- delay_start = (args.solver.task*(args.solver.task+1))/2 * FLAGS.delay_start_iters
- logging.error('delaying start for task %d by %d steps.',
- args.solver.task, delay_start)
-
- additional_args = {}
- final_loss = slim.learning.train(
- train_op=m.train_op,
- logdir=args.logdir,
- master=args.solver.master,
- is_chief=args.solver.task == 0,
- number_of_steps=args.solver.max_steps,
- train_step_fn=tf_utils.train_step_custom_online_sampling,
- train_step_kwargs=train_step_kwargs,
- global_step=m.global_step_op,
- init_op=m.init_op,
- init_fn=m.init_fn,
- sync_optimizer=m.sync_optimizer,
- saver=m.saver_op,
- startup_delay_steps=delay_start,
- summary_op=None, session_config=config, **additional_args)
-
-def _test(args):
- args.solver.master = ''
- container_name = ""
- checkpoint_dir = os.path.join(format(args.logdir))
- logging.error('Checkpoint_dir: %s', args.logdir)
-
- config = tf.ConfigProto();
- config.device_count['GPU'] = 1;
-
- m = utils.Foo()
- m.tf_graph = tf.Graph()
-
- rng_data_seed = 0; rng_action_seed = 0;
- R = lambda: nav_env.get_multiplexer_class(args.navtask, rng_data_seed)
- with m.tf_graph.as_default():
- with tf.container(container_name):
- m = args.setup_to_run(
- m, args, is_training=False,
- batch_norm_is_training=args.control.force_batchnorm_is_training_at_test,
- summary_mode=args.control.test_mode)
- train_step_kwargs = args.setup_train_step_kwargs(
- m, R(), os.path.join(args.logdir, args.control.test_name),
- rng_seed=rng_data_seed, is_chief=True,
- num_steps=args.navtask.task_params.num_steps*args.navtask.task_params.num_goals,
- iters=args.summary.test_iters, train_display_interval=None,
- dagger_sample_bn_false=args.arch.dagger_sample_bn_false)
-
- saver = slim.learning.tf_saver.Saver(variables.get_variables_to_restore())
-
- sv = slim.learning.supervisor.Supervisor(
- graph=ops.get_default_graph(), logdir=None, init_op=m.init_op,
- summary_op=None, summary_writer=None, global_step=None, saver=m.saver_op)
-
- last_checkpoint = None
- reported = False
- while True:
- last_checkpoint_ = None
- while last_checkpoint_ is None:
- last_checkpoint_ = slim.evaluation.wait_for_new_checkpoint(
- checkpoint_dir, last_checkpoint, seconds_to_sleep=10, timeout=60)
- if last_checkpoint_ is None: break
-
- last_checkpoint = last_checkpoint_
- checkpoint_iter = int(os.path.basename(last_checkpoint).split('-')[1])
-
- logging.info('Starting evaluation at %s using checkpoint %s.',
- time.strftime('%Y-%m-%d-%H:%M:%S', time.localtime()),
- last_checkpoint)
-
- if (args.control.only_eval_when_done == False or
- checkpoint_iter >= args.solver.max_steps):
- start = time.time()
- logging.info('Starting evaluation at %s using checkpoint %s.',
- time.strftime('%Y-%m-%d-%H:%M:%S', time.localtime()),
- last_checkpoint)
-
- with sv.managed_session(args.solver.master, config=config,
- start_standard_services=False) as sess:
- sess.run(m.init_op)
- sv.saver.restore(sess, last_checkpoint)
- sv.start_queue_runners(sess)
- if args.control.reset_rng_seed:
- train_step_kwargs['rng_data'] = [np.random.RandomState(rng_data_seed),
- np.random.RandomState(rng_data_seed)]
- train_step_kwargs['rng_action'] = np.random.RandomState(rng_action_seed)
- vals, _ = tf_utils.train_step_custom_online_sampling(
- sess, None, m.global_step_op, train_step_kwargs,
- mode=args.control.test_mode)
- should_stop = False
-
- if checkpoint_iter >= args.solver.max_steps:
- should_stop = True
-
- if should_stop:
- break
-
-if __name__ == '__main__':
- app.run()
diff --git a/research/cognitive_mapping_and_planning/scripts/script_plot_trajectory.py b/research/cognitive_mapping_and_planning/scripts/script_plot_trajectory.py
deleted file mode 100644
index 08273a83b512fa3100f7df6e20d41d666b037aad..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/scripts/script_plot_trajectory.py
+++ /dev/null
@@ -1,339 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-r"""
-Code for plotting trajectories in the top view, and also plot first person views
-from saved trajectories. Does not run the network but only loads the mesh data
-to plot the view points.
- CUDA_VISIBLE_DEVICES=0 LD_LIBRARY_PATH=/opt/cuda-8.0/lib64:/opt/cudnnv51/lib64
- PYTHONPATH='.' PYOPENGL_PLATFORM=egl python scripts/script_plot_trajectory.py \
- --first_person --num_steps 40 \
- --config_name cmp.lmap_Msc.clip5.sbpd_d_r2r \
- --imset test --alsologtostderr --base_dir output --out_dir vis
-
-"""
-import os, sys, numpy as np, copy
-import matplotlib
-matplotlib.use("Agg")
-import matplotlib.pyplot as plt
-import matplotlib.animation as animation
-from matplotlib.gridspec import GridSpec
-
-import tensorflow as tf
-from tensorflow.contrib import slim
-import cv2
-import logging
-from tensorflow.python.platform import gfile
-from tensorflow.python.platform import app
-from tensorflow.python.platform import flags
-
-from datasets import nav_env
-import scripts.script_nav_agent_release as sna
-import src.file_utils as fu
-from src import graph_utils
-from src import utils
-FLAGS = flags.FLAGS
-
-flags.DEFINE_string('out_dir', 'vis', 'Directory where to store the output')
-flags.DEFINE_string('type', '', 'Optional type.')
-flags.DEFINE_bool('first_person', False, 'Visualize the first person view.')
-flags.DEFINE_bool('top_view', False, 'Visualize the trajectory in the top view.')
-flags.DEFINE_integer('num_steps', 40, 'Number of steps to run the model for.')
-flags.DEFINE_string('imset', 'test', '')
-flags.DEFINE_string('base_dir', 'output', 'Cache directory.')
-
-def _get_suffix_str():
- return ''
-
-
-def _load_trajectory():
- base_dir = FLAGS.base_dir
- config_name = FLAGS.config_name+_get_suffix_str()
-
- dir_name = os.path.join(base_dir, FLAGS.type, config_name)
- logging.info('Waiting for snapshot in directory %s.', dir_name)
- last_checkpoint = slim.evaluation.wait_for_new_checkpoint(dir_name, None)
- checkpoint_iter = int(os.path.basename(last_checkpoint).split('-')[1])
-
- # Load the distances.
- a = utils.load_variables(os.path.join(dir_name, 'bench_on_'+FLAGS.imset,
- 'all_locs_at_t_{:d}.pkl'.format(checkpoint_iter)))
- return a
-
-def _compute_hardness():
- # Load the stanford data to compute the hardness.
- if FLAGS.type == '':
- args = sna.get_args_for_config(FLAGS.config_name+'+bench_'+FLAGS.imset)
- else:
- args = sna.get_args_for_config(FLAGS.type+'.'+FLAGS.config_name+'+bench_'+FLAGS.imset)
-
- args.navtask.logdir = None
- R = lambda: nav_env.get_multiplexer_class(args.navtask, 0)
- R = R()
-
- rng_data = [np.random.RandomState(0), np.random.RandomState(0)]
-
- # Sample a room.
- h_dists = []
- gt_dists = []
- for i in range(250):
- e = R.sample_env(rng_data)
- nodes = e.task.nodes
-
- # Initialize the agent.
- init_env_state = e.reset(rng_data)
-
- gt_dist_to_goal = [e.episode.dist_to_goal[0][j][s]
- for j, s in enumerate(e.episode.start_node_ids)]
-
- for j in range(args.navtask.task_params.batch_size):
- start_node_id = e.episode.start_node_ids[j]
- end_node_id =e.episode.goal_node_ids[0][j]
- h_dist = graph_utils.heuristic_fn_vec(
- nodes[[start_node_id],:], nodes[[end_node_id], :],
- n_ori=args.navtask.task_params.n_ori,
- step_size=args.navtask.task_params.step_size)[0][0]
- gt_dist = e.episode.dist_to_goal[0][j][start_node_id]
- h_dists.append(h_dist)
- gt_dists.append(gt_dist)
-
- h_dists = np.array(h_dists)
- gt_dists = np.array(gt_dists)
- e = R.sample_env([np.random.RandomState(0), np.random.RandomState(0)])
- input = e.get_common_data()
- orig_maps = input['orig_maps'][0,0,:,:,0]
- return h_dists, gt_dists, orig_maps
-
-def plot_trajectory_first_person(dt, orig_maps, out_dir):
- out_dir = os.path.join(out_dir, FLAGS.config_name+_get_suffix_str(),
- FLAGS.imset)
- fu.makedirs(out_dir)
-
- # Load the model so that we can render.
- plt.set_cmap('gray')
- samples_per_action = 8; wait_at_action = 0;
-
- Writer = animation.writers['mencoder']
- writer = Writer(fps=3*(samples_per_action+wait_at_action),
- metadata=dict(artist='anonymous'), bitrate=1800)
-
- args = sna.get_args_for_config(FLAGS.config_name + '+bench_'+FLAGS.imset)
- args.navtask.logdir = None
- navtask_ = copy.deepcopy(args.navtask)
- navtask_.camera_param.modalities = ['rgb']
- navtask_.task_params.modalities = ['rgb']
- sz = 512
- navtask_.camera_param.height = sz
- navtask_.camera_param.width = sz
- navtask_.task_params.img_height = sz
- navtask_.task_params.img_width = sz
- R = lambda: nav_env.get_multiplexer_class(navtask_, 0)
- R = R()
- b = R.buildings[0]
-
- f = [0 for _ in range(wait_at_action)] + \
- [float(_)/samples_per_action for _ in range(samples_per_action)];
-
- # Generate things for it to render.
- inds_to_do = []
- inds_to_do += [1, 4, 10] #1291, 1268, 1273, 1289, 1302, 1426, 1413, 1449, 1399, 1390]
-
- for i in inds_to_do:
- fig = plt.figure(figsize=(10,8))
- gs = GridSpec(3,4)
- gs.update(wspace=0.05, hspace=0.05, left=0.0, top=0.97, right=1.0, bottom=0.)
- ax = fig.add_subplot(gs[:,:-1])
- ax1 = fig.add_subplot(gs[0,-1])
- ax2 = fig.add_subplot(gs[1,-1])
- ax3 = fig.add_subplot(gs[2,-1])
- axes = [ax, ax1, ax2, ax3]
- # ax = fig.add_subplot(gs[:,:])
- # axes = [ax]
- for ax in axes:
- ax.set_axis_off()
-
- node_ids = dt['all_node_ids'][i, :, 0]*1
- # Prune so that last node is not repeated more than 3 times?
- if np.all(node_ids[-4:] == node_ids[-1]):
- while node_ids[-4] == node_ids[-1]:
- node_ids = node_ids[:-1]
- num_steps = np.minimum(FLAGS.num_steps, len(node_ids))
-
- xyt = b.to_actual_xyt_vec(b.task.nodes[node_ids])
- xyt_diff = xyt[1:,:] - xyt[:-1:,:]
- xyt_diff[:,2] = np.mod(xyt_diff[:,2], 4)
- ind = np.where(xyt_diff[:,2] == 3)[0]
- xyt_diff[ind, 2] = -1
- xyt_diff = np.expand_dims(xyt_diff, axis=1)
- to_cat = [xyt_diff*_ for _ in f]
- perturbs_all = np.concatenate(to_cat, axis=1)
- perturbs_all = np.concatenate([perturbs_all, np.zeros_like(perturbs_all[:,:,:1])], axis=2)
- node_ids_all = np.expand_dims(node_ids, axis=1)*1
- node_ids_all = np.concatenate([node_ids_all for _ in f], axis=1)
- node_ids_all = np.reshape(node_ids_all[:-1,:], -1)
- perturbs_all = np.reshape(perturbs_all, [-1, 4])
- imgs = b.render_nodes(b.task.nodes[node_ids_all,:], perturb=perturbs_all)
-
- # Get action at each node.
- actions = []
- _, action_to_nodes = b.get_feasible_actions(node_ids)
- for j in range(num_steps-1):
- action_to_node = action_to_nodes[j]
- node_to_action = dict(zip(action_to_node.values(), action_to_node.keys()))
- actions.append(node_to_action[node_ids[j+1]])
-
- def init_fn():
- return fig,
- gt_dist_to_goal = []
-
- # Render trajectories.
- def worker(j):
- # Plot the image.
- step_number = j/(samples_per_action + wait_at_action)
- img = imgs[j]; ax = axes[0]; ax.clear(); ax.set_axis_off();
- img = img.astype(np.uint8); ax.imshow(img);
- tt = ax.set_title(
- "First Person View\n" +
- "Top corners show diagnostics (distance, agents' action) not input to agent.",
- fontsize=12)
- plt.setp(tt, color='white')
-
- # Distance to goal.
- t = 'Dist to Goal:\n{:2d} steps'.format(int(dt['all_d_at_t'][i, step_number]))
- t = ax.text(0.01, 0.99, t,
- horizontalalignment='left',
- verticalalignment='top',
- fontsize=20, color='red',
- transform=ax.transAxes, alpha=1.0)
- t.set_bbox(dict(color='white', alpha=0.85, pad=-0.1))
-
- # Action to take.
- action_latex = ['$\odot$ ', '$\curvearrowright$ ', '$\curvearrowleft$ ', r'$\Uparrow$ ']
- t = ax.text(0.99, 0.99, action_latex[actions[step_number]],
- horizontalalignment='right',
- verticalalignment='top',
- fontsize=40, color='green',
- transform=ax.transAxes, alpha=1.0)
- t.set_bbox(dict(color='white', alpha=0.85, pad=-0.1))
-
-
- # Plot the map top view.
- ax = axes[-1]
- if j == 0:
- # Plot the map
- locs = dt['all_locs'][i,:num_steps,:]
- goal_loc = dt['all_goal_locs'][i,:,:]
- xymin = np.minimum(np.min(goal_loc, axis=0), np.min(locs, axis=0))
- xymax = np.maximum(np.max(goal_loc, axis=0), np.max(locs, axis=0))
- xy1 = (xymax+xymin)/2. - 0.7*np.maximum(np.max(xymax-xymin), 24)
- xy2 = (xymax+xymin)/2. + 0.7*np.maximum(np.max(xymax-xymin), 24)
-
- ax.set_axis_on()
- ax.patch.set_facecolor((0.333, 0.333, 0.333))
- ax.set_xticks([]); ax.set_yticks([]);
- ax.imshow(orig_maps, origin='lower', vmin=-1.0, vmax=2.0)
- ax.plot(goal_loc[:,0], goal_loc[:,1], 'g*', markersize=12)
-
- locs = dt['all_locs'][i,:1,:]
- ax.plot(locs[:,0], locs[:,1], 'b.', markersize=12)
-
- ax.set_xlim([xy1[0], xy2[0]])
- ax.set_ylim([xy1[1], xy2[1]])
-
- locs = dt['all_locs'][i,step_number,:]
- locs = np.expand_dims(locs, axis=0)
- ax.plot(locs[:,0], locs[:,1], 'r.', alpha=1.0, linewidth=0, markersize=4)
- tt = ax.set_title('Trajectory in topview', fontsize=14)
- plt.setp(tt, color='white')
- return fig,
-
- line_ani = animation.FuncAnimation(fig, worker,
- (num_steps-1)*(wait_at_action+samples_per_action),
- interval=500, blit=True, init_func=init_fn)
- tmp_file_name = 'tmp.mp4'
- line_ani.save(tmp_file_name, writer=writer, savefig_kwargs={'facecolor':'black'})
- out_file_name = os.path.join(out_dir, 'vis_{:04d}.mp4'.format(i))
- print(out_file_name)
-
- if fu.exists(out_file_name):
- gfile.Remove(out_file_name)
- gfile.Copy(tmp_file_name, out_file_name)
- gfile.Remove(tmp_file_name)
- plt.close(fig)
-
-def plot_trajectory(dt, hardness, orig_maps, out_dir):
- out_dir = os.path.join(out_dir, FLAGS.config_name+_get_suffix_str(),
- FLAGS.imset)
- fu.makedirs(out_dir)
- out_file = os.path.join(out_dir, 'all_locs_at_t.pkl')
- dt['hardness'] = hardness
- utils.save_variables(out_file, dt.values(), dt.keys(), overwrite=True)
-
- #Plot trajectories onto the maps
- plt.set_cmap('gray')
- for i in range(4000):
- goal_loc = dt['all_goal_locs'][i, :, :]
- locs = np.concatenate((dt['all_locs'][i,:,:],
- dt['all_locs'][i,:,:]), axis=0)
- xymin = np.minimum(np.min(goal_loc, axis=0), np.min(locs, axis=0))
- xymax = np.maximum(np.max(goal_loc, axis=0), np.max(locs, axis=0))
- xy1 = (xymax+xymin)/2. - 1.*np.maximum(np.max(xymax-xymin), 24)
- xy2 = (xymax+xymin)/2. + 1.*np.maximum(np.max(xymax-xymin), 24)
-
- fig, ax = utils.tight_imshow_figure(plt, figsize=(6,6))
- ax.set_axis_on()
- ax.patch.set_facecolor((0.333, 0.333, 0.333))
- ax.set_xticks([])
- ax.set_yticks([])
-
- all_locs = dt['all_locs'][i,:,:]*1
- uniq = np.where(np.any(all_locs[1:,:] != all_locs[:-1,:], axis=1))[0]+1
- uniq = np.sort(uniq).tolist()
- uniq.insert(0,0)
- uniq = np.array(uniq)
- all_locs = all_locs[uniq, :]
-
- ax.plot(dt['all_locs'][i, 0, 0],
- dt['all_locs'][i, 0, 1], 'b.', markersize=24)
- ax.plot(dt['all_goal_locs'][i, 0, 0],
- dt['all_goal_locs'][i, 0, 1], 'g*', markersize=19)
- ax.plot(all_locs[:,0], all_locs[:,1], 'r', alpha=0.4, linewidth=2)
- ax.scatter(all_locs[:,0], all_locs[:,1],
- c=5+np.arange(all_locs.shape[0])*1./all_locs.shape[0],
- cmap='Reds', s=30, linewidth=0)
- ax.imshow(orig_maps, origin='lower', vmin=-1.0, vmax=2.0, aspect='equal')
- ax.set_xlim([xy1[0], xy2[0]])
- ax.set_ylim([xy1[1], xy2[1]])
-
- file_name = os.path.join(out_dir, 'trajectory_{:04d}.png'.format(i))
- print(file_name)
- with fu.fopen(file_name, 'w') as f:
- plt.savefig(f)
- plt.close(fig)
-
-
-def main(_):
- a = _load_trajectory()
- h_dists, gt_dists, orig_maps = _compute_hardness()
- hardness = 1.-h_dists*1./ gt_dists
-
- if FLAGS.top_view:
- plot_trajectory(a, hardness, orig_maps, out_dir=FLAGS.out_dir)
-
- if FLAGS.first_person:
- plot_trajectory_first_person(a, orig_maps, out_dir=FLAGS.out_dir)
-
-if __name__ == '__main__':
- app.run()
diff --git a/research/cognitive_mapping_and_planning/scripts/script_preprocess_annoations_S3DIS.py b/research/cognitive_mapping_and_planning/scripts/script_preprocess_annoations_S3DIS.py
deleted file mode 100644
index 58f32d121acf4c638625079907b02161e808af68..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/scripts/script_preprocess_annoations_S3DIS.py
+++ /dev/null
@@ -1,197 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import os
-import glob
-import numpy as np
-import logging
-import cPickle
-from datasets import nav_env
-from datasets import factory
-from src import utils
-from src import map_utils as mu
-
-logging.basicConfig(level=logging.INFO)
-DATA_DIR = 'data/stanford_building_parser_dataset_raw/'
-
-mkdir_if_missing = utils.mkdir_if_missing
-save_variables = utils.save_variables
-
-def _get_semantic_maps(building_name, transform, map_, flip, cats):
- rooms = get_room_in_building(building_name)
- maps = []
- for cat in cats:
- maps.append(np.zeros((map_.size[1], map_.size[0])))
-
- for r in rooms:
- room = load_room(building_name, r, category_list=cats)
- classes = room['class_id']
- for i, cat in enumerate(cats):
- c_ind = cats.index(cat)
- ind = [_ for _, c in enumerate(classes) if c == c_ind]
- if len(ind) > 0:
- vs = [room['vertexs'][x]*1 for x in ind]
- vs = np.concatenate(vs, axis=0)
- if transform:
- vs = np.array([vs[:,1], vs[:,0], vs[:,2]]).T
- vs[:,0] = -vs[:,0]
- vs[:,1] += 4.20
- vs[:,0] += 6.20
- vs = vs*100.
- if flip:
- vs[:,1] = -vs[:,1]
- maps[i] = maps[i] + \
- mu._project_to_map(map_, vs, ignore_points_outside_map=True)
- return maps
-
-def _map_building_name(building_name):
- b = int(building_name.split('_')[0][4])
- out_name = 'Area_{:d}'.format(b)
- if b == 5:
- if int(building_name.split('_')[0][5]) == 1:
- transform = True
- else:
- transform = False
- else:
- transform = False
- return out_name, transform
-
-def get_categories():
- cats = ['beam', 'board', 'bookcase', 'ceiling', 'chair', 'clutter', 'column',
- 'door', 'floor', 'sofa', 'table', 'wall', 'window']
- return cats
-
-def _write_map_files(b_in, b_out, transform):
- cats = get_categories()
-
- env = utils.Foo(padding=10, resolution=5, num_point_threshold=2,
- valid_min=-10, valid_max=200, n_samples_per_face=200)
- robot = utils.Foo(radius=15, base=10, height=140, sensor_height=120,
- camera_elevation_degree=-15)
-
- building_loader = factory.get_dataset('sbpd')
- for flip in [False, True]:
- b = nav_env.Building(b_out, robot, env, flip=flip,
- building_loader=building_loader)
- logging.info("building_in: %s, building_out: %s, transform: %d", b_in,
- b_out, transform)
- maps = _get_semantic_maps(b_in, transform, b.map, flip, cats)
- maps = np.transpose(np.array(maps), axes=[1,2,0])
-
- # Load file from the cache.
- file_name = '{:s}_{:d}_{:d}_{:d}_{:d}_{:d}_{:d}.pkl'
- file_name = file_name.format(b.building_name, b.map.size[0], b.map.size[1],
- b.map.origin[0], b.map.origin[1],
- b.map.resolution, flip)
- out_file = os.path.join(DATA_DIR, 'processing', 'class-maps', file_name)
- logging.info('Writing semantic maps to %s.', out_file)
- save_variables(out_file, [maps, cats], ['maps', 'cats'], overwrite=True)
-
-def _transform_area5b(room_dimension):
- for a in room_dimension.keys():
- r = room_dimension[a]*1
- r[[0,1,3,4]] = r[[1,0,4,3]]
- r[[0,3]] = -r[[3,0]]
- r[[1,4]] += 4.20
- r[[0,3]] += 6.20
- room_dimension[a] = r
- return room_dimension
-
-def collect_room(building_name, room_name):
- room_dir = os.path.join(DATA_DIR, 'Stanford3dDataset_v1.2', building_name,
- room_name, 'Annotations')
- files = glob.glob1(room_dir, '*.txt')
- files = sorted(files, key=lambda s: s.lower())
- vertexs = []; colors = [];
- for f in files:
- file_name = os.path.join(room_dir, f)
- logging.info(' %s', file_name)
- a = np.loadtxt(file_name)
- vertex = a[:,:3]*1.
- color = a[:,3:]*1
- color = color.astype(np.uint8)
- vertexs.append(vertex)
- colors.append(color)
- files = [f.split('.')[0] for f in files]
- out = {'vertexs': vertexs, 'colors': colors, 'names': files}
- return out
-
-def load_room(building_name, room_name, category_list=None):
- room = collect_room(building_name, room_name)
- room['building_name'] = building_name
- room['room_name'] = room_name
- instance_id = range(len(room['names']))
- room['instance_id'] = instance_id
- if category_list is not None:
- name = [r.split('_')[0] for r in room['names']]
- class_id = []
- for n in name:
- if n in category_list:
- class_id.append(category_list.index(n))
- else:
- class_id.append(len(category_list))
- room['class_id'] = class_id
- room['category_list'] = category_list
- return room
-
-def get_room_in_building(building_name):
- building_dir = os.path.join(DATA_DIR, 'Stanford3dDataset_v1.2', building_name)
- rn = os.listdir(building_dir)
- rn = [x for x in rn if os.path.isdir(os.path.join(building_dir, x))]
- rn = sorted(rn, key=lambda s: s.lower())
- return rn
-
-def write_room_dimensions(b_in, b_out, transform):
- rooms = get_room_in_building(b_in)
- room_dimension = {}
- for r in rooms:
- room = load_room(b_in, r, category_list=None)
- vertex = np.concatenate(room['vertexs'], axis=0)
- room_dimension[r] = np.concatenate((np.min(vertex, axis=0), np.max(vertex, axis=0)), axis=0)
- if transform == 1:
- room_dimension = _transform_area5b(room_dimension)
-
- out_file = os.path.join(DATA_DIR, 'processing', 'room-dimension', b_out+'.pkl')
- save_variables(out_file, [room_dimension], ['room_dimension'], overwrite=True)
-
-def write_room_dimensions_all(I):
- mkdir_if_missing(os.path.join(DATA_DIR, 'processing', 'room-dimension'))
- bs_in = ['Area_1', 'Area_2', 'Area_3', 'Area_4', 'Area_5', 'Area_5', 'Area_6']
- bs_out = ['area1', 'area2', 'area3', 'area4', 'area5a', 'area5b', 'area6']
- transforms = [0, 0, 0, 0, 0, 1, 0]
-
- for i in I:
- b_in = bs_in[i]
- b_out = bs_out[i]
- t = transforms[i]
- write_room_dimensions(b_in, b_out, t)
-
-def write_class_maps_all(I):
- mkdir_if_missing(os.path.join(DATA_DIR, 'processing', 'class-maps'))
- bs_in = ['Area_1', 'Area_2', 'Area_3', 'Area_4', 'Area_5', 'Area_5', 'Area_6']
- bs_out = ['area1', 'area2', 'area3', 'area4', 'area5a', 'area5b', 'area6']
- transforms = [0, 0, 0, 0, 0, 1, 0]
-
- for i in I:
- b_in = bs_in[i]
- b_out = bs_out[i]
- t = transforms[i]
- _write_map_files(b_in, b_out, t)
-
-
-if __name__ == '__main__':
- write_room_dimensions_all([0, 2, 3, 4, 5, 6])
- write_class_maps_all([0, 2, 3, 4, 5, 6])
-
diff --git a/research/cognitive_mapping_and_planning/scripts/script_preprocess_annoations_S3DIS.sh b/research/cognitive_mapping_and_planning/scripts/script_preprocess_annoations_S3DIS.sh
deleted file mode 100644
index 1384fabe69259ccc514a14d62aee358d1909bffb..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/scripts/script_preprocess_annoations_S3DIS.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-cd data/stanford_building_parser_dataset_raw
-unzip Stanford3dDataset_v1.2.zip
-cd ../../
-PYOPENGL_PLATFORM=egl PYTHONPATH='.' python scripts/script_preprocess_annoations_S3DIS.py
-
-mv data/stanford_building_parser_dataset_raw/processing/room-dimension data/stanford_building_parser_dataset/.
-mv data/stanford_building_parser_dataset_raw/processing/class-maps data/stanford_building_parser_dataset/.
-
-echo "You may now delete data/stanford_building_parser_dataset_raw if needed."
diff --git a/research/cognitive_mapping_and_planning/scripts/script_preprocess_meshes_S3DIS.sh b/research/cognitive_mapping_and_planning/scripts/script_preprocess_meshes_S3DIS.sh
deleted file mode 100644
index 557a4dde611d42e71d71dd1589abf96f55e6eec6..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/scripts/script_preprocess_meshes_S3DIS.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-mkdir -p data/stanford_building_parser_dataset
-mkdir -p data/stanford_building_parser_dataset/mesh
-cd data/stanford_building_parser_dataset_raw
-
-# Untar the files and extract the meshes.
-for t in "1" "3" "4" "5a" "5b" "6"; do
- tar -xf area_"$t"_noXYZ.tar area_$t/3d/rgb_textures
- mv area_$t/3d/rgb_textures ../stanford_building_parser_dataset/mesh/area$t
- rmdir area_$t/3d
- rmdir area_$t
-done
-
-cd ../../
-
-# Preprocess meshes to remove the group and chunk information.
-cd data/stanford_building_parser_dataset/
-for t in "1" "3" "4" "5a" "5b" "6"; do
- obj_name=`ls mesh/area$t/*.obj`
- cp $obj_name "$obj_name".bck
- cat $obj_name.bck | grep -v '^g' | grep -v '^o' > $obj_name
-done
-cd ../../
diff --git a/research/cognitive_mapping_and_planning/scripts/script_test_pretrained_models.sh b/research/cognitive_mapping_and_planning/scripts/script_test_pretrained_models.sh
deleted file mode 100644
index a4299fff5346afb53783a61de5c3e84f102a6304..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/scripts/script_test_pretrained_models.sh
+++ /dev/null
@@ -1,63 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-# Test CMP models.
-CUDA_VISIBLE_DEVICES=0 LD_LIBRARY_PATH=/opt/cuda-8.0/lib64:/opt/cudnnv51/lib64 PYTHONPATH='.' PYOPENGL_PLATFORM=egl \
- python scripts/script_nav_agent_release.py --config_name cmp.lmap_Msc.clip5.sbpd_d_r2r+bench_test \
- --logdir output/cmp.lmap_Msc.clip5.sbpd_d_r2r
-
-CUDA_VISIBLE_DEVICES=0 LD_LIBRARY_PATH=/opt/cuda-8.0/lib64:/opt/cudnnv51/lib64 PYTHONPATH='.' PYOPENGL_PLATFORM=egl \
- python scripts/script_nav_agent_release.py --config_name cmp.lmap_Msc.clip5.sbpd_rgb_r2r+bench_test \
- --logdir output/cmp.lmap_Msc.clip5.sbpd_rgb_r2r
-
-CUDA_VISIBLE_DEVICES=0 LD_LIBRARY_PATH=/opt/cuda-8.0/lib64:/opt/cudnnv51/lib64 PYTHONPATH='.' PYOPENGL_PLATFORM=egl \
- python scripts/script_nav_agent_release.py --config_name cmp.lmap_Msc.clip5.sbpd_d_ST+bench_test \
- --logdir output/cmp.lmap_Msc.clip5.sbpd_d_ST
-
-CUDA_VISIBLE_DEVICES=0 LD_LIBRARY_PATH=/opt/cuda-8.0/lib64:/opt/cudnnv51/lib64 PYTHONPATH='.' PYOPENGL_PLATFORM=egl \
- python scripts/script_nav_agent_release.py --config_name cmp.lmap_Msc.clip5.sbpd_rgb_ST+bench_test \
- --logdir output/cmp.lmap_Msc.clip5.sbpd_rgb_ST
-
-CUDA_VISIBLE_DEVICES=0 LD_LIBRARY_PATH=/opt/cuda-8.0/lib64:/opt/cudnnv51/lib64 PYTHONPATH='.' PYOPENGL_PLATFORM=egl \
- python scripts/script_nav_agent_release.py --config_name cmp.lmap_Msc.clip5.sbpd_d_r2r_h0_64_80+bench_test \
- --logdir output/cmp.lmap_Msc.clip5.sbpd_d_r2r_h0_64_80
-
-# Test LSTM baseline models.
-CUDA_VISIBLE_DEVICES=0 LD_LIBRARY_PATH=/opt/cuda-8.0/lib64:/opt/cudnnv51/lib64 PYTHONPATH='.' PYOPENGL_PLATFORM=egl \
- python scripts/script_nav_agent_release.py --config_name bl.v2.noclip.sbpd_d_r2r+bench_test \
- --logdir output/bl.v2.noclip.sbpd_d_r2r
-
-CUDA_VISIBLE_DEVICES=0 LD_LIBRARY_PATH=/opt/cuda-8.0/lib64:/opt/cudnnv51/lib64 PYTHONPATH='.' PYOPENGL_PLATFORM=egl \
- python scripts/script_nav_agent_release.py --config_name bl.v2.noclip.sbpd_rgb_r2r+bench_test \
- --logdir output/bl.v2.noclip.sbpd_rgb_r2r
-
-CUDA_VISIBLE_DEVICES=0 LD_LIBRARY_PATH=/opt/cuda-8.0/lib64:/opt/cudnnv51/lib64 PYTHONPATH='.' PYOPENGL_PLATFORM=egl \
- python scripts/script_nav_agent_release.py --config_name bl.v2.noclip.sbpd_d_ST+bench_test \
- --logdir output/bl.v2.noclip.sbpd_d_ST
-
-CUDA_VISIBLE_DEVICES=0 LD_LIBRARY_PATH=/opt/cuda-8.0/lib64:/opt/cudnnv51/lib64 PYTHONPATH='.' PYOPENGL_PLATFORM=egl \
- python scripts/script_nav_agent_release.py --config_name bl.v2.noclip.sbpd_rgb_ST+bench_test \
- --logdir output/bl.v2.noclip.sbpd_rgb_ST
-
-CUDA_VISIBLE_DEVICES=0 LD_LIBRARY_PATH=/opt/cuda-8.0/lib64:/opt/cudnnv51/lib64 PYTHONPATH='.' PYOPENGL_PLATFORM=egl \
- python scripts/script_nav_agent_release.py --config_name bl.v2.noclip.sbpd_d_r2r_h0_64_80+bench_test \
- --logdir output/bl.v2.noclip.sbpd_d_r2r_h0_64_80
-
-# Visualize test trajectories in top view.
-# CUDA_VISIBLE_DEVICES=0 LD_LIBRARY_PATH=/opt/cuda-8.0/lib64:/opt/cudnnv51/lib64 PYTHONPATH='.' PYOPENGL_PLATFORM=egl \
-# python scripts/script_plot_trajectory.py \
-# --first_person --num_steps 40 \
-# --config_name cmp.lmap_Msc.clip5.sbpd_d_r2r \
-# --imset test --alsologtostderr
diff --git a/research/cognitive_mapping_and_planning/src/__init__.py b/research/cognitive_mapping_and_planning/src/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/cognitive_mapping_and_planning/src/depth_utils.py b/research/cognitive_mapping_and_planning/src/depth_utils.py
deleted file mode 100644
index 35f14fc7c37fffb2a408decede11e378867a2834..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/src/depth_utils.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Utilities for processing depth images.
-"""
-import numpy as np
-import src.rotation_utils as ru
-import src.utils as utils
-
-def get_camera_matrix(width, height, fov):
- """Returns a camera matrix from image size and fov."""
- xc = (width-1.) / 2.
- zc = (height-1.) / 2.
- f = (width / 2.) / np.tan(np.deg2rad(fov / 2.))
- camera_matrix = utils.Foo(xc=xc, zc=zc, f=f)
- return camera_matrix
-
-def get_point_cloud_from_z(Y, camera_matrix):
- """Projects the depth image Y into a 3D point cloud.
- Inputs:
- Y is ...xHxW
- camera_matrix
- Outputs:
- X is positive going right
- Y is positive into the image
- Z is positive up in the image
- XYZ is ...xHxWx3
- """
- x, z = np.meshgrid(np.arange(Y.shape[-1]),
- np.arange(Y.shape[-2]-1, -1, -1))
- for i in range(Y.ndim-2):
- x = np.expand_dims(x, axis=0)
- z = np.expand_dims(z, axis=0)
- X = (x-camera_matrix.xc) * Y / camera_matrix.f
- Z = (z-camera_matrix.zc) * Y / camera_matrix.f
- XYZ = np.concatenate((X[...,np.newaxis], Y[...,np.newaxis],
- Z[...,np.newaxis]), axis=X.ndim)
- return XYZ
-
-def make_geocentric(XYZ, sensor_height, camera_elevation_degree):
- """Transforms the point cloud into geocentric coordinate frame.
- Input:
- XYZ : ...x3
- sensor_height : height of the sensor
- camera_elevation_degree : camera elevation to rectify.
- Output:
- XYZ : ...x3
- """
- R = ru.get_r_matrix([1.,0.,0.], angle=np.deg2rad(camera_elevation_degree))
- XYZ = np.matmul(XYZ.reshape(-1,3), R.T).reshape(XYZ.shape)
- XYZ[...,2] = XYZ[...,2] + sensor_height
- return XYZ
-
-def bin_points(XYZ_cms, map_size, z_bins, xy_resolution):
- """Bins points into xy-z bins
- XYZ_cms is ... x H x W x3
- Outputs is ... x map_size x map_size x (len(z_bins)+1)
- """
- sh = XYZ_cms.shape
- XYZ_cms = XYZ_cms.reshape([-1, sh[-3], sh[-2], sh[-1]])
- n_z_bins = len(z_bins)+1
- map_center = (map_size-1.)/2.
- counts = []
- isvalids = []
- for XYZ_cm in XYZ_cms:
- isnotnan = np.logical_not(np.isnan(XYZ_cm[:,:,0]))
- X_bin = np.round(XYZ_cm[:,:,0] / xy_resolution + map_center).astype(np.int32)
- Y_bin = np.round(XYZ_cm[:,:,1] / xy_resolution + map_center).astype(np.int32)
- Z_bin = np.digitize(XYZ_cm[:,:,2], bins=z_bins).astype(np.int32)
-
- isvalid = np.array([X_bin >= 0, X_bin < map_size, Y_bin >= 0, Y_bin < map_size,
- Z_bin >= 0, Z_bin < n_z_bins, isnotnan])
- isvalid = np.all(isvalid, axis=0)
-
- ind = (Y_bin * map_size + X_bin) * n_z_bins + Z_bin
- ind[np.logical_not(isvalid)] = 0
- count = np.bincount(ind.ravel(), isvalid.ravel().astype(np.int32),
- minlength=map_size*map_size*n_z_bins)
- count = np.reshape(count, [map_size, map_size, n_z_bins])
- counts.append(count)
- isvalids.append(isvalid)
- counts = np.array(counts).reshape(list(sh[:-3]) + [map_size, map_size, n_z_bins])
- isvalids = np.array(isvalids).reshape(list(sh[:-3]) + [sh[-3], sh[-2], 1])
- return counts, isvalids
diff --git a/research/cognitive_mapping_and_planning/src/file_utils.py b/research/cognitive_mapping_and_planning/src/file_utils.py
deleted file mode 100644
index b386236ca6e04c9fa1e452b6ad3e70c6ab9bb88a..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/src/file_utils.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Utilities for manipulating files.
-"""
-import os
-import numpy as np
-import PIL
-from tensorflow.python.platform import gfile
-import cv2
-
-exists = lambda path: gfile.Exists(path)
-fopen = lambda path, mode: gfile.Open(path, mode)
-makedirs = lambda path: gfile.MakeDirs(path)
-listdir = lambda path: gfile.ListDir(path)
-copyfile = lambda a, b, o: gfile.Copy(a,b,o)
-
-def write_image(image_path, rgb):
- ext = os.path.splitext(image_path)[1]
- with gfile.GFile(image_path, 'w') as f:
- img_str = cv2.imencode(ext, rgb[:,:,::-1])[1].tostring()
- f.write(img_str)
-
-def read_image(image_path, type='rgb'):
- with fopen(image_path, 'r') as f:
- I = PIL.Image.open(f)
- II = np.array(I)
- if type == 'rgb':
- II = II[:,:,:3]
- return II
diff --git a/research/cognitive_mapping_and_planning/src/graph_utils.py b/research/cognitive_mapping_and_planning/src/graph_utils.py
deleted file mode 100644
index cd99fd22a2f630438f31eecd7fbfece2c6008ead..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/src/graph_utils.py
+++ /dev/null
@@ -1,552 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Various function to manipulate graphs for computing distances.
-"""
-import skimage.morphology
-import numpy as np
-import networkx as nx
-import itertools
-import logging
-from datasets.nav_env import get_path_ids
-import graph_tool as gt
-import graph_tool.topology
-import graph_tool.generation
-import src.utils as utils
-
-# Compute shortest path from all nodes to or from all source nodes
-def get_distance_node_list(gtG, source_nodes, direction, weights=None):
- gtG_ = gt.Graph(gtG)
- v = gtG_.add_vertex()
-
- if weights is not None:
- weights = gtG_.edge_properties[weights]
-
- for s in source_nodes:
- e = gtG_.add_edge(s, int(v))
- if weights is not None:
- weights[e] = 0.
-
- if direction == 'to':
- dist = gt.topology.shortest_distance(
- gt.GraphView(gtG_, reversed=True), source=gtG_.vertex(int(v)),
- target=None, weights=weights)
- elif direction == 'from':
- dist = gt.topology.shortest_distance(
- gt.GraphView(gtG_, reversed=False), source=gtG_.vertex(int(v)),
- target=None, weights=weights)
- dist = np.array(dist.get_array())
- dist = dist[:-1]
- if weights is None:
- dist = dist-1
- return dist
-
-# Functions for semantically labelling nodes in the traversal graph.
-def generate_lattice(sz_x, sz_y):
- """Generates a lattice with sz_x vertices along x and sz_y vertices along y
- direction Each of these vertices is step_size distance apart. Origin is at
- (0,0). """
- g = gt.generation.lattice([sz_x, sz_y])
- x, y = np.meshgrid(np.arange(sz_x), np.arange(sz_y))
- x = np.reshape(x, [-1,1]); y = np.reshape(y, [-1,1]);
- nodes = np.concatenate((x,y), axis=1)
- return g, nodes
-
-def add_diagonal_edges(g, nodes, sz_x, sz_y, edge_len):
- offset = [sz_x+1, sz_x-1]
- for o in offset:
- s = np.arange(nodes.shape[0]-o-1)
- t = s + o
- ind = np.all(np.abs(nodes[s,:] - nodes[t,:]) == np.array([[1,1]]), axis=1)
- s = s[ind][:,np.newaxis]
- t = t[ind][:,np.newaxis]
- st = np.concatenate((s,t), axis=1)
- for i in range(st.shape[0]):
- e = g.add_edge(st[i,0], st[i,1], add_missing=False)
- g.ep['wts'][e] = edge_len
-
-def convert_traversible_to_graph(traversible, ff_cost=1., fo_cost=1.,
- oo_cost=1., connectivity=4):
- assert(connectivity == 4 or connectivity == 8)
-
- sz_x = traversible.shape[1]
- sz_y = traversible.shape[0]
- g, nodes = generate_lattice(sz_x, sz_y)
-
- # Assign costs.
- edge_wts = g.new_edge_property('float')
- g.edge_properties['wts'] = edge_wts
- wts = np.ones(g.num_edges(), dtype=np.float32)
- edge_wts.get_array()[:] = wts
-
- if connectivity == 8:
- add_diagonal_edges(g, nodes, sz_x, sz_y, np.sqrt(2.))
-
- se = np.array([[int(e.source()), int(e.target())] for e in g.edges()])
- s_xy = nodes[se[:,0]]
- t_xy = nodes[se[:,1]]
- s_t = np.ravel_multi_index((s_xy[:,1], s_xy[:,0]), traversible.shape)
- t_t = np.ravel_multi_index((t_xy[:,1], t_xy[:,0]), traversible.shape)
- s_t = traversible.ravel()[s_t]
- t_t = traversible.ravel()[t_t]
-
- wts = np.zeros(g.num_edges(), dtype=np.float32)
- wts[np.logical_and(s_t == True, t_t == True)] = ff_cost
- wts[np.logical_and(s_t == False, t_t == False)] = oo_cost
- wts[np.logical_xor(s_t, t_t)] = fo_cost
-
- edge_wts = g.edge_properties['wts']
- for i, e in enumerate(g.edges()):
- edge_wts[e] = edge_wts[e] * wts[i]
- # d = edge_wts.get_array()*1.
- # edge_wts.get_array()[:] = d*wts
- return g, nodes
-
-def label_nodes_with_class(nodes_xyt, class_maps, pix):
- """
- Returns:
- class_maps__: one-hot class_map for each class.
- node_class_label: one-hot class_map for each class, nodes_xyt.shape[0] x n_classes
- """
- # Assign each pixel to a node.
- selem = skimage.morphology.disk(pix)
- class_maps_ = class_maps*1.
- for i in range(class_maps.shape[2]):
- class_maps_[:,:,i] = skimage.morphology.dilation(class_maps[:,:,i]*1, selem)
- class_maps__ = np.argmax(class_maps_, axis=2)
- class_maps__[np.max(class_maps_, axis=2) == 0] = -1
-
- # For each node pick out the label from this class map.
- x = np.round(nodes_xyt[:,[0]]).astype(np.int32)
- y = np.round(nodes_xyt[:,[1]]).astype(np.int32)
- ind = np.ravel_multi_index((y,x), class_maps__.shape)
- node_class_label = class_maps__.ravel()[ind][:,0]
-
- # Convert to one hot versions.
- class_maps_one_hot = np.zeros(class_maps.shape, dtype=np.bool)
- node_class_label_one_hot = np.zeros((node_class_label.shape[0], class_maps.shape[2]), dtype=np.bool)
- for i in range(class_maps.shape[2]):
- class_maps_one_hot[:,:,i] = class_maps__ == i
- node_class_label_one_hot[:,i] = node_class_label == i
- return class_maps_one_hot, node_class_label_one_hot
-
-def label_nodes_with_class_geodesic(nodes_xyt, class_maps, pix, traversible,
- ff_cost=1., fo_cost=1., oo_cost=1.,
- connectivity=4):
- """Labels nodes in nodes_xyt with class labels using geodesic distance as
- defined by traversible from class_maps.
- Inputs:
- nodes_xyt
- class_maps: counts for each class.
- pix: distance threshold to consider close enough to target.
- traversible: binary map of whether traversible or not.
- Output:
- labels: For each node in nodes_xyt returns a label of the class or -1 is
- unlabelled.
- """
- g, nodes = convert_traversible_to_graph(traversible, ff_cost=ff_cost,
- fo_cost=fo_cost, oo_cost=oo_cost,
- connectivity=connectivity)
-
- class_dist = np.zeros_like(class_maps*1.)
- n_classes = class_maps.shape[2]
- if False:
- # Assign each pixel to a class based on number of points.
- selem = skimage.morphology.disk(pix)
- class_maps_ = class_maps*1.
- class_maps__ = np.argmax(class_maps_, axis=2)
- class_maps__[np.max(class_maps_, axis=2) == 0] = -1
-
- # Label nodes with classes.
- for i in range(n_classes):
- # class_node_ids = np.where(class_maps__.ravel() == i)[0]
- class_node_ids = np.where(class_maps[:,:,i].ravel() > 0)[0]
- dist_i = get_distance_node_list(g, class_node_ids, 'to', weights='wts')
- class_dist[:,:,i] = np.reshape(dist_i, class_dist[:,:,i].shape)
- class_map_geodesic = (class_dist <= pix)
- class_map_geodesic = np.reshape(class_map_geodesic, [-1, n_classes])
-
- # For each node pick out the label from this class map.
- x = np.round(nodes_xyt[:,[0]]).astype(np.int32)
- y = np.round(nodes_xyt[:,[1]]).astype(np.int32)
- ind = np.ravel_multi_index((y,x), class_dist[:,:,0].shape)
- node_class_label = class_map_geodesic[ind[:,0],:]
- class_map_geodesic = class_dist <= pix
- return class_map_geodesic, node_class_label
-
-def _get_next_nodes_undirected(n, sc, n_ori):
- nodes_to_add = []
- nodes_to_validate = []
- (p, q, r) = n
- nodes_to_add.append((n, (p, q, r), 0))
- if n_ori == 4:
- for _ in [1, 2, 3, 4]:
- if _ == 1:
- v = (p - sc, q, r)
- elif _ == 2:
- v = (p + sc, q, r)
- elif _ == 3:
- v = (p, q - sc, r)
- elif _ == 4:
- v = (p, q + sc, r)
- nodes_to_validate.append((n, v, _))
- return nodes_to_add, nodes_to_validate
-
-def _get_next_nodes(n, sc, n_ori):
- nodes_to_add = []
- nodes_to_validate = []
- (p, q, r) = n
- for r_, a_ in zip([-1, 0, 1], [1, 0, 2]):
- nodes_to_add.append((n, (p, q, np.mod(r+r_, n_ori)), a_))
-
- if n_ori == 6:
- if r == 0:
- v = (p + sc, q, r)
- elif r == 1:
- v = (p + sc, q + sc, r)
- elif r == 2:
- v = (p, q + sc, r)
- elif r == 3:
- v = (p - sc, q, r)
- elif r == 4:
- v = (p - sc, q - sc, r)
- elif r == 5:
- v = (p, q - sc, r)
- elif n_ori == 4:
- if r == 0:
- v = (p + sc, q, r)
- elif r == 1:
- v = (p, q + sc, r)
- elif r == 2:
- v = (p - sc, q, r)
- elif r == 3:
- v = (p, q - sc, r)
- nodes_to_validate.append((n,v,3))
-
- return nodes_to_add, nodes_to_validate
-
-def generate_graph(valid_fn_vec=None, sc=1., n_ori=6,
- starting_location=(0, 0, 0), vis=False, directed=True):
- timer = utils.Timer()
- timer.tic()
- if directed: G = nx.DiGraph(directed=True)
- else: G = nx.Graph()
- G.add_node(starting_location)
- new_nodes = G.nodes()
- while len(new_nodes) != 0:
- nodes_to_add = []
- nodes_to_validate = []
- for n in new_nodes:
- if directed:
- na, nv = _get_next_nodes(n, sc, n_ori)
- else:
- na, nv = _get_next_nodes_undirected(n, sc, n_ori)
- nodes_to_add = nodes_to_add + na
- if valid_fn_vec is not None:
- nodes_to_validate = nodes_to_validate + nv
- else:
- node_to_add = nodes_to_add + nv
-
- # Validate nodes.
- vs = [_[1] for _ in nodes_to_validate]
- valids = valid_fn_vec(vs)
-
- for nva, valid in zip(nodes_to_validate, valids):
- if valid:
- nodes_to_add.append(nva)
-
- new_nodes = []
- for n,v,a in nodes_to_add:
- if not G.has_node(v):
- new_nodes.append(v)
- G.add_edge(n, v, action=a)
-
- timer.toc(average=True, log_at=1, log_str='src.graph_utils.generate_graph')
- return (G)
-
-def vis_G(G, ax, vertex_color='r', edge_color='b', r=None):
- if edge_color is not None:
- for e in G.edges():
- XYT = zip(*e)
- x = XYT[-3]
- y = XYT[-2]
- t = XYT[-1]
- if r is None or t[0] == r:
- ax.plot(x, y, edge_color)
- if vertex_color is not None:
- XYT = zip(*G.nodes())
- x = XYT[-3]
- y = XYT[-2]
- t = XYT[-1]
- ax.plot(x, y, vertex_color + '.')
-
-def convert_to_graph_tool(G):
- timer = utils.Timer()
- timer.tic()
- gtG = gt.Graph(directed=G.is_directed())
- gtG.ep['action'] = gtG.new_edge_property('int')
-
- nodes_list = G.nodes()
- nodes_array = np.array(nodes_list)
-
- nodes_id = np.zeros((nodes_array.shape[0],), dtype=np.int64)
-
- for i in range(nodes_array.shape[0]):
- v = gtG.add_vertex()
- nodes_id[i] = int(v)
-
- # d = {key: value for (key, value) in zip(nodes_list, nodes_id)}
- d = dict(itertools.izip(nodes_list, nodes_id))
-
- for src, dst, data in G.edges_iter(data=True):
- e = gtG.add_edge(d[src], d[dst])
- gtG.ep['action'][e] = data['action']
- nodes_to_id = d
- timer.toc(average=True, log_at=1, log_str='src.graph_utils.convert_to_graph_tool')
- return gtG, nodes_array, nodes_to_id
-
-
-def _rejection_sampling(rng, sampling_d, target_d, bins, hardness, M):
- bin_ind = np.digitize(hardness, bins)-1
- i = 0
- ratio = target_d[bin_ind] / (M*sampling_d[bin_ind])
- while i < ratio.size and rng.rand() > ratio[i]:
- i = i+1
- return i
-
-def heuristic_fn_vec(n1, n2, n_ori, step_size):
- # n1 is a vector and n2 is a single point.
- dx = (n1[:,0] - n2[0,0])/step_size
- dy = (n1[:,1] - n2[0,1])/step_size
- dt = n1[:,2] - n2[0,2]
- dt = np.mod(dt, n_ori)
- dt = np.minimum(dt, n_ori-dt)
-
- if n_ori == 6:
- if dx*dy > 0:
- d = np.maximum(np.abs(dx), np.abs(dy))
- else:
- d = np.abs(dy-dx)
- elif n_ori == 4:
- d = np.abs(dx) + np.abs(dy)
-
- return (d + dt).reshape((-1,1))
-
-def get_hardness_distribution(gtG, max_dist, min_dist, rng, trials, bins, nodes,
- n_ori, step_size):
- heuristic_fn = lambda node_ids, node_id: \
- heuristic_fn_vec(nodes[node_ids, :], nodes[[node_id], :], n_ori, step_size)
- num_nodes = gtG.num_vertices()
- gt_dists = []; h_dists = [];
- for i in range(trials):
- end_node_id = rng.choice(num_nodes)
- gt_dist = gt.topology.shortest_distance(gt.GraphView(gtG, reversed=True),
- source=gtG.vertex(end_node_id),
- target=None, max_dist=max_dist)
- gt_dist = np.array(gt_dist.get_array())
- ind = np.where(np.logical_and(gt_dist <= max_dist, gt_dist >= min_dist))[0]
- gt_dist = gt_dist[ind]
- h_dist = heuristic_fn(ind, end_node_id)[:,0]
- gt_dists.append(gt_dist)
- h_dists.append(h_dist)
- gt_dists = np.concatenate(gt_dists)
- h_dists = np.concatenate(h_dists)
- hardness = 1. - h_dists*1./gt_dists
- hist, _ = np.histogram(hardness, bins)
- hist = hist.astype(np.float64)
- hist = hist / np.sum(hist)
- return hist
-
-def rng_next_goal_rejection_sampling(start_node_ids, batch_size, gtG, rng,
- max_dist, min_dist, max_dist_to_compute,
- sampling_d, target_d,
- nodes, n_ori, step_size, bins, M):
- sample_start_nodes = start_node_ids is None
- dists = []; pred_maps = []; end_node_ids = []; start_node_ids_ = [];
- hardnesss = []; gt_dists = [];
- num_nodes = gtG.num_vertices()
- for i in range(batch_size):
- done = False
- while not done:
- if sample_start_nodes:
- start_node_id = rng.choice(num_nodes)
- else:
- start_node_id = start_node_ids[i]
-
- gt_dist = gt.topology.shortest_distance(
- gt.GraphView(gtG, reversed=False), source=start_node_id, target=None,
- max_dist=max_dist)
- gt_dist = np.array(gt_dist.get_array())
- ind = np.where(np.logical_and(gt_dist <= max_dist, gt_dist >= min_dist))[0]
- ind = rng.permutation(ind)
- gt_dist = gt_dist[ind]*1.
- h_dist = heuristic_fn_vec(nodes[ind, :], nodes[[start_node_id], :],
- n_ori, step_size)[:,0]
- hardness = 1. - h_dist / gt_dist
- sampled_ind = _rejection_sampling(rng, sampling_d, target_d, bins,
- hardness, M)
- if sampled_ind < ind.size:
- # print sampled_ind
- end_node_id = ind[sampled_ind]
- hardness = hardness[sampled_ind]
- gt_dist = gt_dist[sampled_ind]
- done = True
-
- # Compute distance from end node to all nodes, to return.
- dist, pred_map = gt.topology.shortest_distance(
- gt.GraphView(gtG, reversed=True), source=end_node_id, target=None,
- max_dist=max_dist_to_compute, pred_map=True)
- dist = np.array(dist.get_array())
- pred_map = np.array(pred_map.get_array())
-
- hardnesss.append(hardness); dists.append(dist); pred_maps.append(pred_map);
- start_node_ids_.append(start_node_id); end_node_ids.append(end_node_id);
- gt_dists.append(gt_dist);
- paths = None
- return start_node_ids_, end_node_ids, dists, pred_maps, paths, hardnesss, gt_dists
-
-
-def rng_next_goal(start_node_ids, batch_size, gtG, rng, max_dist,
- max_dist_to_compute, node_room_ids, nodes=None,
- compute_path=False, dists_from_start_node=None):
- # Compute the distance field from the starting location, and then pick a
- # destination in another room if possible otherwise anywhere outside this
- # room.
- dists = []; pred_maps = []; paths = []; end_node_ids = [];
- for i in range(batch_size):
- room_id = node_room_ids[start_node_ids[i]]
- # Compute distances.
- if dists_from_start_node == None:
- dist, pred_map = gt.topology.shortest_distance(
- gt.GraphView(gtG, reversed=False), source=gtG.vertex(start_node_ids[i]),
- target=None, max_dist=max_dist_to_compute, pred_map=True)
- dist = np.array(dist.get_array())
- else:
- dist = dists_from_start_node[i]
-
- # Randomly sample nodes which are within max_dist.
- near_ids = dist <= max_dist
- near_ids = near_ids[:, np.newaxis]
- # Check to see if there is a non-negative node which is close enough.
- non_same_room_ids = node_room_ids != room_id
- non_hallway_ids = node_room_ids != -1
- good1_ids = np.logical_and(near_ids, np.logical_and(non_same_room_ids, non_hallway_ids))
- good2_ids = np.logical_and(near_ids, non_hallway_ids)
- good3_ids = near_ids
- if np.any(good1_ids):
- end_node_id = rng.choice(np.where(good1_ids)[0])
- elif np.any(good2_ids):
- end_node_id = rng.choice(np.where(good2_ids)[0])
- elif np.any(good3_ids):
- end_node_id = rng.choice(np.where(good3_ids)[0])
- else:
- logging.error('Did not find any good nodes.')
-
- # Compute distance to this new goal for doing distance queries.
- dist, pred_map = gt.topology.shortest_distance(
- gt.GraphView(gtG, reversed=True), source=gtG.vertex(end_node_id),
- target=None, max_dist=max_dist_to_compute, pred_map=True)
- dist = np.array(dist.get_array())
- pred_map = np.array(pred_map.get_array())
-
- dists.append(dist)
- pred_maps.append(pred_map)
- end_node_ids.append(end_node_id)
-
- path = None
- if compute_path:
- path = get_path_ids(start_node_ids[i], end_node_ids[i], pred_map)
- paths.append(path)
-
- return start_node_ids, end_node_ids, dists, pred_maps, paths
-
-
-def rng_room_to_room(batch_size, gtG, rng, max_dist, max_dist_to_compute,
- node_room_ids, nodes=None, compute_path=False):
- # Sample one of the rooms, compute the distance field. Pick a destination in
- # another room if possible otherwise anywhere outside this room.
- dists = []; pred_maps = []; paths = []; start_node_ids = []; end_node_ids = [];
- room_ids = np.unique(node_room_ids[node_room_ids[:,0] >= 0, 0])
- for i in range(batch_size):
- room_id = rng.choice(room_ids)
- end_node_id = rng.choice(np.where(node_room_ids[:,0] == room_id)[0])
- end_node_ids.append(end_node_id)
-
- # Compute distances.
- dist, pred_map = gt.topology.shortest_distance(
- gt.GraphView(gtG, reversed=True), source=gtG.vertex(end_node_id),
- target=None, max_dist=max_dist_to_compute, pred_map=True)
- dist = np.array(dist.get_array())
- pred_map = np.array(pred_map.get_array())
- dists.append(dist)
- pred_maps.append(pred_map)
-
- # Randomly sample nodes which are within max_dist.
- near_ids = dist <= max_dist
- near_ids = near_ids[:, np.newaxis]
-
- # Check to see if there is a non-negative node which is close enough.
- non_same_room_ids = node_room_ids != room_id
- non_hallway_ids = node_room_ids != -1
- good1_ids = np.logical_and(near_ids, np.logical_and(non_same_room_ids, non_hallway_ids))
- good2_ids = np.logical_and(near_ids, non_hallway_ids)
- good3_ids = near_ids
- if np.any(good1_ids):
- start_node_id = rng.choice(np.where(good1_ids)[0])
- elif np.any(good2_ids):
- start_node_id = rng.choice(np.where(good2_ids)[0])
- elif np.any(good3_ids):
- start_node_id = rng.choice(np.where(good3_ids)[0])
- else:
- logging.error('Did not find any good nodes.')
-
- start_node_ids.append(start_node_id)
-
- path = None
- if compute_path:
- path = get_path_ids(start_node_ids[i], end_node_ids[i], pred_map)
- paths.append(path)
-
- return start_node_ids, end_node_ids, dists, pred_maps, paths
-
-
-def rng_target_dist_field(batch_size, gtG, rng, max_dist, max_dist_to_compute,
- nodes=None, compute_path=False):
- # Sample a single node, compute distance to all nodes less than max_dist,
- # sample nodes which are a particular distance away.
- dists = []; pred_maps = []; paths = []; start_node_ids = []
- end_node_ids = rng.choice(gtG.num_vertices(), size=(batch_size,),
- replace=False).tolist()
-
- for i in range(batch_size):
- dist, pred_map = gt.topology.shortest_distance(
- gt.GraphView(gtG, reversed=True), source=gtG.vertex(end_node_ids[i]),
- target=None, max_dist=max_dist_to_compute, pred_map=True)
- dist = np.array(dist.get_array())
- pred_map = np.array(pred_map.get_array())
- dists.append(dist)
- pred_maps.append(pred_map)
-
- # Randomly sample nodes which are withing max_dist
- near_ids = np.where(dist <= max_dist)[0]
- start_node_id = rng.choice(near_ids, size=(1,), replace=False)[0]
- start_node_ids.append(start_node_id)
-
- path = None
- if compute_path:
- path = get_path_ids(start_node_ids[i], end_node_ids[i], pred_map)
- paths.append(path)
-
- return start_node_ids, end_node_ids, dists, pred_maps, paths
diff --git a/research/cognitive_mapping_and_planning/src/map_utils.py b/research/cognitive_mapping_and_planning/src/map_utils.py
deleted file mode 100644
index 6756131a9eac161e7633ef089ed573e324f859e1..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/src/map_utils.py
+++ /dev/null
@@ -1,245 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Various function to compute the ground truth map for training etc.
-"""
-import copy
-import skimage.morphology
-import logging
-import numpy as np
-import scipy.ndimage
-import matplotlib.pyplot as plt
-import PIL
-
-import src.utils as utils
-import cv2
-
-def _get_xy_bounding_box(vertex, padding):
- """Returns the xy bounding box of the environment."""
- min_ = np.floor(np.min(vertex[:, :2], axis=0) - padding).astype(np.int)
- max_ = np.ceil(np.max(vertex[:, :2], axis=0) + padding).astype(np.int)
- return min_, max_
-
-def _project_to_map(map, vertex, wt=None, ignore_points_outside_map=False):
- """Projects points to map, returns how many points are present at each
- location."""
- num_points = np.zeros((map.size[1], map.size[0]))
- vertex_ = vertex[:, :2] - map.origin
- vertex_ = np.round(vertex_ / map.resolution).astype(np.int)
- if ignore_points_outside_map:
- good_ind = np.all(np.array([vertex_[:,1] >= 0, vertex_[:,1] < map.size[1],
- vertex_[:,0] >= 0, vertex_[:,0] < map.size[0]]),
- axis=0)
- vertex_ = vertex_[good_ind, :]
- if wt is not None:
- wt = wt[good_ind, :]
- if wt is None:
- np.add.at(num_points, (vertex_[:, 1], vertex_[:, 0]), 1)
- else:
- assert(wt.shape[0] == vertex.shape[0]), \
- 'number of weights should be same as vertices.'
- np.add.at(num_points, (vertex_[:, 1], vertex_[:, 0]), wt)
- return num_points
-
-def make_map(padding, resolution, vertex=None, sc=1.):
- """Returns a map structure."""
- min_, max_ = _get_xy_bounding_box(vertex*sc, padding=padding)
- sz = np.ceil((max_ - min_ + 1) / resolution).astype(np.int32)
- max_ = min_ + sz * resolution - 1
- map = utils.Foo(origin=min_, size=sz, max=max_, resolution=resolution,
- padding=padding)
- return map
-
-def _fill_holes(img, thresh):
- """Fills holes less than thresh area (assumes 4 connectivity when computing
- hole area."""
- l, n = scipy.ndimage.label(np.logical_not(img))
- img_ = img == True
- cnts = np.bincount(l.reshape(-1))
- for i, cnt in enumerate(cnts):
- if cnt < thresh:
- l[l == i] = -1
- img_[l == -1] = True
- return img_
-
-def compute_traversibility(map, robot_base, robot_height, robot_radius,
- valid_min, valid_max, num_point_threshold, shapess,
- sc=100., n_samples_per_face=200):
- """Returns a bit map with pixels that are traversible or not as long as the
- robot center is inside this volume we are good colisions can be detected by
- doing a line search on things, or walking from current location to final
- location in the bitmap, or doing bwlabel on the traversibility map."""
-
- tt = utils.Timer()
- tt.tic()
- num_obstcale_points = np.zeros((map.size[1], map.size[0]))
- num_points = np.zeros((map.size[1], map.size[0]))
-
- for i, shapes in enumerate(shapess):
- for j in range(shapes.get_number_of_meshes()):
- p, face_areas, face_idx = shapes.sample_points_on_face_of_shape(
- j, n_samples_per_face, sc)
- wt = face_areas[face_idx]/n_samples_per_face
-
- ind = np.all(np.concatenate(
- (p[:, [2]] > robot_base,
- p[:, [2]] < robot_base + robot_height), axis=1),axis=1)
- num_obstcale_points += _project_to_map(map, p[ind, :], wt[ind])
-
- ind = np.all(np.concatenate(
- (p[:, [2]] > valid_min,
- p[:, [2]] < valid_max), axis=1),axis=1)
- num_points += _project_to_map(map, p[ind, :], wt[ind])
-
- selem = skimage.morphology.disk(robot_radius / map.resolution)
- obstacle_free = skimage.morphology.binary_dilation(
- _fill_holes(num_obstcale_points > num_point_threshold, 20), selem) != True
- valid_space = _fill_holes(num_points > num_point_threshold, 20)
- traversible = np.all(np.concatenate((obstacle_free[...,np.newaxis],
- valid_space[...,np.newaxis]), axis=2),
- axis=2)
- # plt.imshow(np.concatenate((obstacle_free, valid_space, traversible), axis=1))
- # plt.show()
-
- map_out = copy.deepcopy(map)
- map_out.num_obstcale_points = num_obstcale_points
- map_out.num_points = num_points
- map_out.traversible = traversible
- map_out.obstacle_free = obstacle_free
- map_out.valid_space = valid_space
- tt.toc(log_at=1, log_str='src.map_utils.compute_traversibility: ')
- return map_out
-
-
-def resize_maps(map, map_scales, resize_method):
- scaled_maps = []
- for i, sc in enumerate(map_scales):
- if resize_method == 'antialiasing':
- # Resize using open cv so that we can compute the size.
- # Use PIL resize to use anti aliasing feature.
- map_ = cv2.resize(map*1, None, None, fx=sc, fy=sc, interpolation=cv2.INTER_LINEAR)
- w = map_.shape[1]; h = map_.shape[0]
-
- map_img = PIL.Image.fromarray((map*255).astype(np.uint8))
- map__img = map_img.resize((w,h), PIL.Image.ANTIALIAS)
- map_ = np.asarray(map__img).astype(np.float32)
- map_ = map_/255.
- map_ = np.minimum(map_, 1.0)
- map_ = np.maximum(map_, 0.0)
- elif resize_method == 'linear_noantialiasing':
- map_ = cv2.resize(map*1, None, None, fx=sc, fy=sc, interpolation=cv2.INTER_LINEAR)
- else:
- logging.error('Unknown resizing method')
- scaled_maps.append(map_)
- return scaled_maps
-
-
-def pick_largest_cc(traversible):
- out = scipy.ndimage.label(traversible)[0]
- cnt = np.bincount(out.reshape(-1))[1:]
- return out == np.argmax(cnt) + 1
-
-def get_graph_origin_loc(rng, traversible):
- """Erode the traversibility mask so that we get points in the bulk of the
- graph, and not end up with a situation where the graph is localized in the
- corner of a cramped room. Output Locs is in the coordinate frame of the
- map."""
-
- aa = pick_largest_cc(skimage.morphology.binary_erosion(traversible == True,
- selem=np.ones((15,15))))
- y, x = np.where(aa > 0)
- ind = rng.choice(y.size)
- locs = np.array([x[ind], y[ind]])
- locs = locs + rng.rand(*(locs.shape)) - 0.5
- return locs
-
-
-def generate_egocentric_maps(scaled_maps, map_scales, map_crop_sizes, loc,
- x_axis, y_axis, theta):
- maps = []
- for i, (map_, sc, map_crop_size) in enumerate(zip(scaled_maps, map_scales, map_crop_sizes)):
- maps_i = np.array(get_map_to_predict(loc*sc, x_axis, y_axis, map_,
- map_crop_size,
- interpolation=cv2.INTER_LINEAR)[0])
- maps_i[np.isnan(maps_i)] = 0
- maps.append(maps_i)
- return maps
-
-def generate_goal_images(map_scales, map_crop_sizes, n_ori, goal_dist,
- goal_theta, rel_goal_orientation):
- goal_dist = goal_dist[:,0]
- goal_theta = goal_theta[:,0]
- rel_goal_orientation = rel_goal_orientation[:,0]
-
- goals = [];
- # Generate the map images.
- for i, (sc, map_crop_size) in enumerate(zip(map_scales, map_crop_sizes)):
- goal_i = np.zeros((goal_dist.shape[0], map_crop_size, map_crop_size, n_ori),
- dtype=np.float32)
- x = goal_dist*np.cos(goal_theta)*sc + (map_crop_size-1.)/2.
- y = goal_dist*np.sin(goal_theta)*sc + (map_crop_size-1.)/2.
-
- for j in range(goal_dist.shape[0]):
- gc = rel_goal_orientation[j]
- x0 = np.floor(x[j]).astype(np.int32); x1 = x0 + 1;
- y0 = np.floor(y[j]).astype(np.int32); y1 = y0 + 1;
- if x0 >= 0 and x0 <= map_crop_size-1:
- if y0 >= 0 and y0 <= map_crop_size-1:
- goal_i[j, y0, x0, gc] = (x1-x[j])*(y1-y[j])
- if y1 >= 0 and y1 <= map_crop_size-1:
- goal_i[j, y1, x0, gc] = (x1-x[j])*(y[j]-y0)
-
- if x1 >= 0 and x1 <= map_crop_size-1:
- if y0 >= 0 and y0 <= map_crop_size-1:
- goal_i[j, y0, x1, gc] = (x[j]-x0)*(y1-y[j])
- if y1 >= 0 and y1 <= map_crop_size-1:
- goal_i[j, y1, x1, gc] = (x[j]-x0)*(y[j]-y0)
-
- goals.append(goal_i)
- return goals
-
-def get_map_to_predict(src_locs, src_x_axiss, src_y_axiss, map, map_size,
- interpolation=cv2.INTER_LINEAR):
- fss = []
- valids = []
-
- center = (map_size-1.0)/2.0
- dst_theta = np.pi/2.0
- dst_loc = np.array([center, center])
- dst_x_axis = np.array([np.cos(dst_theta), np.sin(dst_theta)])
- dst_y_axis = np.array([np.cos(dst_theta+np.pi/2), np.sin(dst_theta+np.pi/2)])
-
- def compute_points(center, x_axis, y_axis):
- points = np.zeros((3,2),dtype=np.float32)
- points[0,:] = center
- points[1,:] = center + x_axis
- points[2,:] = center + y_axis
- return points
-
- dst_points = compute_points(dst_loc, dst_x_axis, dst_y_axis)
- for i in range(src_locs.shape[0]):
- src_loc = src_locs[i,:]
- src_x_axis = src_x_axiss[i,:]
- src_y_axis = src_y_axiss[i,:]
- src_points = compute_points(src_loc, src_x_axis, src_y_axis)
- M = cv2.getAffineTransform(src_points, dst_points)
-
- fs = cv2.warpAffine(map, M, (map_size, map_size), None, flags=interpolation,
- borderValue=np.NaN)
- valid = np.invert(np.isnan(fs))
- valids.append(valid)
- fss.append(fs)
- return fss, valids
-
diff --git a/research/cognitive_mapping_and_planning/src/rotation_utils.py b/research/cognitive_mapping_and_planning/src/rotation_utils.py
deleted file mode 100644
index 8d6d4f3cbdb1f808d210dce8b22fa3ba831d45a9..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/src/rotation_utils.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Utilities for generating and applying rotation matrices.
-"""
-import numpy as np
-
-ANGLE_EPS = 0.001
-
-
-def normalize(v):
- return v / np.linalg.norm(v)
-
-
-def get_r_matrix(ax_, angle):
- ax = normalize(ax_)
- if np.abs(angle) > ANGLE_EPS:
- S_hat = np.array(
- [[0.0, -ax[2], ax[1]], [ax[2], 0.0, -ax[0]], [-ax[1], ax[0], 0.0]],
- dtype=np.float32)
- R = np.eye(3) + np.sin(angle)*S_hat + \
- (1-np.cos(angle))*(np.linalg.matrix_power(S_hat, 2))
- else:
- R = np.eye(3)
- return R
-
-
-def r_between(v_from_, v_to_):
- v_from = normalize(v_from_)
- v_to = normalize(v_to_)
- ax = normalize(np.cross(v_from, v_to))
- angle = np.arccos(np.dot(v_from, v_to))
- return get_r_matrix(ax, angle)
-
-
-def rotate_camera_to_point_at(up_from, lookat_from, up_to, lookat_to):
- inputs = [up_from, lookat_from, up_to, lookat_to]
- for i in range(4):
- inputs[i] = normalize(np.array(inputs[i]).reshape((-1,)))
- up_from, lookat_from, up_to, lookat_to = inputs
- r1 = r_between(lookat_from, lookat_to)
-
- new_x = np.dot(r1, np.array([1, 0, 0]).reshape((-1, 1))).reshape((-1))
- to_x = normalize(np.cross(lookat_to, up_to))
- angle = np.arccos(np.dot(new_x, to_x))
- if angle > ANGLE_EPS:
- if angle < np.pi - ANGLE_EPS:
- ax = normalize(np.cross(new_x, to_x))
- flip = np.dot(lookat_to, ax)
- if flip > 0:
- r2 = get_r_matrix(lookat_to, angle)
- elif flip < 0:
- r2 = get_r_matrix(lookat_to, -1. * angle)
- else:
- # Angle of rotation is too close to 180 degrees, direction of rotation
- # does not matter.
- r2 = get_r_matrix(lookat_to, angle)
- else:
- r2 = np.eye(3)
- return np.dot(r2, r1)
-
diff --git a/research/cognitive_mapping_and_planning/src/utils.py b/research/cognitive_mapping_and_planning/src/utils.py
deleted file mode 100644
index a1b9e44260b7c7884855761f56ac60d6f508c2fb..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/src/utils.py
+++ /dev/null
@@ -1,168 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-r"""Generaly Utilities.
-"""
-
-import numpy as np, cPickle, os, time
-from six.moves import xrange
-import src.file_utils as fu
-import logging
-
-class Timer():
- def __init__(self):
- self.calls = 0.
- self.start_time = 0.
- self.time_per_call = 0.
- self.total_time = 0.
- self.last_log_time = 0.
-
- def tic(self):
- self.start_time = time.time()
-
- def toc(self, average=True, log_at=-1, log_str='', type='calls'):
- if self.start_time == 0:
- logging.error('Timer not started by calling tic().')
- t = time.time()
- diff = time.time() - self.start_time
- self.total_time += diff
- self.calls += 1.
- self.time_per_call = self.total_time/self.calls
-
- if type == 'calls' and log_at > 0 and np.mod(self.calls, log_at) == 0:
- _ = []
- logging.info('%s: %f seconds.', log_str, self.time_per_call)
- elif type == 'time' and log_at > 0 and t - self.last_log_time >= log_at:
- _ = []
- logging.info('%s: %f seconds.', log_str, self.time_per_call)
- self.last_log_time = t
-
- if average:
- return self.time_per_call
- else:
- return diff
-
-class Foo(object):
- def __init__(self, **kwargs):
- self.__dict__.update(kwargs)
- def __str__(self):
- str_ = ''
- for v in vars(self).keys():
- a = getattr(self, v)
- if True: #isinstance(v, object):
- str__ = str(a)
- str__ = str__.replace('\n', '\n ')
- else:
- str__ = str(a)
- str_ += '{:s}: {:s}'.format(v, str__)
- str_ += '\n'
- return str_
-
-
-def dict_equal(dict1, dict2):
- assert(set(dict1.keys()) == set(dict2.keys())), "Sets of keys between 2 dictionaries are different."
- for k in dict1.keys():
- assert(type(dict1[k]) == type(dict2[k])), "Type of key '{:s}' if different.".format(k)
- if type(dict1[k]) == np.ndarray:
- assert(dict1[k].dtype == dict2[k].dtype), "Numpy Type of key '{:s}' if different.".format(k)
- assert(np.allclose(dict1[k], dict2[k])), "Value for key '{:s}' do not match.".format(k)
- else:
- assert(dict1[k] == dict2[k]), "Value for key '{:s}' do not match.".format(k)
- return True
-
-def subplot(plt, Y_X, sz_y_sz_x = (10, 10)):
- Y,X = Y_X
- sz_y, sz_x = sz_y_sz_x
- plt.rcParams['figure.figsize'] = (X*sz_x, Y*sz_y)
- fig, axes = plt.subplots(Y, X)
- plt.subplots_adjust(wspace=0.1, hspace=0.1)
- return fig, axes
-
-def tic_toc_print(interval, string):
- global tic_toc_print_time_old
- if 'tic_toc_print_time_old' not in globals():
- tic_toc_print_time_old = time.time()
- print(string)
- else:
- new_time = time.time()
- if new_time - tic_toc_print_time_old > interval:
- tic_toc_print_time_old = new_time;
- print(string)
-
-def mkdir_if_missing(output_dir):
- if not fu.exists(output_dir):
- fu.makedirs(output_dir)
-
-def save_variables(pickle_file_name, var, info, overwrite = False):
- if fu.exists(pickle_file_name) and overwrite == False:
- raise Exception('{:s} exists and over write is false.'.format(pickle_file_name))
- # Construct the dictionary
- assert(type(var) == list); assert(type(info) == list);
- d = {}
- for i in xrange(len(var)):
- d[info[i]] = var[i]
- with fu.fopen(pickle_file_name, 'w') as f:
- cPickle.dump(d, f, cPickle.HIGHEST_PROTOCOL)
-
-def load_variables(pickle_file_name):
- if fu.exists(pickle_file_name):
- with fu.fopen(pickle_file_name, 'r') as f:
- d = cPickle.load(f)
- return d
- else:
- raise Exception('{:s} does not exists.'.format(pickle_file_name))
-
-def voc_ap(rec, prec):
- rec = rec.reshape((-1,1))
- prec = prec.reshape((-1,1))
- z = np.zeros((1,1))
- o = np.ones((1,1))
- mrec = np.vstack((z, rec, o))
- mpre = np.vstack((z, prec, z))
- for i in range(len(mpre)-2, -1, -1):
- mpre[i] = max(mpre[i], mpre[i+1])
-
- I = np.where(mrec[1:] != mrec[0:-1])[0]+1;
- ap = 0;
- for i in I:
- ap = ap + (mrec[i] - mrec[i-1])*mpre[i];
- return ap
-
-def tight_imshow_figure(plt, figsize=None):
- fig = plt.figure(figsize=figsize)
- ax = plt.Axes(fig, [0,0,1,1])
- ax.set_axis_off()
- fig.add_axes(ax)
- return fig, ax
-
-def calc_pr(gt, out, wt=None):
- if wt is None:
- wt = np.ones((gt.size,1))
-
- gt = gt.astype(np.float64).reshape((-1,1))
- wt = wt.astype(np.float64).reshape((-1,1))
- out = out.astype(np.float64).reshape((-1,1))
-
- gt = gt*wt
- tog = np.concatenate([gt, wt, out], axis=1)*1.
- ind = np.argsort(tog[:,2], axis=0)[::-1]
- tog = tog[ind,:]
- cumsumsortgt = np.cumsum(tog[:,0])
- cumsumsortwt = np.cumsum(tog[:,1])
- prec = cumsumsortgt / cumsumsortwt
- rec = cumsumsortgt / np.sum(tog[:,0])
-
- ap = voc_ap(rec, prec)
- return ap, rec, prec
diff --git a/research/cognitive_mapping_and_planning/tfcode/__init__.py b/research/cognitive_mapping_and_planning/tfcode/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/cognitive_mapping_and_planning/tfcode/cmp.py b/research/cognitive_mapping_and_planning/tfcode/cmp.py
deleted file mode 100644
index 228ef90fddcd9ff41b26795544d93a1f18466158..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/tfcode/cmp.py
+++ /dev/null
@@ -1,553 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Code for setting up the network for CMP.
-
-Sets up the mapper and the planner.
-"""
-
-import sys, os, numpy as np
-import matplotlib.pyplot as plt
-import copy
-import argparse, pprint
-import time
-
-
-import tensorflow as tf
-
-from tensorflow.contrib import slim
-from tensorflow.contrib.slim import arg_scope
-
-import logging
-from tensorflow.python.platform import app
-from tensorflow.python.platform import flags
-from src import utils
-import src.file_utils as fu
-import tfcode.nav_utils as nu
-import tfcode.cmp_utils as cu
-import tfcode.cmp_summary as cmp_s
-from tfcode import tf_utils
-
-value_iteration_network = cu.value_iteration_network
-rotate_preds = cu.rotate_preds
-deconv = cu.deconv
-get_visual_frustum = cu.get_visual_frustum
-fr_v2 = cu.fr_v2
-
-setup_train_step_kwargs = nu.default_train_step_kwargs
-compute_losses_multi_or = nu.compute_losses_multi_or
-
-get_repr_from_image = nu.get_repr_from_image
-
-_save_d_at_t = nu.save_d_at_t
-_save_all = nu.save_all
-_eval_ap = nu.eval_ap
-_eval_dist = nu.eval_dist
-_plot_trajectories = nu.plot_trajectories
-
-_vis_readout_maps = cmp_s._vis_readout_maps
-_vis = cmp_s._vis
-_summary_vis = cmp_s._summary_vis
-_summary_readout_maps = cmp_s._summary_readout_maps
-_add_summaries = cmp_s._add_summaries
-
-def _inputs(problem):
- # Set up inputs.
- with tf.name_scope('inputs'):
- inputs = []
- inputs.append(('orig_maps', tf.float32,
- (problem.batch_size, 1, None, None, 1)))
- inputs.append(('goal_loc', tf.float32,
- (problem.batch_size, problem.num_goals, 2)))
- common_input_data, _ = tf_utils.setup_inputs(inputs)
-
- inputs = []
- if problem.input_type == 'vision':
- # Multiple images from an array of cameras.
- inputs.append(('imgs', tf.float32,
- (problem.batch_size, None, len(problem.aux_delta_thetas)+1,
- problem.img_height, problem.img_width,
- problem.img_channels)))
- elif problem.input_type == 'analytical_counts':
- for i in range(len(problem.map_crop_sizes)):
- inputs.append(('analytical_counts_{:d}'.format(i), tf.float32,
- (problem.batch_size, None, problem.map_crop_sizes[i],
- problem.map_crop_sizes[i], problem.map_channels)))
-
- if problem.outputs.readout_maps:
- for i in range(len(problem.readout_maps_crop_sizes)):
- inputs.append(('readout_maps_{:d}'.format(i), tf.float32,
- (problem.batch_size, None,
- problem.readout_maps_crop_sizes[i],
- problem.readout_maps_crop_sizes[i],
- problem.readout_maps_channels)))
-
- for i in range(len(problem.map_crop_sizes)):
- inputs.append(('ego_goal_imgs_{:d}'.format(i), tf.float32,
- (problem.batch_size, None, problem.map_crop_sizes[i],
- problem.map_crop_sizes[i], problem.goal_channels)))
- for s in ['sum_num', 'sum_denom', 'max_denom']:
- inputs.append(('running_'+s+'_{:d}'.format(i), tf.float32,
- (problem.batch_size, 1, problem.map_crop_sizes[i],
- problem.map_crop_sizes[i], problem.map_channels)))
-
- inputs.append(('incremental_locs', tf.float32,
- (problem.batch_size, None, 2)))
- inputs.append(('incremental_thetas', tf.float32,
- (problem.batch_size, None, 1)))
- inputs.append(('step_number', tf.int32, (1, None, 1)))
- inputs.append(('node_ids', tf.int32, (problem.batch_size, None,
- problem.node_ids_dim)))
- inputs.append(('perturbs', tf.float32, (problem.batch_size, None,
- problem.perturbs_dim)))
-
- # For plotting result plots
- inputs.append(('loc_on_map', tf.float32, (problem.batch_size, None, 2)))
- inputs.append(('gt_dist_to_goal', tf.float32, (problem.batch_size, None, 1)))
-
- step_input_data, _ = tf_utils.setup_inputs(inputs)
-
- inputs = []
- inputs.append(('action', tf.int32, (problem.batch_size, None, problem.num_actions)))
- train_data, _ = tf_utils.setup_inputs(inputs)
- train_data.update(step_input_data)
- train_data.update(common_input_data)
- return common_input_data, step_input_data, train_data
-
-def readout_general(multi_scale_belief, num_neurons, strides, layers_per_block,
- kernel_size, batch_norm_is_training_op, wt_decay):
- multi_scale_belief = tf.stop_gradient(multi_scale_belief)
- with tf.variable_scope('readout_maps_deconv'):
- x, outs = deconv(multi_scale_belief, batch_norm_is_training_op,
- wt_decay=wt_decay, neurons=num_neurons, strides=strides,
- layers_per_block=layers_per_block, kernel_size=kernel_size,
- conv_fn=slim.conv2d_transpose, offset=0,
- name='readout_maps_deconv')
- probs = tf.sigmoid(x)
- return x, probs
-
-
-def running_combine(fss_logits, confs_probs, incremental_locs,
- incremental_thetas, previous_sum_num, previous_sum_denom,
- previous_max_denom, map_size, num_steps):
- # fss_logits is B x N x H x W x C
- # confs_logits is B x N x H x W x C
- # incremental_locs is B x N x 2
- # incremental_thetas is B x N x 1
- # previous_sum_num etc is B x 1 x H x W x C
-
- with tf.name_scope('combine_{:d}'.format(num_steps)):
- running_sum_nums_ = []; running_sum_denoms_ = [];
- running_max_denoms_ = [];
-
- fss_logits_ = tf.unstack(fss_logits, axis=1, num=num_steps)
- confs_probs_ = tf.unstack(confs_probs, axis=1, num=num_steps)
- incremental_locs_ = tf.unstack(incremental_locs, axis=1, num=num_steps)
- incremental_thetas_ = tf.unstack(incremental_thetas, axis=1, num=num_steps)
- running_sum_num = tf.unstack(previous_sum_num, axis=1, num=1)[0]
- running_sum_denom = tf.unstack(previous_sum_denom, axis=1, num=1)[0]
- running_max_denom = tf.unstack(previous_max_denom, axis=1, num=1)[0]
-
- for i in range(num_steps):
- # Rotate the previous running_num and running_denom
- running_sum_num, running_sum_denom, running_max_denom = rotate_preds(
- incremental_locs_[i], incremental_thetas_[i], map_size,
- [running_sum_num, running_sum_denom, running_max_denom],
- output_valid_mask=False)[0]
- # print i, num_steps, running_sum_num.get_shape().as_list()
- running_sum_num = running_sum_num + fss_logits_[i] * confs_probs_[i]
- running_sum_denom = running_sum_denom + confs_probs_[i]
- running_max_denom = tf.maximum(running_max_denom, confs_probs_[i])
- running_sum_nums_.append(running_sum_num)
- running_sum_denoms_.append(running_sum_denom)
- running_max_denoms_.append(running_max_denom)
-
- running_sum_nums = tf.stack(running_sum_nums_, axis=1)
- running_sum_denoms = tf.stack(running_sum_denoms_, axis=1)
- running_max_denoms = tf.stack(running_max_denoms_, axis=1)
- return running_sum_nums, running_sum_denoms, running_max_denoms
-
-def get_map_from_images(imgs, mapper_arch, task_params, freeze_conv, wt_decay,
- is_training, batch_norm_is_training_op, num_maps,
- split_maps=True):
- # Hit image with a resnet.
- n_views = len(task_params.aux_delta_thetas) + 1
- out = utils.Foo()
-
- images_reshaped = tf.reshape(imgs,
- shape=[-1, task_params.img_height,
- task_params.img_width,
- task_params.img_channels], name='re_image')
-
- x, out.vars_to_restore = get_repr_from_image(
- images_reshaped, task_params.modalities, task_params.data_augment,
- mapper_arch.encoder, freeze_conv, wt_decay, is_training)
-
- # Reshape into nice things so that these can be accumulated over time steps
- # for faster backprop.
- sh_before = x.get_shape().as_list()
- out.encoder_output = tf.reshape(x, shape=[task_params.batch_size, -1, n_views] + sh_before[1:])
- x = tf.reshape(out.encoder_output, shape=[-1] + sh_before[1:])
-
- # Add a layer to reduce dimensions for a fc layer.
- if mapper_arch.dim_reduce_neurons > 0:
- ks = 1; neurons = mapper_arch.dim_reduce_neurons;
- init_var = np.sqrt(2.0/(ks**2)/neurons)
- batch_norm_param = mapper_arch.batch_norm_param
- batch_norm_param['is_training'] = batch_norm_is_training_op
- out.conv_feat = slim.conv2d(x, neurons, kernel_size=ks, stride=1,
- normalizer_fn=slim.batch_norm, normalizer_params=batch_norm_param,
- padding='SAME', scope='dim_reduce',
- weights_regularizer=slim.l2_regularizer(wt_decay),
- weights_initializer=tf.random_normal_initializer(stddev=init_var))
- reshape_conv_feat = slim.flatten(out.conv_feat)
- sh = reshape_conv_feat.get_shape().as_list()
- out.reshape_conv_feat = tf.reshape(reshape_conv_feat, shape=[-1, sh[1]*n_views])
-
- with tf.variable_scope('fc'):
- # Fully connected layers to compute the representation in top-view space.
- fc_batch_norm_param = {'center': True, 'scale': True,
- 'activation_fn':tf.nn.relu,
- 'is_training': batch_norm_is_training_op}
- f = out.reshape_conv_feat
- out_neurons = (mapper_arch.fc_out_size**2)*mapper_arch.fc_out_neurons
- neurons = mapper_arch.fc_neurons + [out_neurons]
- f, _ = tf_utils.fc_network(f, neurons=neurons, wt_decay=wt_decay,
- name='fc', offset=0,
- batch_norm_param=fc_batch_norm_param,
- is_training=is_training,
- dropout_ratio=mapper_arch.fc_dropout)
- f = tf.reshape(f, shape=[-1, mapper_arch.fc_out_size,
- mapper_arch.fc_out_size,
- mapper_arch.fc_out_neurons], name='re_fc')
-
- # Use pool5 to predict the free space map via deconv layers.
- with tf.variable_scope('deconv'):
- x, outs = deconv(f, batch_norm_is_training_op, wt_decay=wt_decay,
- neurons=mapper_arch.deconv_neurons,
- strides=mapper_arch.deconv_strides,
- layers_per_block=mapper_arch.deconv_layers_per_block,
- kernel_size=mapper_arch.deconv_kernel_size,
- conv_fn=slim.conv2d_transpose, offset=0, name='deconv')
-
- # Reshape x the right way.
- sh = x.get_shape().as_list()
- x = tf.reshape(x, shape=[task_params.batch_size, -1] + sh[1:])
- out.deconv_output = x
-
- # Separate out the map and the confidence predictions, pass the confidence
- # through a sigmoid.
- if split_maps:
- with tf.name_scope('split'):
- out_all = tf.split(value=x, axis=4, num_or_size_splits=2*num_maps)
- out.fss_logits = out_all[:num_maps]
- out.confs_logits = out_all[num_maps:]
- with tf.name_scope('sigmoid'):
- out.confs_probs = [tf.nn.sigmoid(x) for x in out.confs_logits]
- return out
-
-def setup_to_run(m, args, is_training, batch_norm_is_training, summary_mode):
- assert(args.arch.multi_scale), 'removed support for old single scale code.'
- # Set up the model.
- tf.set_random_seed(args.solver.seed)
- task_params = args.navtask.task_params
-
- batch_norm_is_training_op = \
- tf.placeholder_with_default(batch_norm_is_training, shape=[],
- name='batch_norm_is_training_op')
-
- # Setup the inputs
- m.input_tensors = {}
- m.train_ops = {}
- m.input_tensors['common'], m.input_tensors['step'], m.input_tensors['train'] = \
- _inputs(task_params)
-
- m.init_fn = None
-
- if task_params.input_type == 'vision':
- m.vision_ops = get_map_from_images(
- m.input_tensors['step']['imgs'], args.mapper_arch,
- task_params, args.solver.freeze_conv,
- args.solver.wt_decay, is_training, batch_norm_is_training_op,
- num_maps=len(task_params.map_crop_sizes))
-
- # Load variables from snapshot if needed.
- if args.solver.pretrained_path is not None:
- m.init_fn = slim.assign_from_checkpoint_fn(args.solver.pretrained_path,
- m.vision_ops.vars_to_restore)
-
- # Set up caching of vision features if needed.
- if args.solver.freeze_conv:
- m.train_ops['step_data_cache'] = [m.vision_ops.encoder_output]
- else:
- m.train_ops['step_data_cache'] = []
-
- # Set up blobs that are needed for the computation in rest of the graph.
- m.ego_map_ops = m.vision_ops.fss_logits
- m.coverage_ops = m.vision_ops.confs_probs
-
- # Zero pad these to make them same size as what the planner expects.
- for i in range(len(m.ego_map_ops)):
- if args.mapper_arch.pad_map_with_zeros_each[i] > 0:
- paddings = np.zeros((5,2), dtype=np.int32)
- paddings[2:4,:] = args.mapper_arch.pad_map_with_zeros_each[i]
- paddings_op = tf.constant(paddings, dtype=tf.int32)
- m.ego_map_ops[i] = tf.pad(m.ego_map_ops[i], paddings=paddings_op)
- m.coverage_ops[i] = tf.pad(m.coverage_ops[i], paddings=paddings_op)
-
- elif task_params.input_type == 'analytical_counts':
- m.ego_map_ops = []; m.coverage_ops = []
- for i in range(len(task_params.map_crop_sizes)):
- ego_map_op = m.input_tensors['step']['analytical_counts_{:d}'.format(i)]
- coverage_op = tf.cast(tf.greater_equal(
- tf.reduce_max(ego_map_op, reduction_indices=[4],
- keep_dims=True), 1), tf.float32)
- coverage_op = tf.ones_like(ego_map_op) * coverage_op
- m.ego_map_ops.append(ego_map_op)
- m.coverage_ops.append(coverage_op)
- m.train_ops['step_data_cache'] = []
-
- num_steps = task_params.num_steps
- num_goals = task_params.num_goals
-
- map_crop_size_ops = []
- for map_crop_size in task_params.map_crop_sizes:
- map_crop_size_ops.append(tf.constant(map_crop_size, dtype=tf.int32, shape=(2,)))
-
- with tf.name_scope('check_size'):
- is_single_step = tf.equal(tf.unstack(tf.shape(m.ego_map_ops[0]), num=5)[1], 1)
-
- fr_ops = []; value_ops = [];
- fr_intermediate_ops = []; value_intermediate_ops = [];
- crop_value_ops = [];
- resize_crop_value_ops = [];
- confs = []; occupancys = [];
-
- previous_value_op = None
- updated_state = []; state_names = [];
-
- for i in range(len(task_params.map_crop_sizes)):
- map_crop_size = task_params.map_crop_sizes[i]
- with tf.variable_scope('scale_{:d}'.format(i)):
- # Accumulate the map.
- fn = lambda ns: running_combine(
- m.ego_map_ops[i],
- m.coverage_ops[i],
- m.input_tensors['step']['incremental_locs'] * task_params.map_scales[i],
- m.input_tensors['step']['incremental_thetas'],
- m.input_tensors['step']['running_sum_num_{:d}'.format(i)],
- m.input_tensors['step']['running_sum_denom_{:d}'.format(i)],
- m.input_tensors['step']['running_max_denom_{:d}'.format(i)],
- map_crop_size, ns)
-
- running_sum_num, running_sum_denom, running_max_denom = \
- tf.cond(is_single_step, lambda: fn(1), lambda: fn(num_steps*num_goals))
- updated_state += [running_sum_num, running_sum_denom, running_max_denom]
- state_names += ['running_sum_num_{:d}'.format(i),
- 'running_sum_denom_{:d}'.format(i),
- 'running_max_denom_{:d}'.format(i)]
-
- # Concat the accumulated map and goal
- occupancy = running_sum_num / tf.maximum(running_sum_denom, 0.001)
- conf = running_max_denom
- # print occupancy.get_shape().as_list()
-
- # Concat occupancy, how much occupied and goal.
- with tf.name_scope('concat'):
- sh = [-1, map_crop_size, map_crop_size, task_params.map_channels]
- occupancy = tf.reshape(occupancy, shape=sh)
- conf = tf.reshape(conf, shape=sh)
-
- sh = [-1, map_crop_size, map_crop_size, task_params.goal_channels]
- goal = tf.reshape(m.input_tensors['step']['ego_goal_imgs_{:d}'.format(i)], shape=sh)
- to_concat = [occupancy, conf, goal]
-
- if previous_value_op is not None:
- to_concat.append(previous_value_op)
-
- x = tf.concat(to_concat, 3)
-
- # Pass the map, previous rewards and the goal through a few convolutional
- # layers to get fR.
- fr_op, fr_intermediate_op = fr_v2(
- x, output_neurons=args.arch.fr_neurons,
- inside_neurons=args.arch.fr_inside_neurons,
- is_training=batch_norm_is_training_op, name='fr',
- wt_decay=args.solver.wt_decay, stride=args.arch.fr_stride)
-
- # Do Value Iteration on the fR
- if args.arch.vin_num_iters > 0:
- value_op, value_intermediate_op = value_iteration_network(
- fr_op, num_iters=args.arch.vin_num_iters,
- val_neurons=args.arch.vin_val_neurons,
- action_neurons=args.arch.vin_action_neurons,
- kernel_size=args.arch.vin_ks, share_wts=args.arch.vin_share_wts,
- name='vin', wt_decay=args.solver.wt_decay)
- else:
- value_op = fr_op
- value_intermediate_op = []
-
- # Crop out and upsample the previous value map.
- remove = args.arch.crop_remove_each
- if remove > 0:
- crop_value_op = value_op[:, remove:-remove, remove:-remove,:]
- else:
- crop_value_op = value_op
- crop_value_op = tf.reshape(crop_value_op, shape=[-1, args.arch.value_crop_size,
- args.arch.value_crop_size,
- args.arch.vin_val_neurons])
- if i < len(task_params.map_crop_sizes)-1:
- # Reshape it to shape of the next scale.
- previous_value_op = tf.image.resize_bilinear(crop_value_op,
- map_crop_size_ops[i+1],
- align_corners=True)
- resize_crop_value_ops.append(previous_value_op)
-
- occupancys.append(occupancy)
- confs.append(conf)
- value_ops.append(value_op)
- crop_value_ops.append(crop_value_op)
- fr_ops.append(fr_op)
- fr_intermediate_ops.append(fr_intermediate_op)
-
- m.value_ops = value_ops
- m.value_intermediate_ops = value_intermediate_ops
- m.fr_ops = fr_ops
- m.fr_intermediate_ops = fr_intermediate_ops
- m.final_value_op = crop_value_op
- m.crop_value_ops = crop_value_ops
- m.resize_crop_value_ops = resize_crop_value_ops
- m.confs = confs
- m.occupancys = occupancys
-
- sh = [-1, args.arch.vin_val_neurons*((args.arch.value_crop_size)**2)]
- m.value_features_op = tf.reshape(m.final_value_op, sh, name='reshape_value_op')
-
- # Determine what action to take.
- with tf.variable_scope('action_pred'):
- batch_norm_param = args.arch.pred_batch_norm_param
- if batch_norm_param is not None:
- batch_norm_param['is_training'] = batch_norm_is_training_op
- m.action_logits_op, _ = tf_utils.fc_network(
- m.value_features_op, neurons=args.arch.pred_neurons,
- wt_decay=args.solver.wt_decay, name='pred', offset=0,
- num_pred=task_params.num_actions,
- batch_norm_param=batch_norm_param)
- m.action_prob_op = tf.nn.softmax(m.action_logits_op)
-
- init_state = tf.constant(0., dtype=tf.float32, shape=[
- task_params.batch_size, 1, map_crop_size, map_crop_size,
- task_params.map_channels])
-
- m.train_ops['state_names'] = state_names
- m.train_ops['updated_state'] = updated_state
- m.train_ops['init_state'] = [init_state for _ in updated_state]
-
- m.train_ops['step'] = m.action_prob_op
- m.train_ops['common'] = [m.input_tensors['common']['orig_maps'],
- m.input_tensors['common']['goal_loc']]
- m.train_ops['batch_norm_is_training_op'] = batch_norm_is_training_op
- m.loss_ops = []; m.loss_ops_names = [];
-
- if args.arch.readout_maps:
- with tf.name_scope('readout_maps'):
- all_occupancys = tf.concat(m.occupancys + m.confs, 3)
- readout_maps, probs = readout_general(
- all_occupancys, num_neurons=args.arch.rom_arch.num_neurons,
- strides=args.arch.rom_arch.strides,
- layers_per_block=args.arch.rom_arch.layers_per_block,
- kernel_size=args.arch.rom_arch.kernel_size,
- batch_norm_is_training_op=batch_norm_is_training_op,
- wt_decay=args.solver.wt_decay)
-
- gt_ego_maps = [m.input_tensors['step']['readout_maps_{:d}'.format(i)]
- for i in range(len(task_params.readout_maps_crop_sizes))]
- m.readout_maps_gt = tf.concat(gt_ego_maps, 4)
- gt_shape = tf.shape(m.readout_maps_gt)
- m.readout_maps_logits = tf.reshape(readout_maps, gt_shape)
- m.readout_maps_probs = tf.reshape(probs, gt_shape)
-
- # Add a loss op
- m.readout_maps_loss_op = tf.losses.sigmoid_cross_entropy(
- tf.reshape(m.readout_maps_gt, [-1, len(task_params.readout_maps_crop_sizes)]),
- tf.reshape(readout_maps, [-1, len(task_params.readout_maps_crop_sizes)]),
- scope='loss')
- m.readout_maps_loss_op = 10.*m.readout_maps_loss_op
-
- ewma_decay = 0.99 if is_training else 0.0
- weight = tf.ones_like(m.input_tensors['train']['action'], dtype=tf.float32,
- name='weight')
- m.reg_loss_op, m.data_loss_op, m.total_loss_op, m.acc_ops = \
- compute_losses_multi_or(m.action_logits_op,
- m.input_tensors['train']['action'], weights=weight,
- num_actions=task_params.num_actions,
- data_loss_wt=args.solver.data_loss_wt,
- reg_loss_wt=args.solver.reg_loss_wt,
- ewma_decay=ewma_decay)
-
- if args.arch.readout_maps:
- m.total_loss_op = m.total_loss_op + m.readout_maps_loss_op
- m.loss_ops += [m.readout_maps_loss_op]
- m.loss_ops_names += ['readout_maps_loss']
-
- m.loss_ops += [m.reg_loss_op, m.data_loss_op, m.total_loss_op]
- m.loss_ops_names += ['reg_loss', 'data_loss', 'total_loss']
-
- if args.solver.freeze_conv:
- vars_to_optimize = list(set(tf.trainable_variables()) -
- set(m.vision_ops.vars_to_restore))
- else:
- vars_to_optimize = None
-
- m.lr_op, m.global_step_op, m.train_op, m.should_stop_op, m.optimizer, \
- m.sync_optimizer = tf_utils.setup_training(
- m.total_loss_op,
- args.solver.initial_learning_rate,
- args.solver.steps_per_decay,
- args.solver.learning_rate_decay,
- args.solver.momentum,
- args.solver.max_steps,
- args.solver.sync,
- args.solver.adjust_lr_sync,
- args.solver.num_workers,
- args.solver.task,
- vars_to_optimize=vars_to_optimize,
- clip_gradient_norm=args.solver.clip_gradient_norm,
- typ=args.solver.typ, momentum2=args.solver.momentum2,
- adam_eps=args.solver.adam_eps)
-
- if args.arch.sample_gt_prob_type == 'inverse_sigmoid_decay':
- m.sample_gt_prob_op = tf_utils.inverse_sigmoid_decay(args.arch.isd_k,
- m.global_step_op)
- elif args.arch.sample_gt_prob_type == 'zero':
- m.sample_gt_prob_op = tf.constant(-1.0, dtype=tf.float32)
-
- elif args.arch.sample_gt_prob_type.split('_')[0] == 'step':
- step = int(args.arch.sample_gt_prob_type.split('_')[1])
- m.sample_gt_prob_op = tf_utils.step_gt_prob(
- step, m.input_tensors['step']['step_number'][0,0,0])
-
- m.sample_action_type = args.arch.action_sample_type
- m.sample_action_combine_type = args.arch.action_sample_combine_type
-
- m.summary_ops = {
- summary_mode: _add_summaries(m, args, summary_mode,
- args.summary.arop_full_summary_iters)}
-
- m.init_op = tf.group(tf.global_variables_initializer(),
- tf.local_variables_initializer())
- m.saver_op = tf.train.Saver(keep_checkpoint_every_n_hours=4,
- write_version=tf.train.SaverDef.V2)
- return m
diff --git a/research/cognitive_mapping_and_planning/tfcode/cmp_summary.py b/research/cognitive_mapping_and_planning/tfcode/cmp_summary.py
deleted file mode 100644
index 55313bfbd52a9e079e1de5093ae1882a9bf1d858..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/tfcode/cmp_summary.py
+++ /dev/null
@@ -1,213 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Code for setting up summaries for CMP.
-"""
-
-import sys, os, numpy as np
-import matplotlib.pyplot as plt
-
-
-import tensorflow as tf
-
-from tensorflow.contrib import slim
-from tensorflow.contrib.slim import arg_scope
-
-import logging
-from tensorflow.python.platform import app
-from tensorflow.python.platform import flags
-from src import utils
-import src.file_utils as fu
-import tfcode.nav_utils as nu
-
-def _vis_readout_maps(outputs, global_step, output_dir, metric_summary, N):
- # outputs is [gt_map, pred_map]:
- if N >= 0:
- outputs = outputs[:N]
- N = len(outputs)
-
- plt.set_cmap('jet')
- fig, axes = utils.subplot(plt, (N, outputs[0][0].shape[4]*2), (5,5))
- axes = axes.ravel()[::-1].tolist()
- for i in range(N):
- gt_map, pred_map = outputs[i]
- for j in [0]:
- for k in range(gt_map.shape[4]):
- # Display something like the midpoint of the trajectory.
- id = np.int(gt_map.shape[1]/2)
-
- ax = axes.pop();
- ax.imshow(gt_map[j,id,:,:,k], origin='lower', interpolation='none',
- vmin=0., vmax=1.)
- ax.set_axis_off();
- if i == 0: ax.set_title('gt_map')
-
- ax = axes.pop();
- ax.imshow(pred_map[j,id,:,:,k], origin='lower', interpolation='none',
- vmin=0., vmax=1.)
- ax.set_axis_off();
- if i == 0: ax.set_title('pred_map')
-
- file_name = os.path.join(output_dir, 'readout_map_{:d}.png'.format(global_step))
- with fu.fopen(file_name, 'w') as f:
- fig.savefig(f, bbox_inches='tight', transparent=True, pad_inches=0)
- plt.close(fig)
-
-def _vis(outputs, global_step, output_dir, metric_summary, N):
- # Plot the value map, goal for various maps to see what if the model is
- # learning anything useful.
- #
- # outputs is [values, goals, maps, occupancy, conf].
- #
- if N >= 0:
- outputs = outputs[:N]
- N = len(outputs)
-
- plt.set_cmap('jet')
- fig, axes = utils.subplot(plt, (N, outputs[0][0].shape[4]*5), (5,5))
- axes = axes.ravel()[::-1].tolist()
- for i in range(N):
- values, goals, maps, occupancy, conf = outputs[i]
- for j in [0]:
- for k in range(values.shape[4]):
- # Display something like the midpoint of the trajectory.
- id = np.int(values.shape[1]/2)
-
- ax = axes.pop();
- ax.imshow(goals[j,id,:,:,k], origin='lower', interpolation='none')
- ax.set_axis_off();
- if i == 0: ax.set_title('goal')
-
- ax = axes.pop();
- ax.imshow(occupancy[j,id,:,:,k], origin='lower', interpolation='none')
- ax.set_axis_off();
- if i == 0: ax.set_title('occupancy')
-
- ax = axes.pop();
- ax.imshow(conf[j,id,:,:,k], origin='lower', interpolation='none',
- vmin=0., vmax=1.)
- ax.set_axis_off();
- if i == 0: ax.set_title('conf')
-
- ax = axes.pop();
- ax.imshow(values[j,id,:,:,k], origin='lower', interpolation='none')
- ax.set_axis_off();
- if i == 0: ax.set_title('value')
-
- ax = axes.pop();
- ax.imshow(maps[j,id,:,:,k], origin='lower', interpolation='none')
- ax.set_axis_off();
- if i == 0: ax.set_title('incr map')
-
- file_name = os.path.join(output_dir, 'value_vis_{:d}.png'.format(global_step))
- with fu.fopen(file_name, 'w') as f:
- fig.savefig(f, bbox_inches='tight', transparent=True, pad_inches=0)
- plt.close(fig)
-
-def _summary_vis(m, batch_size, num_steps, arop_full_summary_iters):
- arop = []; arop_summary_iters = []; arop_eval_fns = [];
- vis_value_ops = []; vis_goal_ops = []; vis_map_ops = [];
- vis_occupancy_ops = []; vis_conf_ops = [];
- for i, val_op in enumerate(m.value_ops):
- vis_value_op = tf.reduce_mean(tf.abs(val_op), axis=3, keep_dims=True)
- vis_value_ops.append(vis_value_op)
-
- vis_occupancy_op = tf.reduce_mean(tf.abs(m.occupancys[i]), 3, True)
- vis_occupancy_ops.append(vis_occupancy_op)
-
- vis_conf_op = tf.reduce_max(tf.abs(m.confs[i]), axis=3, keep_dims=True)
- vis_conf_ops.append(vis_conf_op)
-
- ego_goal_imgs_i_op = m.input_tensors['step']['ego_goal_imgs_{:d}'.format(i)]
- vis_goal_op = tf.reduce_max(ego_goal_imgs_i_op, 4, True)
- vis_goal_ops.append(vis_goal_op)
-
- vis_map_op = tf.reduce_mean(tf.abs(m.ego_map_ops[i]), 4, True)
- vis_map_ops.append(vis_map_op)
-
- vis_goal_ops = tf.concat(vis_goal_ops, 4)
- vis_map_ops = tf.concat(vis_map_ops, 4)
- vis_value_ops = tf.concat(vis_value_ops, 3)
- vis_occupancy_ops = tf.concat(vis_occupancy_ops, 3)
- vis_conf_ops = tf.concat(vis_conf_ops, 3)
-
- sh = tf.unstack(tf.shape(vis_value_ops))[1:]
- vis_value_ops = tf.reshape(vis_value_ops, shape=[batch_size, -1] + sh)
-
- sh = tf.unstack(tf.shape(vis_conf_ops))[1:]
- vis_conf_ops = tf.reshape(vis_conf_ops, shape=[batch_size, -1] + sh)
-
- sh = tf.unstack(tf.shape(vis_occupancy_ops))[1:]
- vis_occupancy_ops = tf.reshape(vis_occupancy_ops, shape=[batch_size,-1] + sh)
-
- # Save memory, only return time steps that need to be visualized, factor of
- # 32 CPU memory saving.
- id = np.int(num_steps/2)
- vis_goal_ops = tf.expand_dims(vis_goal_ops[:,id,:,:,:], axis=1)
- vis_map_ops = tf.expand_dims(vis_map_ops[:,id,:,:,:], axis=1)
- vis_value_ops = tf.expand_dims(vis_value_ops[:,id,:,:,:], axis=1)
- vis_conf_ops = tf.expand_dims(vis_conf_ops[:,id,:,:,:], axis=1)
- vis_occupancy_ops = tf.expand_dims(vis_occupancy_ops[:,id,:,:,:], axis=1)
-
- arop += [[vis_value_ops, vis_goal_ops, vis_map_ops, vis_occupancy_ops,
- vis_conf_ops]]
- arop_summary_iters += [arop_full_summary_iters]
- arop_eval_fns += [_vis]
- return arop, arop_summary_iters, arop_eval_fns
-
-def _summary_readout_maps(m, num_steps, arop_full_summary_iters):
- arop = []; arop_summary_iters = []; arop_eval_fns = [];
- id = np.int(num_steps-1)
- vis_readout_maps_gt = m.readout_maps_gt
- vis_readout_maps_prob = tf.reshape(m.readout_maps_probs,
- shape=tf.shape(vis_readout_maps_gt))
- vis_readout_maps_gt = tf.expand_dims(vis_readout_maps_gt[:,id,:,:,:], 1)
- vis_readout_maps_prob = tf.expand_dims(vis_readout_maps_prob[:,id,:,:,:], 1)
- arop += [[vis_readout_maps_gt, vis_readout_maps_prob]]
- arop_summary_iters += [arop_full_summary_iters]
- arop_eval_fns += [_vis_readout_maps]
- return arop, arop_summary_iters, arop_eval_fns
-
-def _add_summaries(m, args, summary_mode, arop_full_summary_iters):
- task_params = args.navtask.task_params
-
- summarize_ops = [m.lr_op, m.global_step_op, m.sample_gt_prob_op] + \
- m.loss_ops + m.acc_ops
- summarize_names = ['lr', 'global_step', 'sample_gt_prob_op'] + \
- m.loss_ops_names + ['acc_{:d}'.format(i) for i in range(len(m.acc_ops))]
- to_aggregate = [0, 0, 0] + [1]*len(m.loss_ops_names) + [1]*len(m.acc_ops)
-
- scope_name = 'summary'
- with tf.name_scope(scope_name):
- s_ops = nu.add_default_summaries(summary_mode, arop_full_summary_iters,
- summarize_ops, summarize_names,
- to_aggregate, m.action_prob_op,
- m.input_tensors, scope_name=scope_name)
- if summary_mode == 'val':
- arop, arop_summary_iters, arop_eval_fns = _summary_vis(
- m, task_params.batch_size, task_params.num_steps,
- arop_full_summary_iters)
- s_ops.additional_return_ops += arop
- s_ops.arop_summary_iters += arop_summary_iters
- s_ops.arop_eval_fns += arop_eval_fns
-
- if args.arch.readout_maps:
- arop, arop_summary_iters, arop_eval_fns = _summary_readout_maps(
- m, task_params.num_steps, arop_full_summary_iters)
- s_ops.additional_return_ops += arop
- s_ops.arop_summary_iters += arop_summary_iters
- s_ops.arop_eval_fns += arop_eval_fns
-
- return s_ops
diff --git a/research/cognitive_mapping_and_planning/tfcode/cmp_utils.py b/research/cognitive_mapping_and_planning/tfcode/cmp_utils.py
deleted file mode 100644
index 6d87c697b4b29128c8b8a42caac27aeb4d657ec6..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/tfcode/cmp_utils.py
+++ /dev/null
@@ -1,164 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Utility functions for setting up the CMP graph.
-"""
-
-import os, numpy as np
-import matplotlib.pyplot as plt
-
-
-import tensorflow as tf
-
-from tensorflow.contrib import slim
-from tensorflow.contrib.slim import arg_scope
-import logging
-from src import utils
-import src.file_utils as fu
-from tfcode import tf_utils
-
-resnet_v2 = tf_utils.resnet_v2
-custom_residual_block = tf_utils.custom_residual_block
-
-def value_iteration_network(
- fr, num_iters, val_neurons, action_neurons, kernel_size, share_wts=False,
- name='vin', wt_decay=0.0001, activation_fn=None, shape_aware=False):
- """
- Constructs a Value Iteration Network, convolutions and max pooling across
- channels.
- Input:
- fr: NxWxHxC
- val_neurons: Number of channels for maintaining the value.
- action_neurons: Computes action_neurons * val_neurons at each iteration to
- max pool over.
- Output:
- value image: NxHxWx(val_neurons)
- """
- init_var = np.sqrt(2.0/(kernel_size**2)/(val_neurons*action_neurons))
- vals = []
- with tf.variable_scope(name) as varscope:
- if shape_aware == False:
- fr_shape = tf.unstack(tf.shape(fr))
- val_shape = tf.stack(fr_shape[:-1] + [val_neurons])
- val = tf.zeros(val_shape, name='val_init')
- else:
- val = tf.expand_dims(tf.zeros_like(fr[:,:,:,0]), dim=-1) * \
- tf.constant(0., dtype=tf.float32, shape=[1,1,1,val_neurons])
- val_shape = tf.shape(val)
- vals.append(val)
- for i in range(num_iters):
- if share_wts:
- # The first Value Iteration maybe special, so it can have its own
- # paramterss.
- scope = 'conv'
- if i == 0: scope = 'conv_0'
- if i > 1: varscope.reuse_variables()
- else:
- scope = 'conv_{:d}'.format(i)
- val = slim.conv2d(tf.concat([val, fr], 3, name='concat_{:d}'.format(i)),
- num_outputs=action_neurons*val_neurons,
- kernel_size=kernel_size, stride=1, activation_fn=activation_fn,
- scope=scope, normalizer_fn=None,
- weights_regularizer=slim.l2_regularizer(wt_decay),
- weights_initializer=tf.random_normal_initializer(stddev=init_var),
- biases_initializer=tf.zeros_initializer())
- val = tf.reshape(val, [-1, action_neurons*val_neurons, 1, 1],
- name='re_{:d}'.format(i))
- val = slim.max_pool2d(val, kernel_size=[action_neurons,1],
- stride=[action_neurons,1], padding='VALID',
- scope='val_{:d}'.format(i))
- val = tf.reshape(val, val_shape, name='unre_{:d}'.format(i))
- vals.append(val)
- return val, vals
-
-
-def rotate_preds(loc_on_map, relative_theta, map_size, preds,
- output_valid_mask):
- with tf.name_scope('rotate'):
- flow_op = tf_utils.get_flow(loc_on_map, relative_theta, map_size=map_size)
- if type(preds) != list:
- rotated_preds, valid_mask_warps = tf_utils.dense_resample(preds, flow_op,
- output_valid_mask)
- else:
- rotated_preds = [] ;valid_mask_warps = []
- for pred in preds:
- rotated_pred, valid_mask_warp = tf_utils.dense_resample(pred, flow_op,
- output_valid_mask)
- rotated_preds.append(rotated_pred)
- valid_mask_warps.append(valid_mask_warp)
- return rotated_preds, valid_mask_warps
-
-def get_visual_frustum(map_size, shape_like, expand_dims=[0,0]):
- with tf.name_scope('visual_frustum'):
- l = np.tril(np.ones(map_size)) ;l = l + l[:,::-1]
- l = (l == 2).astype(np.float32)
- for e in expand_dims:
- l = np.expand_dims(l, axis=e)
- confs_probs = tf.constant(l, dtype=tf.float32)
- confs_probs = tf.ones_like(shape_like, dtype=tf.float32) * confs_probs
- return confs_probs
-
-def deconv(x, is_training, wt_decay, neurons, strides, layers_per_block,
- kernel_size, conv_fn, name, offset=0):
- """Generates a up sampling network with residual connections.
- """
- batch_norm_param = {'center': True, 'scale': True,
- 'activation_fn': tf.nn.relu,
- 'is_training': is_training}
- outs = []
- for i, (neuron, stride) in enumerate(zip(neurons, strides)):
- for s in range(layers_per_block):
- scope = '{:s}_{:d}_{:d}'.format(name, i+1+offset,s+1)
- x = custom_residual_block(x, neuron, kernel_size, stride, scope,
- is_training, wt_decay, use_residual=True,
- residual_stride_conv=True, conv_fn=conv_fn,
- batch_norm_param=batch_norm_param)
- stride = 1
- outs.append((x,True))
- return x, outs
-
-def fr_v2(x, output_neurons, inside_neurons, is_training, name='fr',
- wt_decay=0.0001, stride=1, updates_collections=tf.GraphKeys.UPDATE_OPS):
- """Performs fusion of information between the map and the reward map.
- Inputs
- x: NxHxWxC1
-
- Outputs
- fr map: NxHxWx(output_neurons)
- """
- if type(stride) != list:
- stride = [stride]
- with slim.arg_scope(resnet_v2.resnet_utils.resnet_arg_scope(
- is_training=is_training, weight_decay=wt_decay)):
- with slim.arg_scope([slim.batch_norm], updates_collections=updates_collections) as arg_sc:
- # Change the updates_collections for the conv normalizer_params to None
- for i in range(len(arg_sc.keys())):
- if 'convolution' in arg_sc.keys()[i]:
- arg_sc.values()[i]['normalizer_params']['updates_collections'] = updates_collections
- with slim.arg_scope(arg_sc):
- bottleneck = resnet_v2.bottleneck
- blocks = []
- for i, s in enumerate(stride):
- b = resnet_v2.resnet_utils.Block(
- 'block{:d}'.format(i + 1), bottleneck, [{
- 'depth': output_neurons,
- 'depth_bottleneck': inside_neurons,
- 'stride': stride[i]
- }])
- blocks.append(b)
- x, outs = resnet_v2.resnet_v2(x, blocks, num_classes=None, global_pool=False,
- output_stride=None, include_root_block=False,
- reuse=False, scope=name)
- return x, outs
diff --git a/research/cognitive_mapping_and_planning/tfcode/nav_utils.py b/research/cognitive_mapping_and_planning/tfcode/nav_utils.py
deleted file mode 100644
index 2f764f33df91a80f6539dcbae1e0fa7093becd29..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/tfcode/nav_utils.py
+++ /dev/null
@@ -1,435 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Various losses for training navigation agents.
-
-Defines various loss functions for navigation agents,
-compute_losses_multi_or.
-"""
-
-import os, numpy as np
-import matplotlib.pyplot as plt
-
-
-import tensorflow as tf
-
-from tensorflow.contrib import slim
-from tensorflow.contrib.slim import arg_scope
-from tensorflow.contrib.slim.nets import resnet_v2
-from tensorflow.python.training import moving_averages
-import logging
-from src import utils
-import src.file_utils as fu
-from tfcode import tf_utils
-
-
-def compute_losses_multi_or(logits, actions_one_hot, weights=None,
- num_actions=-1, data_loss_wt=1., reg_loss_wt=1.,
- ewma_decay=0.99, reg_loss_op=None):
- assert(num_actions > 0), 'num_actions must be specified and must be > 0.'
-
- with tf.name_scope('loss'):
- if weights is None:
- weight = tf.ones_like(actions_one_hot, dtype=tf.float32, name='weight')
-
- actions_one_hot = tf.cast(tf.reshape(actions_one_hot, [-1, num_actions],
- 're_actions_one_hot'), tf.float32)
- weights = tf.reduce_sum(tf.reshape(weights, [-1, num_actions], 're_weight'),
- reduction_indices=1)
- total = tf.reduce_sum(weights)
-
- action_prob = tf.nn.softmax(logits)
- action_prob = tf.reduce_sum(tf.multiply(action_prob, actions_one_hot),
- reduction_indices=1)
- example_loss = -tf.log(tf.maximum(tf.constant(1e-4), action_prob))
-
- data_loss_op = tf.reduce_sum(example_loss * weights) / total
- if reg_loss_op is None:
- if reg_loss_wt > 0:
- reg_loss_op = tf.add_n(tf.losses.get_regularization_losses())
- else:
- reg_loss_op = tf.constant(0.)
-
- if reg_loss_wt > 0:
- total_loss_op = data_loss_wt*data_loss_op + reg_loss_wt*reg_loss_op
- else:
- total_loss_op = data_loss_wt*data_loss_op
-
- is_correct = tf.cast(tf.greater(action_prob, 0.5, name='pred_class'), tf.float32)
- acc_op = tf.reduce_sum(is_correct*weights) / total
-
- ewma_acc_op = moving_averages.weighted_moving_average(
- acc_op, ewma_decay, weight=total, name='ewma_acc')
-
- acc_ops = [ewma_acc_op]
-
- return reg_loss_op, data_loss_op, total_loss_op, acc_ops
-
-
-def get_repr_from_image(images_reshaped, modalities, data_augment, encoder,
- freeze_conv, wt_decay, is_training):
- # Pass image through lots of convolutional layers, to obtain pool5
- if modalities == ['rgb']:
- with tf.name_scope('pre_rgb'):
- x = (images_reshaped + 128.) / 255. # Convert to brightness between 0 and 1.
- if data_augment.relight and is_training:
- x = tf_utils.distort_image(x, fast_mode=data_augment.relight_fast)
- x = (x-0.5)*2.0
- scope_name = encoder
- elif modalities == ['depth']:
- with tf.name_scope('pre_d'):
- d_image = images_reshaped
- x = 2*(d_image[...,0] - 80.0)/100.0
- y = d_image[...,1]
- d_image = tf.concat([tf.expand_dims(x, -1), tf.expand_dims(y, -1)], 3)
- x = d_image
- scope_name = 'd_'+encoder
-
- resnet_is_training = is_training and (not freeze_conv)
- with slim.arg_scope(resnet_v2.resnet_utils.resnet_arg_scope(resnet_is_training)):
- fn = getattr(tf_utils, encoder)
- x, end_points = fn(x, num_classes=None, global_pool=False,
- output_stride=None, reuse=None,
- scope=scope_name)
- vars_ = slim.get_variables_to_restore()
-
- conv_feat = x
- return conv_feat, vars_
-
-def default_train_step_kwargs(m, obj, logdir, rng_seed, is_chief, num_steps,
- iters, train_display_interval,
- dagger_sample_bn_false):
- train_step_kwargs = {}
- train_step_kwargs['obj'] = obj
- train_step_kwargs['m'] = m
-
- # rng_data has 2 independent rngs, one for sampling episodes and one for
- # sampling perturbs (so that we can make results reproducible.
- train_step_kwargs['rng_data'] = [np.random.RandomState(rng_seed),
- np.random.RandomState(rng_seed)]
- train_step_kwargs['rng_action'] = np.random.RandomState(rng_seed)
- if is_chief:
- train_step_kwargs['writer'] = tf.summary.FileWriter(logdir) #, m.tf_graph)
- else:
- train_step_kwargs['writer'] = None
- train_step_kwargs['iters'] = iters
- train_step_kwargs['train_display_interval'] = train_display_interval
- train_step_kwargs['num_steps'] = num_steps
- train_step_kwargs['logdir'] = logdir
- train_step_kwargs['dagger_sample_bn_false'] = dagger_sample_bn_false
- return train_step_kwargs
-
-# Utilities for visualizing and analysing validation output.
-def save_d_at_t(outputs, global_step, output_dir, metric_summary, N):
- """Save distance to goal at all time steps.
-
- Args:
- outputs : [gt_dist_to_goal].
- global_step : number of iterations.
- output_dir : output directory.
- metric_summary : to append scalars to summary.
- N : number of outputs to process.
-
- """
- d_at_t = np.concatenate(map(lambda x: x[0][:,:,0]*1, outputs), axis=0)
- fig, axes = utils.subplot(plt, (1,1), (5,5))
- axes.plot(np.arange(d_at_t.shape[1]), np.mean(d_at_t, axis=0), 'r.')
- axes.set_xlabel('time step')
- axes.set_ylabel('dist to next goal')
- axes.grid('on')
- file_name = os.path.join(output_dir, 'dist_at_t_{:d}.png'.format(global_step))
- with fu.fopen(file_name, 'w') as f:
- fig.savefig(f, bbox_inches='tight', transparent=True, pad_inches=0)
- file_name = os.path.join(output_dir, 'dist_at_t_{:d}.pkl'.format(global_step))
- utils.save_variables(file_name, [d_at_t], ['d_at_t'], overwrite=True)
- plt.close(fig)
- return None
-
-def save_all(outputs, global_step, output_dir, metric_summary, N):
- """Save numerous statistics.
-
- Args:
- outputs : [locs, goal_loc, gt_dist_to_goal, node_ids, perturbs]
- global_step : number of iterations.
- output_dir : output directory.
- metric_summary : to append scalars to summary.
- N : number of outputs to process.
- """
- all_locs = np.concatenate(map(lambda x: x[0], outputs), axis=0)
- all_goal_locs = np.concatenate(map(lambda x: x[1], outputs), axis=0)
- all_d_at_t = np.concatenate(map(lambda x: x[2][:,:,0]*1, outputs), axis=0)
- all_node_ids = np.concatenate(map(lambda x: x[3], outputs), axis=0)
- all_perturbs = np.concatenate(map(lambda x: x[4], outputs), axis=0)
-
- file_name = os.path.join(output_dir, 'all_locs_at_t_{:d}.pkl'.format(global_step))
- vars = [all_locs, all_goal_locs, all_d_at_t, all_node_ids, all_perturbs]
- var_names = ['all_locs', 'all_goal_locs', 'all_d_at_t', 'all_node_ids', 'all_perturbs']
- utils.save_variables(file_name, vars, var_names, overwrite=True)
- return None
-
-def eval_ap(outputs, global_step, output_dir, metric_summary, N, num_classes=4):
- """Processes the collected outputs to compute AP for action prediction.
-
- Args:
- outputs : [logits, labels]
- global_step : global_step.
- output_dir : where to store results.
- metric_summary : summary object to add summaries to.
- N : number of outputs to process.
- num_classes : number of classes to compute AP over, and to reshape tensors.
- """
- if N >= 0:
- outputs = outputs[:N]
- logits = np.concatenate(map(lambda x: x[0], outputs), axis=0).reshape((-1, num_classes))
- labels = np.concatenate(map(lambda x: x[1], outputs), axis=0).reshape((-1, num_classes))
- aps = []
- for i in range(logits.shape[1]):
- ap, rec, prec = utils.calc_pr(labels[:,i], logits[:,i])
- ap = ap[0]
- tf_utils.add_value_to_summary(metric_summary, 'aps/ap_{:d}: '.format(i), ap)
- aps.append(ap)
- return aps
-
-def eval_dist(outputs, global_step, output_dir, metric_summary, N):
- """Processes the collected outputs during validation to
- 1. Plot the distance over time curve.
- 2. Compute mean and median distances.
- 3. Plots histogram of end distances.
-
- Args:
- outputs : [locs, goal_loc, gt_dist_to_goal].
- global_step : global_step.
- output_dir : where to store results.
- metric_summary : summary object to add summaries to.
- N : number of outputs to process.
- """
- SUCCESS_THRESH = 3
- if N >= 0:
- outputs = outputs[:N]
-
- # Plot distance at time t.
- d_at_t = []
- for i in range(len(outputs)):
- locs, goal_loc, gt_dist_to_goal = outputs[i]
- d_at_t.append(gt_dist_to_goal[:,:,0]*1)
-
- # Plot the distance.
- fig, axes = utils.subplot(plt, (1,1), (5,5))
- d_at_t = np.concatenate(d_at_t, axis=0)
- axes.plot(np.arange(d_at_t.shape[1]), np.mean(d_at_t, axis=0), 'r.')
- axes.set_xlabel('time step')
- axes.set_ylabel('dist to next goal')
- axes.grid('on')
- file_name = os.path.join(output_dir, 'dist_at_t_{:d}.png'.format(global_step))
- with fu.fopen(file_name, 'w') as f:
- fig.savefig(f, bbox_inches='tight', transparent=True, pad_inches=0)
- file_name = os.path.join(output_dir, 'dist_at_t_{:d}.pkl'.format(global_step))
- utils.save_variables(file_name, [d_at_t], ['d_at_t'], overwrite=True)
- plt.close(fig)
-
- # Plot the trajectories and the init_distance and final distance.
- d_inits = []
- d_ends = []
- for i in range(len(outputs)):
- locs, goal_loc, gt_dist_to_goal = outputs[i]
- d_inits.append(gt_dist_to_goal[:,0,0]*1)
- d_ends.append(gt_dist_to_goal[:,-1,0]*1)
-
- # Plot the distance.
- fig, axes = utils.subplot(plt, (1,1), (5,5))
- d_inits = np.concatenate(d_inits, axis=0)
- d_ends = np.concatenate(d_ends, axis=0)
- axes.plot(d_inits+np.random.rand(*(d_inits.shape))-0.5,
- d_ends+np.random.rand(*(d_ends.shape))-0.5, '.', mec='red', mew=1.0)
- axes.set_xlabel('init dist'); axes.set_ylabel('final dist');
- axes.grid('on'); axes.axis('equal');
- title_str = 'mean: {:0.1f}, 50: {:0.1f}, 75: {:0.2f}, s: {:0.1f}'
- title_str = title_str.format(
- np.mean(d_ends), np.median(d_ends), np.percentile(d_ends, q=75),
- 100*(np.mean(d_ends <= SUCCESS_THRESH)))
- axes.set_title(title_str)
- file_name = os.path.join(output_dir, 'dist_{:d}.png'.format(global_step))
- with fu.fopen(file_name, 'w') as f:
- fig.savefig(f, bbox_inches='tight', transparent=True, pad_inches=0)
-
- file_name = os.path.join(output_dir, 'dist_{:d}.pkl'.format(global_step))
- utils.save_variables(file_name, [d_inits, d_ends], ['d_inits', 'd_ends'],
- overwrite=True)
- plt.close(fig)
-
- # Plot the histogram of the end_distance.
- with plt.style.context('seaborn-white'):
- d_ends_ = np.sort(d_ends)
- d_inits_ = np.sort(d_inits)
- leg = [];
- fig, ax = utils.subplot(plt, (1,1), (5,5))
- ax.grid('on')
- ax.set_xlabel('Distance from goal'); ax.xaxis.label.set_fontsize(16);
- ax.set_ylabel('Fraction of data'); ax.yaxis.label.set_fontsize(16);
- ax.plot(d_ends_, np.arange(d_ends_.size)*1./d_ends_.size, 'r')
- ax.plot(d_inits_, np.arange(d_inits_.size)*1./d_inits_.size, 'k')
- leg.append('Final'); leg.append('Init');
- ax.legend(leg, fontsize='x-large');
- ax.set_axis_on()
- title_str = 'mean: {:0.1f}, 50: {:0.1f}, 75: {:0.2f}, s: {:0.1f}'
- title_str = title_str.format(
- np.mean(d_ends), np.median(d_ends), np.percentile(d_ends, q=75),
- 100*(np.mean(d_ends <= SUCCESS_THRESH)))
- ax.set_title(title_str)
- file_name = os.path.join(output_dir, 'dist_hist_{:d}.png'.format(global_step))
- with fu.fopen(file_name, 'w') as f:
- fig.savefig(f, bbox_inches='tight', transparent=True, pad_inches=0)
-
- # Log distance metrics.
- tf_utils.add_value_to_summary(metric_summary, 'dists/success_init: ',
- 100*(np.mean(d_inits <= SUCCESS_THRESH)))
- tf_utils.add_value_to_summary(metric_summary, 'dists/success_end: ',
- 100*(np.mean(d_ends <= SUCCESS_THRESH)))
- tf_utils.add_value_to_summary(metric_summary, 'dists/dist_init (75): ',
- np.percentile(d_inits, q=75))
- tf_utils.add_value_to_summary(metric_summary, 'dists/dist_end (75): ',
- np.percentile(d_ends, q=75))
- tf_utils.add_value_to_summary(metric_summary, 'dists/dist_init (median): ',
- np.median(d_inits))
- tf_utils.add_value_to_summary(metric_summary, 'dists/dist_end (median): ',
- np.median(d_ends))
- tf_utils.add_value_to_summary(metric_summary, 'dists/dist_init (mean): ',
- np.mean(d_inits))
- tf_utils.add_value_to_summary(metric_summary, 'dists/dist_end (mean): ',
- np.mean(d_ends))
- return np.median(d_inits), np.median(d_ends), np.mean(d_inits), np.mean(d_ends), \
- np.percentile(d_inits, q=75), np.percentile(d_ends, q=75), \
- 100*(np.mean(d_inits) <= SUCCESS_THRESH), 100*(np.mean(d_ends) <= SUCCESS_THRESH)
-
-def plot_trajectories(outputs, global_step, output_dir, metric_summary, N):
- """Processes the collected outputs during validation to plot the trajectories
- in the top view.
-
- Args:
- outputs : [locs, orig_maps, goal_loc].
- global_step : global_step.
- output_dir : where to store results.
- metric_summary : summary object to add summaries to.
- N : number of outputs to process.
- """
- if N >= 0:
- outputs = outputs[:N]
- N = len(outputs)
-
- plt.set_cmap('gray')
- fig, axes = utils.subplot(plt, (N, outputs[0][1].shape[0]), (5,5))
- axes = axes.ravel()[::-1].tolist()
- for i in range(N):
- locs, orig_maps, goal_loc = outputs[i]
- is_semantic = np.isnan(goal_loc[0,0,1])
- for j in range(orig_maps.shape[0]):
- ax = axes.pop();
- ax.plot(locs[j,0,0], locs[j,0,1], 'ys')
- # Plot one by one, so that they come in different colors.
- for k in range(goal_loc.shape[1]):
- if not is_semantic:
- ax.plot(goal_loc[j,k,0], goal_loc[j,k,1], 's')
- if False:
- ax.plot(locs[j,:,0], locs[j,:,1], 'r.', ms=3)
- ax.imshow(orig_maps[j,0,:,:,0], origin='lower')
- ax.set_axis_off();
- else:
- ax.scatter(locs[j,:,0], locs[j,:,1], c=np.arange(locs.shape[1]),
- cmap='jet', s=10, lw=0)
- ax.imshow(orig_maps[j,0,:,:,0], origin='lower', vmin=-1.0, vmax=2.0)
- if not is_semantic:
- xymin = np.minimum(np.min(goal_loc[j,:,:], axis=0), np.min(locs[j,:,:], axis=0))
- xymax = np.maximum(np.max(goal_loc[j,:,:], axis=0), np.max(locs[j,:,:], axis=0))
- else:
- xymin = np.min(locs[j,:,:], axis=0)
- xymax = np.max(locs[j,:,:], axis=0)
- xy1 = (xymax+xymin)/2. - np.maximum(np.max(xymax-xymin), 12)
- xy2 = (xymax+xymin)/2. + np.maximum(np.max(xymax-xymin), 12)
- ax.set_xlim([xy1[0], xy2[0]])
- ax.set_ylim([xy1[1], xy2[1]])
- ax.set_axis_off()
- file_name = os.path.join(output_dir, 'trajectory_{:d}.png'.format(global_step))
- with fu.fopen(file_name, 'w') as f:
- fig.savefig(f, bbox_inches='tight', transparent=True, pad_inches=0)
- plt.close(fig)
- return None
-
-def add_default_summaries(mode, arop_full_summary_iters, summarize_ops,
- summarize_names, to_aggregate, action_prob_op,
- input_tensors, scope_name):
- assert(mode == 'train' or mode == 'val' or mode == 'test'), \
- 'add_default_summaries mode is neither train or val or test.'
-
- s_ops = tf_utils.get_default_summary_ops()
-
- if mode == 'train':
- s_ops.summary_ops, s_ops.print_summary_ops, additional_return_ops, \
- arop_summary_iters, arop_eval_fns = tf_utils.simple_summaries(
- summarize_ops, summarize_names, mode, to_aggregate=False,
- scope_name=scope_name)
- s_ops.additional_return_ops += additional_return_ops
- s_ops.arop_summary_iters += arop_summary_iters
- s_ops.arop_eval_fns += arop_eval_fns
- elif mode == 'val':
- s_ops.summary_ops, s_ops.print_summary_ops, additional_return_ops, \
- arop_summary_iters, arop_eval_fns = tf_utils.simple_summaries(
- summarize_ops, summarize_names, mode, to_aggregate=to_aggregate,
- scope_name=scope_name)
- s_ops.additional_return_ops += additional_return_ops
- s_ops.arop_summary_iters += arop_summary_iters
- s_ops.arop_eval_fns += arop_eval_fns
-
- elif mode == 'test':
- s_ops.summary_ops, s_ops.print_summary_ops, additional_return_ops, \
- arop_summary_iters, arop_eval_fns = tf_utils.simple_summaries(
- [], [], mode, to_aggregate=[], scope_name=scope_name)
- s_ops.additional_return_ops += additional_return_ops
- s_ops.arop_summary_iters += arop_summary_iters
- s_ops.arop_eval_fns += arop_eval_fns
-
-
- if mode == 'val':
- arop = s_ops.additional_return_ops
- arop += [[action_prob_op, input_tensors['train']['action']]]
- arop += [[input_tensors['step']['loc_on_map'],
- input_tensors['common']['goal_loc'],
- input_tensors['step']['gt_dist_to_goal']]]
- arop += [[input_tensors['step']['loc_on_map'],
- input_tensors['common']['orig_maps'],
- input_tensors['common']['goal_loc']]]
- s_ops.arop_summary_iters += [-1, arop_full_summary_iters,
- arop_full_summary_iters]
- s_ops.arop_eval_fns += [eval_ap, eval_dist, plot_trajectories]
-
- elif mode == 'test':
- arop = s_ops.additional_return_ops
- arop += [[input_tensors['step']['loc_on_map'],
- input_tensors['common']['goal_loc'],
- input_tensors['step']['gt_dist_to_goal']]]
- arop += [[input_tensors['step']['gt_dist_to_goal']]]
- arop += [[input_tensors['step']['loc_on_map'],
- input_tensors['common']['goal_loc'],
- input_tensors['step']['gt_dist_to_goal'],
- input_tensors['step']['node_ids'],
- input_tensors['step']['perturbs']]]
- arop += [[input_tensors['step']['loc_on_map'],
- input_tensors['common']['orig_maps'],
- input_tensors['common']['goal_loc']]]
- s_ops.arop_summary_iters += [-1, -1, -1, arop_full_summary_iters]
- s_ops.arop_eval_fns += [eval_dist, save_d_at_t, save_all,
- plot_trajectories]
- return s_ops
-
-
diff --git a/research/cognitive_mapping_and_planning/tfcode/tf_utils.py b/research/cognitive_mapping_and_planning/tfcode/tf_utils.py
deleted file mode 100644
index 5f96d8ff5ce7473f0ec49096abcbac274e6c4fcc..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/tfcode/tf_utils.py
+++ /dev/null
@@ -1,840 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import numpy as np
-import sys
-import tensorflow as tf
-import src.utils as utils
-import logging
-from tensorflow.contrib import slim
-from tensorflow.contrib.metrics.python.ops import confusion_matrix_ops
-from tensorflow.contrib.slim import arg_scope
-from tensorflow.contrib.slim.nets import resnet_v2
-from tensorflow.python.framework import dtypes
-from tensorflow.python.ops import array_ops
-from tensorflow.python.ops import check_ops
-from tensorflow.python.ops import math_ops
-from tensorflow.python.ops import variable_scope
-sys.path.insert(0, '../slim')
-from preprocessing import inception_preprocessing as ip
-
-resnet_v2_50 = resnet_v2.resnet_v2_50
-
-
-def custom_residual_block(x, neurons, kernel_size, stride, name, is_training,
- wt_decay=0.0001, use_residual=True,
- residual_stride_conv=True, conv_fn=slim.conv2d,
- batch_norm_param=None):
-
- # batch norm x and relu
- init_var = np.sqrt(2.0/(kernel_size**2)/neurons)
- with arg_scope([conv_fn],
- weights_regularizer=slim.l2_regularizer(wt_decay),
- weights_initializer=tf.random_normal_initializer(stddev=init_var),
- biases_initializer=tf.zeros_initializer()):
-
- if batch_norm_param is None:
- batch_norm_param = {'center': True, 'scale': False,
- 'activation_fn':tf.nn.relu,
- 'is_training': is_training}
-
- y = slim.batch_norm(x, scope=name+'_bn', **batch_norm_param)
-
- y = conv_fn(y, num_outputs=neurons, kernel_size=kernel_size, stride=stride,
- activation_fn=None, scope=name+'_1',
- normalizer_fn=slim.batch_norm,
- normalizer_params=batch_norm_param)
-
- y = conv_fn(y, num_outputs=neurons, kernel_size=kernel_size,
- stride=1, activation_fn=None, scope=name+'_2')
-
- if use_residual:
- if stride != 1 or x.get_shape().as_list()[-1] != neurons:
- batch_norm_param_ = dict(batch_norm_param)
- batch_norm_param_['activation_fn'] = None
- x = conv_fn(x, num_outputs=neurons, kernel_size=1,
- stride=stride if residual_stride_conv else 1,
- activation_fn=None, scope=name+'_0_1x1',
- normalizer_fn=slim.batch_norm,
- normalizer_params=batch_norm_param_)
- if not residual_stride_conv:
- x = slim.avg_pool2d(x, 1, stride=stride, scope=name+'_0_avg')
-
- y = tf.add(x, y, name=name+'_add')
-
- return y
-
-def step_gt_prob(step, step_number_op):
- # Change samping probability from 1 to -1 at step steps.
- with tf.name_scope('step_gt_prob'):
- out = tf.cond(tf.less(step_number_op, step),
- lambda: tf.constant(1.), lambda: tf.constant(-1.))
- return out
-
-def inverse_sigmoid_decay(k, global_step_op):
- with tf.name_scope('inverse_sigmoid_decay'):
- k = tf.constant(k, dtype=tf.float32)
- tmp = k*tf.exp(-tf.cast(global_step_op, tf.float32)/k)
- tmp = tmp / (1. + tmp)
- return tmp
-
-def dense_resample(im, flow_im, output_valid_mask, name='dense_resample'):
- """ Resample reward at particular locations.
- Args:
- im: ...xHxWxC matrix to sample from.
- flow_im: ...xHxWx2 matrix, samples the image using absolute offsets as given
- by the flow_im.
- """
- with tf.name_scope(name):
- valid_mask = None
-
- x, y = tf.unstack(flow_im, axis=-1)
- x = tf.cast(tf.reshape(x, [-1]), tf.float32)
- y = tf.cast(tf.reshape(y, [-1]), tf.float32)
-
- # constants
- shape = tf.unstack(tf.shape(im))
- channels = shape[-1]
- width = shape[-2]
- height = shape[-3]
- num_batch = tf.cast(tf.reduce_prod(tf.stack(shape[:-3])), 'int32')
- zero = tf.constant(0, dtype=tf.int32)
-
- # Round up and down.
- x0 = tf.cast(tf.floor(x), 'int32'); x1 = x0 + 1;
- y0 = tf.cast(tf.floor(y), 'int32'); y1 = y0 + 1;
-
- if output_valid_mask:
- valid_mask = tf.logical_and(
- tf.logical_and(tf.less_equal(x, tf.cast(width, tf.float32)-1.), tf.greater_equal(x, 0.)),
- tf.logical_and(tf.less_equal(y, tf.cast(height, tf.float32)-1.), tf.greater_equal(y, 0.)))
- valid_mask = tf.reshape(valid_mask, shape=shape[:-1] + [1])
-
- x0 = tf.clip_by_value(x0, zero, width-1)
- x1 = tf.clip_by_value(x1, zero, width-1)
- y0 = tf.clip_by_value(y0, zero, height-1)
- y1 = tf.clip_by_value(y1, zero, height-1)
-
- dim2 = width; dim1 = width * height;
-
- # Create base index
- base = tf.reshape(tf.range(num_batch) * dim1, shape=[-1,1])
- base = tf.reshape(tf.tile(base, [1, height*width]), shape=[-1])
-
- base_y0 = base + y0 * dim2
- base_y1 = base + y1 * dim2
- idx_a = base_y0 + x0
- idx_b = base_y1 + x0
- idx_c = base_y0 + x1
- idx_d = base_y1 + x1
-
- # use indices to lookup pixels in the flat image and restore channels dim
- sh = tf.stack([tf.constant(-1,dtype=tf.int32), channels])
- im_flat = tf.cast(tf.reshape(im, sh), dtype=tf.float32)
- pixel_a = tf.gather(im_flat, idx_a)
- pixel_b = tf.gather(im_flat, idx_b)
- pixel_c = tf.gather(im_flat, idx_c)
- pixel_d = tf.gather(im_flat, idx_d)
-
- # and finally calculate interpolated values
- x1_f = tf.to_float(x1)
- y1_f = tf.to_float(y1)
-
- wa = tf.expand_dims(((x1_f - x) * (y1_f - y)), 1)
- wb = tf.expand_dims((x1_f - x) * (1.0 - (y1_f - y)), 1)
- wc = tf.expand_dims(((1.0 - (x1_f - x)) * (y1_f - y)), 1)
- wd = tf.expand_dims(((1.0 - (x1_f - x)) * (1.0 - (y1_f - y))), 1)
-
- output = tf.add_n([wa * pixel_a, wb * pixel_b, wc * pixel_c, wd * pixel_d])
- output = tf.reshape(output, shape=tf.shape(im))
- return output, valid_mask
-
-def get_flow(t, theta, map_size, name_scope='gen_flow'):
- """
- Rotates the map by theta and translates the rotated map by t.
-
- Assume that the robot rotates by an angle theta and then moves forward by
- translation t. This function returns the flow field field. For every pixel in
- the new image it tells us which pixel in the original image it came from:
- NewI(x, y) = OldI(flow_x(x,y), flow_y(x,y)).
-
- Assume there is a point p in the original image. Robot rotates by R and moves
- forward by t. p1 = Rt*p; p2 = p1 - t; (the world moves in opposite direction.
- So, p2 = Rt*p - t, thus p2 came from R*(p2+t), which is what this function
- calculates.
-
- t: ... x 2 (translation for B batches of N motions each).
- theta: ... x 1 (rotation for B batches of N motions each).
-
- Output: ... x map_size x map_size x 2
- """
-
- with tf.name_scope(name_scope):
- tx, ty = tf.unstack(tf.reshape(t, shape=[-1, 1, 1, 1, 2]), axis=4)
- theta = tf.reshape(theta, shape=[-1, 1, 1, 1])
- c = tf.constant((map_size-1.)/2., dtype=tf.float32)
-
- x, y = np.meshgrid(np.arange(map_size), np.arange(map_size))
- x = tf.constant(x[np.newaxis, :, :, np.newaxis], dtype=tf.float32, name='x',
- shape=[1, map_size, map_size, 1])
- y = tf.constant(y[np.newaxis, :, :, np.newaxis], dtype=tf.float32, name='y',
- shape=[1,map_size, map_size, 1])
-
- x = x-(-tx+c)
- y = y-(-ty+c)
-
- sin_theta = tf.sin(theta)
- cos_theta = tf.cos(theta)
- xr = cos_theta*x - sin_theta*y
- yr = sin_theta*x + cos_theta*y
-
- xr = xr + c
- yr = yr + c
-
- flow = tf.stack([xr, yr], axis=-1)
- sh = tf.unstack(tf.shape(t), axis=0)
- sh = tf.stack(sh[:-1]+[tf.constant(_, dtype=tf.int32) for _ in [map_size, map_size, 2]])
- flow = tf.reshape(flow, shape=sh)
- return flow
-
-def distort_image(im, fast_mode=False):
- # All images in the same batch are transformed the same way, but over
- # iterations you see different distortions.
- # im should be float with values between 0 and 1.
- im_ = tf.reshape(im, shape=(-1,1,3))
- im_ = ip.apply_with_random_selector(
- im_, lambda x, ordering: ip.distort_color(x, ordering, fast_mode),
- num_cases=4)
- im_ = tf.reshape(im_, tf.shape(im))
- return im_
-
-def fc_network(x, neurons, wt_decay, name, num_pred=None, offset=0,
- batch_norm_param=None, dropout_ratio=0.0, is_training=None):
- if dropout_ratio > 0:
- assert(is_training is not None), \
- 'is_training needs to be defined when trainnig with dropout.'
-
- repr = []
- for i, neuron in enumerate(neurons):
- init_var = np.sqrt(2.0/neuron)
- if batch_norm_param is not None:
- x = slim.fully_connected(x, neuron, activation_fn=None,
- weights_initializer=tf.random_normal_initializer(stddev=init_var),
- weights_regularizer=slim.l2_regularizer(wt_decay),
- normalizer_fn=slim.batch_norm,
- normalizer_params=batch_norm_param,
- biases_initializer=tf.zeros_initializer(),
- scope='{:s}_{:d}'.format(name, offset+i))
- else:
- x = slim.fully_connected(x, neuron, activation_fn=tf.nn.relu,
- weights_initializer=tf.random_normal_initializer(stddev=init_var),
- weights_regularizer=slim.l2_regularizer(wt_decay),
- biases_initializer=tf.zeros_initializer(),
- scope='{:s}_{:d}'.format(name, offset+i))
- if dropout_ratio > 0:
- x = slim.dropout(x, keep_prob=1-dropout_ratio, is_training=is_training,
- scope='{:s}_{:d}'.format('dropout_'+name, offset+i))
- repr.append(x)
-
- if num_pred is not None:
- init_var = np.sqrt(2.0/num_pred)
- x = slim.fully_connected(x, num_pred,
- weights_regularizer=slim.l2_regularizer(wt_decay),
- weights_initializer=tf.random_normal_initializer(stddev=init_var),
- biases_initializer=tf.zeros_initializer(),
- activation_fn=None,
- scope='{:s}_pred'.format(name))
- return x, repr
-
-def concat_state_x_list(f, names):
- af = {}
- for i, k in enumerate(names):
- af[k] = np.concatenate([x[i] for x in f], axis=1)
- return af
-
-def concat_state_x(f, names):
- af = {}
- for k in names:
- af[k] = np.concatenate([x[k] for x in f], axis=1)
- # af[k] = np.swapaxes(af[k], 0, 1)
- return af
-
-def sample_action(rng, action_probs, optimal_action, sample_gt_prob,
- type='sample', combine_type='one_or_other'):
- optimal_action_ = optimal_action/np.sum(optimal_action+0., 1, keepdims=True)
- action_probs_ = action_probs/np.sum(action_probs+0.001, 1, keepdims=True)
- batch_size = action_probs_.shape[0]
-
- action = np.zeros((batch_size), dtype=np.int32)
- action_sample_wt = np.zeros((batch_size), dtype=np.float32)
- if combine_type == 'add':
- sample_gt_prob_ = np.minimum(np.maximum(sample_gt_prob, 0.), 1.)
-
- for i in range(batch_size):
- if combine_type == 'one_or_other':
- sample_gt = rng.rand() < sample_gt_prob
- if sample_gt: distr_ = optimal_action_[i,:]*1.
- else: distr_ = action_probs_[i,:]*1.
- elif combine_type == 'add':
- distr_ = optimal_action_[i,:]*sample_gt_prob_ + \
- (1.-sample_gt_prob_)*action_probs_[i,:]
- distr_ = distr_ / np.sum(distr_)
-
- if type == 'sample':
- action[i] = np.argmax(rng.multinomial(1, distr_, size=1))
- elif type == 'argmax':
- action[i] = np.argmax(distr_)
- action_sample_wt[i] = action_probs_[i, action[i]] / distr_[action[i]]
- return action, action_sample_wt
-
-def train_step_custom_online_sampling(sess, train_op, global_step,
- train_step_kwargs, mode='train'):
- m = train_step_kwargs['m']
- obj = train_step_kwargs['obj']
- rng_data = train_step_kwargs['rng_data']
- rng_action = train_step_kwargs['rng_action']
- writer = train_step_kwargs['writer']
- iters = train_step_kwargs['iters']
- num_steps = train_step_kwargs['num_steps']
- logdir = train_step_kwargs['logdir']
- dagger_sample_bn_false = train_step_kwargs['dagger_sample_bn_false']
- train_display_interval = train_step_kwargs['train_display_interval']
- if 'outputs' not in m.train_ops:
- m.train_ops['outputs'] = []
-
- s_ops = m.summary_ops[mode]
- val_additional_ops = []
-
- # Print all variables here.
- if False:
- v = tf.get_collection(tf.GraphKeys.VARIABLES)
- v_op = [_.value() for _ in v]
- v_op_value = sess.run(v_op)
-
- filter = lambda x, y: 'Adam' in x.name
- # filter = lambda x, y: np.is_any_nan(y)
- ind = [i for i, (_, __) in enumerate(zip(v, v_op_value)) if filter(_, __)]
- v = [v[i] for i in ind]
- v_op_value = [v_op_value[i] for i in ind]
-
- for i in range(len(v)):
- logging.info('XXXX: variable: %30s, is_any_nan: %5s, norm: %f.',
- v[i].name, np.any(np.isnan(v_op_value[i])),
- np.linalg.norm(v_op_value[i]))
-
- tt = utils.Timer()
- for i in range(iters):
- tt.tic()
- # Sample a room.
- e = obj.sample_env(rng_data)
-
- # Initialize the agent.
- init_env_state = e.reset(rng_data)
-
- # Get and process the common data.
- input = e.get_common_data()
- input = e.pre_common_data(input)
- feed_dict = prepare_feed_dict(m.input_tensors['common'], input)
- if dagger_sample_bn_false:
- feed_dict[m.train_ops['batch_norm_is_training_op']] = False
- common_data = sess.run(m.train_ops['common'], feed_dict=feed_dict)
-
- states = []
- state_features = []
- state_targets = []
- net_state_to_input = []
- step_data_cache = []
- executed_actions = []
- rewards = []
- action_sample_wts = []
- states.append(init_env_state)
-
- net_state = sess.run(m.train_ops['init_state'], feed_dict=feed_dict)
- net_state = dict(zip(m.train_ops['state_names'], net_state))
- net_state_to_input.append(net_state)
- for j in range(num_steps):
- f = e.get_features(states[j], j)
- f = e.pre_features(f)
- f.update(net_state)
- f['step_number'] = np.ones((1,1,1), dtype=np.int32)*j
- state_features.append(f)
-
- feed_dict = prepare_feed_dict(m.input_tensors['step'], state_features[-1])
- optimal_action = e.get_optimal_action(states[j], j)
- for x, v in zip(m.train_ops['common'], common_data):
- feed_dict[x] = v
- if dagger_sample_bn_false:
- feed_dict[m.train_ops['batch_norm_is_training_op']] = False
- outs = sess.run([m.train_ops['step'], m.sample_gt_prob_op,
- m.train_ops['step_data_cache'],
- m.train_ops['updated_state'],
- m.train_ops['outputs']], feed_dict=feed_dict)
- action_probs = outs[0]
- sample_gt_prob = outs[1]
- step_data_cache.append(dict(zip(m.train_ops['step_data_cache'], outs[2])))
- net_state = outs[3]
- if hasattr(e, 'update_state'):
- outputs = outs[4]
- outputs = dict(zip(m.train_ops['output_names'], outputs))
- e.update_state(outputs, j)
- state_targets.append(e.get_targets(states[j], j))
-
- if j < num_steps-1:
- # Sample from action_probs and optimal action.
- action, action_sample_wt = sample_action(
- rng_action, action_probs, optimal_action, sample_gt_prob,
- m.sample_action_type, m.sample_action_combine_type)
- next_state, reward = e.take_action(states[j], action, j)
- executed_actions.append(action)
- states.append(next_state)
- rewards.append(reward)
- action_sample_wts.append(action_sample_wt)
- net_state = dict(zip(m.train_ops['state_names'], net_state))
- net_state_to_input.append(net_state)
-
- # Concatenate things together for training.
- rewards = np.array(rewards).T
- action_sample_wts = np.array(action_sample_wts).T
- executed_actions = np.array(executed_actions).T
- all_state_targets = concat_state_x(state_targets, e.get_targets_name())
- all_state_features = concat_state_x(state_features,
- e.get_features_name()+['step_number'])
- # all_state_net = concat_state_x(net_state_to_input,
- # m.train_ops['state_names'])
- all_step_data_cache = concat_state_x(step_data_cache,
- m.train_ops['step_data_cache'])
-
- dict_train = dict(input)
- dict_train.update(all_state_features)
- dict_train.update(all_state_targets)
- # dict_train.update(all_state_net)
- dict_train.update(net_state_to_input[0])
- dict_train.update(all_step_data_cache)
- dict_train.update({'rewards': rewards,
- 'action_sample_wts': action_sample_wts,
- 'executed_actions': executed_actions})
- feed_dict = prepare_feed_dict(m.input_tensors['train'], dict_train)
- for x in m.train_ops['step_data_cache']:
- feed_dict[x] = all_step_data_cache[x]
- if mode == 'train':
- n_step = sess.run(global_step)
-
- if np.mod(n_step, train_display_interval) == 0:
- total_loss, np_global_step, summary, print_summary = sess.run(
- [train_op, global_step, s_ops.summary_ops, s_ops.print_summary_ops],
- feed_dict=feed_dict)
- logging.error("")
- else:
- total_loss, np_global_step, summary = sess.run(
- [train_op, global_step, s_ops.summary_ops], feed_dict=feed_dict)
-
- if writer is not None and summary is not None:
- writer.add_summary(summary, np_global_step)
-
- should_stop = sess.run(m.should_stop_op)
-
- if mode != 'train':
- arop = [[] for j in range(len(s_ops.additional_return_ops))]
- for j in range(len(s_ops.additional_return_ops)):
- if s_ops.arop_summary_iters[j] < 0 or i < s_ops.arop_summary_iters[j]:
- arop[j] = s_ops.additional_return_ops[j]
- val = sess.run(arop, feed_dict=feed_dict)
- val_additional_ops.append(val)
- tt.toc(log_at=60, log_str='val timer {:d} / {:d}: '.format(i, iters),
- type='time')
-
- if mode != 'train':
- # Write the default val summaries.
- summary, print_summary, np_global_step = sess.run(
- [s_ops.summary_ops, s_ops.print_summary_ops, global_step])
- if writer is not None and summary is not None:
- writer.add_summary(summary, np_global_step)
-
- # write custom validation ops
- val_summarys = []
- val_additional_ops = zip(*val_additional_ops)
- if len(s_ops.arop_eval_fns) > 0:
- val_metric_summary = tf.summary.Summary()
- for i in range(len(s_ops.arop_eval_fns)):
- val_summary = None
- if s_ops.arop_eval_fns[i] is not None:
- val_summary = s_ops.arop_eval_fns[i](val_additional_ops[i],
- np_global_step, logdir,
- val_metric_summary,
- s_ops.arop_summary_iters[i])
- val_summarys.append(val_summary)
- if writer is not None:
- writer.add_summary(val_metric_summary, np_global_step)
-
- # Return the additional val_ops
- total_loss = (val_additional_ops, val_summarys)
- should_stop = None
-
- return total_loss, should_stop
-
-def train_step_custom_v2(sess, train_op, global_step, train_step_kwargs,
- mode='train'):
- m = train_step_kwargs['m']
- obj = train_step_kwargs['obj']
- rng = train_step_kwargs['rng']
- writer = train_step_kwargs['writer']
- iters = train_step_kwargs['iters']
- logdir = train_step_kwargs['logdir']
- train_display_interval = train_step_kwargs['train_display_interval']
-
- s_ops = m.summary_ops[mode]
- val_additional_ops = []
-
- # Print all variables here.
- if False:
- v = tf.get_collection(tf.GraphKeys.VARIABLES)
- v_op = [_.value() for _ in v]
- v_op_value = sess.run(v_op)
-
- filter = lambda x, y: 'Adam' in x.name
- # filter = lambda x, y: np.is_any_nan(y)
- ind = [i for i, (_, __) in enumerate(zip(v, v_op_value)) if filter(_, __)]
- v = [v[i] for i in ind]
- v_op_value = [v_op_value[i] for i in ind]
-
- for i in range(len(v)):
- logging.info('XXXX: variable: %30s, is_any_nan: %5s, norm: %f.',
- v[i].name, np.any(np.isnan(v_op_value[i])),
- np.linalg.norm(v_op_value[i]))
-
- tt = utils.Timer()
- for i in range(iters):
- tt.tic()
- e = obj.sample_env(rng)
- rngs = e.gen_rng(rng)
- input_data = e.gen_data(*rngs)
- input_data = e.pre_data(input_data)
- feed_dict = prepare_feed_dict(m.input_tensors, input_data)
-
- if mode == 'train':
- n_step = sess.run(global_step)
-
- if np.mod(n_step, train_display_interval) == 0:
- total_loss, np_global_step, summary, print_summary = sess.run(
- [train_op, global_step, s_ops.summary_ops, s_ops.print_summary_ops],
- feed_dict=feed_dict)
- else:
- total_loss, np_global_step, summary = sess.run(
- [train_op, global_step, s_ops.summary_ops],
- feed_dict=feed_dict)
-
- if writer is not None and summary is not None:
- writer.add_summary(summary, np_global_step)
-
- should_stop = sess.run(m.should_stop_op)
-
- if mode != 'train':
- arop = [[] for j in range(len(s_ops.additional_return_ops))]
- for j in range(len(s_ops.additional_return_ops)):
- if s_ops.arop_summary_iters[j] < 0 or i < s_ops.arop_summary_iters[j]:
- arop[j] = s_ops.additional_return_ops[j]
- val = sess.run(arop, feed_dict=feed_dict)
- val_additional_ops.append(val)
- tt.toc(log_at=60, log_str='val timer {:d} / {:d}: '.format(i, iters),
- type='time')
-
- if mode != 'train':
- # Write the default val summaries.
- summary, print_summary, np_global_step = sess.run(
- [s_ops.summary_ops, s_ops.print_summary_ops, global_step])
- if writer is not None and summary is not None:
- writer.add_summary(summary, np_global_step)
-
- # write custom validation ops
- val_summarys = []
- val_additional_ops = zip(*val_additional_ops)
- if len(s_ops.arop_eval_fns) > 0:
- val_metric_summary = tf.summary.Summary()
- for i in range(len(s_ops.arop_eval_fns)):
- val_summary = None
- if s_ops.arop_eval_fns[i] is not None:
- val_summary = s_ops.arop_eval_fns[i](val_additional_ops[i],
- np_global_step, logdir,
- val_metric_summary,
- s_ops.arop_summary_iters[i])
- val_summarys.append(val_summary)
- if writer is not None:
- writer.add_summary(val_metric_summary, np_global_step)
-
- # Return the additional val_ops
- total_loss = (val_additional_ops, val_summarys)
- should_stop = None
-
- return total_loss, should_stop
-
-def train_step_custom(sess, train_op, global_step, train_step_kwargs,
- mode='train'):
- m = train_step_kwargs['m']
- params = train_step_kwargs['params']
- rng = train_step_kwargs['rng']
- writer = train_step_kwargs['writer']
- iters = train_step_kwargs['iters']
- gen_rng = train_step_kwargs['gen_rng']
- logdir = train_step_kwargs['logdir']
- gen_data = train_step_kwargs['gen_data']
- pre_data = train_step_kwargs['pre_data']
- train_display_interval = train_step_kwargs['train_display_interval']
-
- val_additional_ops = []
- # Print all variables here.
- if False:
- v = tf.get_collection(tf.GraphKeys.VARIABLES)
- for _ in v:
- val = sess.run(_.value())
- logging.info('variable: %30s, is_any_nan: %5s, norm: %f.', _.name,
- np.any(np.isnan(val)), np.linalg.norm(val))
-
- for i in range(iters):
- rngs = gen_rng(params, rng)
- input_data = gen_data(params, *rngs)
- input_data = pre_data(params, input_data)
- feed_dict = prepare_feed_dict(m.input_tensors, input_data)
-
- if mode == 'train':
- n_step = sess.run(global_step)
-
- if np.mod(n_step, train_display_interval) == 0:
- total_loss, np_global_step, summary, print_summary = sess.run(
- [train_op, global_step, m.summary_op[mode], m.print_summary_op[mode]],
- feed_dict=feed_dict)
- else:
- total_loss, np_global_step, summary = sess.run(
- [train_op, global_step, m.summary_op[mode]],
- feed_dict=feed_dict)
-
- if writer is not None:
- writer.add_summary(summary, np_global_step)
-
- should_stop = sess.run(m.should_stop_op)
-
- if mode == 'val':
- val = sess.run(m.agg_update_op[mode] + m.additional_return_op[mode],
- feed_dict=feed_dict)
- val_additional_ops.append(val[len(m.agg_update_op[mode]):])
-
- if mode == 'val':
- summary, print_summary, np_global_step = sess.run(
- [m.summary_op[mode], m.print_summary_op[mode], global_step])
- if writer is not None:
- writer.add_summary(summary, np_global_step)
- sess.run([m.agg_reset_op[mode]])
-
- # write custom validation ops
- if m.eval_metrics_fn[mode] is not None:
- val_metric_summary = m.eval_metrics_fn[mode](val_additional_ops,
- np_global_step, logdir)
- if writer is not None:
- writer.add_summary(val_metric_summary, np_global_step)
-
- total_loss = val_additional_ops
- should_stop = None
-
- return total_loss, should_stop
-
-def setup_training(loss_op, initial_learning_rate, steps_per_decay,
- learning_rate_decay, momentum, max_steps,
- sync=False, adjust_lr_sync=True,
- num_workers=1, replica_id=0, vars_to_optimize=None,
- clip_gradient_norm=0, typ=None, momentum2=0.999,
- adam_eps=1e-8):
- if sync and adjust_lr_sync:
- initial_learning_rate = initial_learning_rate * num_workers
- max_steps = np.int(max_steps / num_workers)
- steps_per_decay = np.int(steps_per_decay / num_workers)
-
- global_step_op = slim.get_or_create_global_step()
- lr_op = tf.train.exponential_decay(initial_learning_rate,
- global_step_op, steps_per_decay, learning_rate_decay, staircase=True)
- if typ == 'sgd':
- optimizer = tf.train.MomentumOptimizer(lr_op, momentum)
- elif typ == 'adam':
- optimizer = tf.train.AdamOptimizer(learning_rate=lr_op, beta1=momentum,
- beta2=momentum2, epsilon=adam_eps)
-
- if sync:
-
- sync_optimizer = tf.train.SyncReplicasOptimizer(optimizer,
- replicas_to_aggregate=num_workers,
- replica_id=replica_id,
- total_num_replicas=num_workers)
- train_op = slim.learning.create_train_op(loss_op, sync_optimizer,
- variables_to_train=vars_to_optimize,
- clip_gradient_norm=clip_gradient_norm)
- else:
- sync_optimizer = None
- train_op = slim.learning.create_train_op(loss_op, optimizer,
- variables_to_train=vars_to_optimize,
- clip_gradient_norm=clip_gradient_norm)
- should_stop_op = tf.greater_equal(global_step_op, max_steps)
- return lr_op, global_step_op, train_op, should_stop_op, optimizer, sync_optimizer
-
-def add_value_to_summary(metric_summary, tag, val, log=True, tag_str=None):
- """Adds a scalar summary to the summary object. Optionally also logs to
- logging."""
- new_value = metric_summary.value.add();
- new_value.tag = tag
- new_value.simple_value = val
- if log:
- if tag_str is None:
- tag_str = tag + '%f'
- logging.info(tag_str, val)
-
-def add_scalar_summary_op(tensor, name=None,
- summary_key='summaries', print_summary_key='print_summaries', prefix=''):
- collections = []
- op = tf.summary.scalar(name, tensor, collections=collections)
- if summary_key != print_summary_key:
- tf.add_to_collection(summary_key, op)
-
- op = tf.Print(op, [tensor], ' {:-<25s}: '.format(name) + prefix)
- tf.add_to_collection(print_summary_key, op)
- return op
-
-def setup_inputs(inputs):
- input_tensors = {}
- input_shapes = {}
- for (name, typ, sz) in inputs:
- _ = tf.placeholder(typ, shape=sz, name=name)
- input_tensors[name] = _
- input_shapes[name] = sz
- return input_tensors, input_shapes
-
-def prepare_feed_dict(input_tensors, inputs):
- feed_dict = {}
- for n in input_tensors.keys():
- feed_dict[input_tensors[n]] = inputs[n].astype(input_tensors[n].dtype.as_numpy_dtype)
- return feed_dict
-
-def simple_add_summaries(summarize_ops, summarize_names,
- summary_key='summaries',
- print_summary_key='print_summaries', prefix=''):
- for op, name, in zip(summarize_ops, summarize_names):
- add_scalar_summary_op(op, name, summary_key, print_summary_key, prefix)
-
- summary_op = tf.summary.merge_all(summary_key)
- print_summary_op = tf.summary.merge_all(print_summary_key)
- return summary_op, print_summary_op
-
-def add_summary_ops(m, summarize_ops, summarize_names, to_aggregate=None,
- summary_key='summaries',
- print_summary_key='print_summaries', prefix=''):
- if type(to_aggregate) != list:
- to_aggregate = [to_aggregate for _ in summarize_ops]
-
- # set up aggregating metrics
- if np.any(to_aggregate):
- agg_ops = []
- for op, name, to_agg in zip(summarize_ops, summarize_names, to_aggregate):
- if to_agg:
- # agg_ops.append(slim.metrics.streaming_mean(op, return_reset_op=True))
- agg_ops.append(tf.contrib.metrics.streaming_mean(op))
- # agg_ops.append(tf.contrib.metrics.streaming_mean(op, return_reset_op=True))
- else:
- agg_ops.append([None, None, None])
-
- # agg_values_op, agg_update_op, agg_reset_op = zip(*agg_ops)
- # agg_update_op = [x for x in agg_update_op if x is not None]
- # agg_reset_op = [x for x in agg_reset_op if x is not None]
- agg_values_op, agg_update_op = zip(*agg_ops)
- agg_update_op = [x for x in agg_update_op if x is not None]
- agg_reset_op = [tf.no_op()]
- else:
- agg_values_op = [None for _ in to_aggregate]
- agg_update_op = [tf.no_op()]
- agg_reset_op = [tf.no_op()]
-
- for op, name, to_agg, agg_op in zip(summarize_ops, summarize_names, to_aggregate, agg_values_op):
- if to_agg:
- add_scalar_summary_op(agg_op, name, summary_key, print_summary_key, prefix)
- else:
- add_scalar_summary_op(op, name, summary_key, print_summary_key, prefix)
-
- summary_op = tf.summary.merge_all(summary_key)
- print_summary_op = tf.summary.merge_all(print_summary_key)
- return summary_op, print_summary_op, agg_update_op, agg_reset_op
-
-
-
-def accum_val_ops(outputs, names, global_step, output_dir, metric_summary, N):
- """Processes the collected outputs to compute AP for action prediction.
-
- Args:
- outputs : List of scalar ops to summarize.
- names : Name of the scalar ops.
- global_step : global_step.
- output_dir : where to store results.
- metric_summary : summary object to add summaries to.
- N : number of outputs to process.
- """
- outs = []
- if N >= 0:
- outputs = outputs[:N]
- for i in range(len(outputs[0])):
- scalar = np.array(map(lambda x: x[i], outputs))
- assert(scalar.ndim == 1)
- add_value_to_summary(metric_summary, names[i], np.mean(scalar),
- tag_str='{:>27s}: [{:s}]: %f'.format(names[i], ''))
- outs.append(np.mean(scalar))
- return outs
-
-def get_default_summary_ops():
- return utils.Foo(summary_ops=None, print_summary_ops=None,
- additional_return_ops=[], arop_summary_iters=[],
- arop_eval_fns=[])
-
-
-def simple_summaries(summarize_ops, summarize_names, mode, to_aggregate=False,
- scope_name='summary'):
-
- if type(to_aggregate) != list:
- to_aggregate = [to_aggregate for _ in summarize_ops]
-
- summary_key = '{:s}_summaries'.format(mode)
- print_summary_key = '{:s}_print_summaries'.format(mode)
- prefix=' [{:s}]: '.format(mode)
-
- # Default ops for things that dont need to be aggregated.
- if not np.all(to_aggregate):
- for op, name, to_agg in zip(summarize_ops, summarize_names, to_aggregate):
- if not to_agg:
- add_scalar_summary_op(op, name, summary_key, print_summary_key, prefix)
- summary_ops = tf.summary.merge_all(summary_key)
- print_summary_ops = tf.summary.merge_all(print_summary_key)
- else:
- summary_ops = tf.no_op()
- print_summary_ops = tf.no_op()
-
- # Default ops for things that dont need to be aggregated.
- if np.any(to_aggregate):
- additional_return_ops = [[summarize_ops[i]
- for i, x in enumerate(to_aggregate )if x]]
- arop_summary_iters = [-1]
- s_names = ['{:s}/{:s}'.format(scope_name, summarize_names[i])
- for i, x in enumerate(to_aggregate) if x]
- fn = lambda outputs, global_step, output_dir, metric_summary, N: \
- accum_val_ops(outputs, s_names, global_step, output_dir, metric_summary,
- N)
- arop_eval_fns = [fn]
- else:
- additional_return_ops = []
- arop_summary_iters = []
- arop_eval_fns = []
- return summary_ops, print_summary_ops, additional_return_ops, \
- arop_summary_iters, arop_eval_fns
diff --git a/research/cognitive_mapping_and_planning/tfcode/vision_baseline_lstm.py b/research/cognitive_mapping_and_planning/tfcode/vision_baseline_lstm.py
deleted file mode 100644
index ccf3ab23b06b71ed2a6d300b9a7d2a67a396c52e..0000000000000000000000000000000000000000
--- a/research/cognitive_mapping_and_planning/tfcode/vision_baseline_lstm.py
+++ /dev/null
@@ -1,533 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import numpy as np
-
-
-import tensorflow as tf
-
-from tensorflow.contrib import slim
-
-import logging
-from tensorflow.python.platform import app
-from tensorflow.python.platform import flags
-from src import utils
-import src.file_utils as fu
-import tfcode.nav_utils as nu
-from tfcode import tf_utils
-
-setup_train_step_kwargs = nu.default_train_step_kwargs
-compute_losses_multi_or = nu.compute_losses_multi_or
-get_repr_from_image = nu.get_repr_from_image
-
-_save_d_at_t = nu.save_d_at_t
-_save_all = nu.save_all
-_eval_ap = nu.eval_ap
-_eval_dist = nu.eval_dist
-_plot_trajectories = nu.plot_trajectories
-
-def lstm_online(cell_fn, num_steps, inputs, state, varscope):
- # inputs is B x num_steps x C, C channels.
- # state is 2 tuple with B x 1 x C1, B x 1 x C2
- # Output state is always B x 1 x C
- inputs = tf.unstack(inputs, axis=1, num=num_steps)
- state = tf.unstack(state, axis=1, num=1)[0]
- outputs = []
-
- if num_steps > 1:
- varscope.reuse_variables()
-
- for s in range(num_steps):
- output, state = cell_fn(inputs[s], state)
- outputs.append(output)
- outputs = tf.stack(outputs, axis=1)
- state = tf.stack([state], axis=1)
- return outputs, state
-
-def _inputs(problem, lstm_states, lstm_state_dims):
- # Set up inputs.
- with tf.name_scope('inputs'):
- n_views = problem.n_views
-
- inputs = []
- inputs.append(('orig_maps', tf.float32,
- (problem.batch_size, 1, None, None, 1)))
- inputs.append(('goal_loc', tf.float32,
- (problem.batch_size, problem.num_goals, 2)))
-
- # For initing LSTM.
- inputs.append(('rel_goal_loc_at_start', tf.float32,
- (problem.batch_size, problem.num_goals,
- problem.rel_goal_loc_dim)))
- common_input_data, _ = tf_utils.setup_inputs(inputs)
-
- inputs = []
- inputs.append(('imgs', tf.float32, (problem.batch_size, None, n_views,
- problem.img_height, problem.img_width,
- problem.img_channels)))
- # Goal location as a tuple of delta location and delta theta.
- inputs.append(('rel_goal_loc', tf.float32, (problem.batch_size, None,
- problem.rel_goal_loc_dim)))
- if problem.outputs.visit_count:
- inputs.append(('visit_count', tf.int32, (problem.batch_size, None, 1)))
- inputs.append(('last_visit', tf.int32, (problem.batch_size, None, 1)))
-
- for i, (state, dim) in enumerate(zip(lstm_states, lstm_state_dims)):
- inputs.append((state, tf.float32, (problem.batch_size, 1, dim)))
-
- if problem.outputs.egomotion:
- inputs.append(('incremental_locs', tf.float32,
- (problem.batch_size, None, 2)))
- inputs.append(('incremental_thetas', tf.float32,
- (problem.batch_size, None, 1)))
-
- inputs.append(('step_number', tf.int32, (1, None, 1)))
- inputs.append(('node_ids', tf.int32, (problem.batch_size, None,
- problem.node_ids_dim)))
- inputs.append(('perturbs', tf.float32, (problem.batch_size, None,
- problem.perturbs_dim)))
-
- # For plotting result plots
- inputs.append(('loc_on_map', tf.float32, (problem.batch_size, None, 2)))
- inputs.append(('gt_dist_to_goal', tf.float32, (problem.batch_size, None, 1)))
- step_input_data, _ = tf_utils.setup_inputs(inputs)
-
- inputs = []
- inputs.append(('executed_actions', tf.int32, (problem.batch_size, None)))
- inputs.append(('rewards', tf.float32, (problem.batch_size, None)))
- inputs.append(('action_sample_wts', tf.float32, (problem.batch_size, None)))
- inputs.append(('action', tf.int32, (problem.batch_size, None,
- problem.num_actions)))
- train_data, _ = tf_utils.setup_inputs(inputs)
- train_data.update(step_input_data)
- train_data.update(common_input_data)
- return common_input_data, step_input_data, train_data
-
-
-def _add_summaries(m, summary_mode, arop_full_summary_iters):
- summarize_ops = [m.lr_op, m.global_step_op, m.sample_gt_prob_op,
- m.total_loss_op, m.data_loss_op, m.reg_loss_op] + m.acc_ops
- summarize_names = ['lr', 'global_step', 'sample_gt_prob_op', 'total_loss',
- 'data_loss', 'reg_loss'] + \
- ['acc_{:d}'.format(i) for i in range(len(m.acc_ops))]
- to_aggregate = [0, 0, 0, 1, 1, 1] + [1]*len(m.acc_ops)
-
- scope_name = 'summary'
- with tf.name_scope(scope_name):
- s_ops = nu.add_default_summaries(summary_mode, arop_full_summary_iters,
- summarize_ops, summarize_names,
- to_aggregate, m.action_prob_op,
- m.input_tensors, scope_name=scope_name)
- m.summary_ops = {summary_mode: s_ops}
-
-def visit_count_fc(visit_count, last_visit, embed_neurons, wt_decay, fc_dropout):
- with tf.variable_scope('embed_visit_count'):
- visit_count = tf.reshape(visit_count, shape=[-1])
- last_visit = tf.reshape(last_visit, shape=[-1])
-
- visit_count = tf.clip_by_value(visit_count, clip_value_min=-1,
- clip_value_max=15)
- last_visit = tf.clip_by_value(last_visit, clip_value_min=-1,
- clip_value_max=15)
- visit_count = tf.one_hot(visit_count, depth=16, axis=1, dtype=tf.float32,
- on_value=10., off_value=0.)
- last_visit = tf.one_hot(last_visit, depth=16, axis=1, dtype=tf.float32,
- on_value=10., off_value=0.)
- f = tf.concat([visit_count, last_visit], 1)
- x, _ = tf_utils.fc_network(
- f, neurons=embed_neurons, wt_decay=wt_decay, name='visit_count_embed',
- offset=0, batch_norm_param=None, dropout_ratio=fc_dropout,
- is_training=is_training)
- return x
-
-def lstm_setup(name, x, batch_size, is_single_step, lstm_dim, lstm_out,
- num_steps, state_input_op):
- # returns state_name, state_init_op, updated_state_op, out_op
- with tf.name_scope('reshape_'+name):
- sh = x.get_shape().as_list()
- x = tf.reshape(x, shape=[batch_size, -1, sh[-1]])
-
- with tf.variable_scope(name) as varscope:
- cell = tf.contrib.rnn.LSTMCell(
- num_units=lstm_dim, forget_bias=1.0, state_is_tuple=False,
- num_proj=lstm_out, use_peepholes=True,
- initializer=tf.random_uniform_initializer(-0.01, 0.01, seed=0),
- cell_clip=None, proj_clip=None)
-
- sh = [batch_size, 1, lstm_dim+lstm_out]
- state_init_op = tf.constant(0., dtype=tf.float32, shape=sh)
-
- fn = lambda ns: lstm_online(cell, ns, x, state_input_op, varscope)
- out_op, updated_state_op = tf.cond(is_single_step, lambda: fn(1), lambda:
- fn(num_steps))
-
- return name, state_init_op, updated_state_op, out_op
-
-def combine_setup(name, combine_type, embed_img, embed_goal, num_img_neuorons=None,
- num_goal_neurons=None):
- with tf.name_scope(name + '_' + combine_type):
- if combine_type == 'add':
- # Simple concat features from goal and image
- out = embed_img + embed_goal
-
- elif combine_type == 'multiply':
- # Multiply things together
- re_embed_img = tf.reshape(
- embed_img, shape=[-1, num_img_neuorons / num_goal_neurons,
- num_goal_neurons])
- re_embed_goal = tf.reshape(embed_goal, shape=[-1, num_goal_neurons, 1])
- x = tf.matmul(re_embed_img, re_embed_goal, transpose_a=False, transpose_b=False)
- out = slim.flatten(x)
- elif combine_type == 'none' or combine_type == 'imgonly':
- out = embed_img
- elif combine_type == 'goalonly':
- out = embed_goal
- else:
- logging.fatal('Undefined combine_type: %s', combine_type)
- return out
-
-
-def preprocess_egomotion(locs, thetas):
- with tf.name_scope('pre_ego'):
- pre_ego = tf.concat([locs, tf.sin(thetas), tf.cos(thetas)], 2)
- sh = pre_ego.get_shape().as_list()
- pre_ego = tf.reshape(pre_ego, [-1, sh[-1]])
- return pre_ego
-
-def setup_to_run(m, args, is_training, batch_norm_is_training, summary_mode):
- # Set up the model.
- tf.set_random_seed(args.solver.seed)
- task_params = args.navtask.task_params
- num_steps = task_params.num_steps
- num_goals = task_params.num_goals
- num_actions = task_params.num_actions
- num_actions_ = num_actions
-
- n_views = task_params.n_views
-
- batch_norm_is_training_op = \
- tf.placeholder_with_default(batch_norm_is_training, shape=[],
- name='batch_norm_is_training_op')
- # Setup the inputs
- m.input_tensors = {}
- lstm_states = []; lstm_state_dims = [];
- state_names = []; updated_state_ops = []; init_state_ops = [];
- if args.arch.lstm_output:
- lstm_states += ['lstm_output']
- lstm_state_dims += [args.arch.lstm_output_dim+task_params.num_actions]
- if args.arch.lstm_ego:
- lstm_states += ['lstm_ego']
- lstm_state_dims += [args.arch.lstm_ego_dim + args.arch.lstm_ego_out]
- lstm_states += ['lstm_img']
- lstm_state_dims += [args.arch.lstm_img_dim + args.arch.lstm_img_out]
- elif args.arch.lstm_img:
- # An LSTM only on the image
- lstm_states += ['lstm_img']
- lstm_state_dims += [args.arch.lstm_img_dim + args.arch.lstm_img_out]
- else:
- # No LSTMs involved here.
- None
-
- m.input_tensors['common'], m.input_tensors['step'], m.input_tensors['train'] = \
- _inputs(task_params, lstm_states, lstm_state_dims)
-
- with tf.name_scope('check_size'):
- is_single_step = tf.equal(tf.unstack(tf.shape(m.input_tensors['step']['imgs']),
- num=6)[1], 1)
-
- images_reshaped = tf.reshape(m.input_tensors['step']['imgs'],
- shape=[-1, task_params.img_height, task_params.img_width,
- task_params.img_channels], name='re_image')
-
- rel_goal_loc_reshaped = tf.reshape(m.input_tensors['step']['rel_goal_loc'],
- shape=[-1, task_params.rel_goal_loc_dim], name='re_rel_goal_loc')
-
- x, vars_ = get_repr_from_image(
- images_reshaped, task_params.modalities, task_params.data_augment,
- args.arch.encoder, args.solver.freeze_conv, args.solver.wt_decay,
- is_training)
-
- # Reshape into nice things so that these can be accumulated over time steps
- # for faster backprop.
- sh_before = x.get_shape().as_list()
- m.encoder_output = tf.reshape(
- x, shape=[task_params.batch_size, -1, n_views] + sh_before[1:])
- x = tf.reshape(m.encoder_output, shape=[-1] + sh_before[1:])
-
- # Add a layer to reduce dimensions for a fc layer.
- if args.arch.dim_reduce_neurons > 0:
- ks = 1; neurons = args.arch.dim_reduce_neurons;
- init_var = np.sqrt(2.0/(ks**2)/neurons)
- batch_norm_param = args.arch.batch_norm_param
- batch_norm_param['is_training'] = batch_norm_is_training_op
- m.conv_feat = slim.conv2d(
- x, neurons, kernel_size=ks, stride=1, normalizer_fn=slim.batch_norm,
- normalizer_params=batch_norm_param, padding='SAME', scope='dim_reduce',
- weights_regularizer=slim.l2_regularizer(args.solver.wt_decay),
- weights_initializer=tf.random_normal_initializer(stddev=init_var))
- reshape_conv_feat = slim.flatten(m.conv_feat)
- sh = reshape_conv_feat.get_shape().as_list()
- m.reshape_conv_feat = tf.reshape(reshape_conv_feat,
- shape=[-1, sh[1]*n_views])
-
- # Restore these from a checkpoint.
- if args.solver.pretrained_path is not None:
- m.init_fn = slim.assign_from_checkpoint_fn(args.solver.pretrained_path,
- vars_)
- else:
- m.init_fn = None
-
- # Hit the goal_location with a bunch of fully connected layers, to embed it
- # into some space.
- with tf.variable_scope('embed_goal'):
- batch_norm_param = args.arch.batch_norm_param
- batch_norm_param['is_training'] = batch_norm_is_training_op
- m.embed_goal, _ = tf_utils.fc_network(
- rel_goal_loc_reshaped, neurons=args.arch.goal_embed_neurons,
- wt_decay=args.solver.wt_decay, name='goal_embed', offset=0,
- batch_norm_param=batch_norm_param, dropout_ratio=args.arch.fc_dropout,
- is_training=is_training)
-
- if args.arch.embed_goal_for_state:
- with tf.variable_scope('embed_goal_for_state'):
- batch_norm_param = args.arch.batch_norm_param
- batch_norm_param['is_training'] = batch_norm_is_training_op
- m.embed_goal_for_state, _ = tf_utils.fc_network(
- m.input_tensors['common']['rel_goal_loc_at_start'][:,0,:],
- neurons=args.arch.goal_embed_neurons, wt_decay=args.solver.wt_decay,
- name='goal_embed', offset=0, batch_norm_param=batch_norm_param,
- dropout_ratio=args.arch.fc_dropout, is_training=is_training)
-
- # Hit the goal_location with a bunch of fully connected layers, to embed it
- # into some space.
- with tf.variable_scope('embed_img'):
- batch_norm_param = args.arch.batch_norm_param
- batch_norm_param['is_training'] = batch_norm_is_training_op
- m.embed_img, _ = tf_utils.fc_network(
- m.reshape_conv_feat, neurons=args.arch.img_embed_neurons,
- wt_decay=args.solver.wt_decay, name='img_embed', offset=0,
- batch_norm_param=batch_norm_param, dropout_ratio=args.arch.fc_dropout,
- is_training=is_training)
-
- # For lstm_ego, and lstm_image, embed the ego motion, accumulate it into an
- # LSTM, combine with image features and accumulate those in an LSTM. Finally
- # combine what you get from the image LSTM with the goal to output an action.
- if args.arch.lstm_ego:
- ego_reshaped = preprocess_egomotion(m.input_tensors['step']['incremental_locs'],
- m.input_tensors['step']['incremental_thetas'])
- with tf.variable_scope('embed_ego'):
- batch_norm_param = args.arch.batch_norm_param
- batch_norm_param['is_training'] = batch_norm_is_training_op
- m.embed_ego, _ = tf_utils.fc_network(
- ego_reshaped, neurons=args.arch.ego_embed_neurons,
- wt_decay=args.solver.wt_decay, name='ego_embed', offset=0,
- batch_norm_param=batch_norm_param, dropout_ratio=args.arch.fc_dropout,
- is_training=is_training)
-
- state_name, state_init_op, updated_state_op, out_op = lstm_setup(
- 'lstm_ego', m.embed_ego, task_params.batch_size, is_single_step,
- args.arch.lstm_ego_dim, args.arch.lstm_ego_out, num_steps*num_goals,
- m.input_tensors['step']['lstm_ego'])
- state_names += [state_name]
- init_state_ops += [state_init_op]
- updated_state_ops += [updated_state_op]
-
- # Combine the output with the vision features.
- m.img_ego_op = combine_setup('img_ego', args.arch.combine_type_ego,
- m.embed_img, out_op,
- args.arch.img_embed_neurons[-1],
- args.arch.lstm_ego_out)
-
- # LSTM on these vision features.
- state_name, state_init_op, updated_state_op, out_op = lstm_setup(
- 'lstm_img', m.img_ego_op, task_params.batch_size, is_single_step,
- args.arch.lstm_img_dim, args.arch.lstm_img_out, num_steps*num_goals,
- m.input_tensors['step']['lstm_img'])
- state_names += [state_name]
- init_state_ops += [state_init_op]
- updated_state_ops += [updated_state_op]
-
- m.img_for_goal = out_op
- num_img_for_goal_neurons = args.arch.lstm_img_out
-
- elif args.arch.lstm_img:
- # LSTM on just the image features.
- state_name, state_init_op, updated_state_op, out_op = lstm_setup(
- 'lstm_img', m.embed_img, task_params.batch_size, is_single_step,
- args.arch.lstm_img_dim, args.arch.lstm_img_out, num_steps*num_goals,
- m.input_tensors['step']['lstm_img'])
- state_names += [state_name]
- init_state_ops += [state_init_op]
- updated_state_ops += [updated_state_op]
- m.img_for_goal = out_op
- num_img_for_goal_neurons = args.arch.lstm_img_out
-
- else:
- m.img_for_goal = m.embed_img
- num_img_for_goal_neurons = args.arch.img_embed_neurons[-1]
-
-
- if args.arch.use_visit_count:
- m.embed_visit_count = visit_count_fc(
- m.input_tensors['step']['visit_count'],
- m.input_tensors['step']['last_visit'], args.arch.goal_embed_neurons,
- args.solver.wt_decay, args.arch.fc_dropout, is_training=is_training)
- m.embed_goal = m.embed_goal + m.embed_visit_count
-
- m.combined_f = combine_setup('img_goal', args.arch.combine_type,
- m.img_for_goal, m.embed_goal,
- num_img_for_goal_neurons,
- args.arch.goal_embed_neurons[-1])
-
- # LSTM on the combined representation.
- if args.arch.lstm_output:
- name = 'lstm_output'
- # A few fully connected layers here.
- with tf.variable_scope('action_pred'):
- batch_norm_param = args.arch.batch_norm_param
- batch_norm_param['is_training'] = batch_norm_is_training_op
- x, _ = tf_utils.fc_network(
- m.combined_f, neurons=args.arch.pred_neurons,
- wt_decay=args.solver.wt_decay, name='pred', offset=0,
- batch_norm_param=batch_norm_param, dropout_ratio=args.arch.fc_dropout)
-
- if args.arch.lstm_output_init_state_from_goal:
- # Use the goal embedding to initialize the LSTM state.
- # UGLY CLUGGY HACK: if this is doing computation for a single time step
- # then this will not involve back prop, so we can use the state input from
- # the feed dict, otherwise we compute the state representation from the
- # goal and feed that in. Necessary for using goal location to generate the
- # state representation.
- m.embed_goal_for_state = tf.expand_dims(m.embed_goal_for_state, dim=1)
- state_op = tf.cond(is_single_step, lambda: m.input_tensors['step'][name],
- lambda: m.embed_goal_for_state)
- state_name, state_init_op, updated_state_op, out_op = lstm_setup(
- name, x, task_params.batch_size, is_single_step,
- args.arch.lstm_output_dim,
- num_actions_,
- num_steps*num_goals, state_op)
- init_state_ops += [m.embed_goal_for_state]
- else:
- state_op = m.input_tensors['step'][name]
- state_name, state_init_op, updated_state_op, out_op = lstm_setup(
- name, x, task_params.batch_size, is_single_step,
- args.arch.lstm_output_dim,
- num_actions_, num_steps*num_goals, state_op)
- init_state_ops += [state_init_op]
-
- state_names += [state_name]
- updated_state_ops += [updated_state_op]
-
- out_op = tf.reshape(out_op, shape=[-1, num_actions_])
- if num_actions_ > num_actions:
- m.action_logits_op = out_op[:,:num_actions]
- m.baseline_op = out_op[:,num_actions:]
- else:
- m.action_logits_op = out_op
- m.baseline_op = None
- m.action_prob_op = tf.nn.softmax(m.action_logits_op)
-
- else:
- # A few fully connected layers here.
- with tf.variable_scope('action_pred'):
- batch_norm_param = args.arch.batch_norm_param
- batch_norm_param['is_training'] = batch_norm_is_training_op
- out_op, _ = tf_utils.fc_network(
- m.combined_f, neurons=args.arch.pred_neurons,
- wt_decay=args.solver.wt_decay, name='pred', offset=0,
- num_pred=num_actions_,
- batch_norm_param=batch_norm_param,
- dropout_ratio=args.arch.fc_dropout, is_training=is_training)
- if num_actions_ > num_actions:
- m.action_logits_op = out_op[:,:num_actions]
- m.baseline_op = out_op[:,num_actions:]
- else:
- m.action_logits_op = out_op
- m.baseline_op = None
- m.action_prob_op = tf.nn.softmax(m.action_logits_op)
-
- m.train_ops = {}
- m.train_ops['step'] = m.action_prob_op
- m.train_ops['common'] = [m.input_tensors['common']['orig_maps'],
- m.input_tensors['common']['goal_loc'],
- m.input_tensors['common']['rel_goal_loc_at_start']]
- m.train_ops['state_names'] = state_names
- m.train_ops['init_state'] = init_state_ops
- m.train_ops['updated_state'] = updated_state_ops
- m.train_ops['batch_norm_is_training_op'] = batch_norm_is_training_op
-
- # Flat list of ops which cache the step data.
- m.train_ops['step_data_cache'] = [tf.no_op()]
-
- if args.solver.freeze_conv:
- m.train_ops['step_data_cache'] = [m.encoder_output]
- else:
- m.train_ops['step_data_cache'] = []
-
- ewma_decay = 0.99 if is_training else 0.0
- weight = tf.ones_like(m.input_tensors['train']['action'], dtype=tf.float32,
- name='weight')
-
- m.reg_loss_op, m.data_loss_op, m.total_loss_op, m.acc_ops = \
- compute_losses_multi_or(
- m.action_logits_op, m.input_tensors['train']['action'],
- weights=weight, num_actions=num_actions,
- data_loss_wt=args.solver.data_loss_wt,
- reg_loss_wt=args.solver.reg_loss_wt, ewma_decay=ewma_decay)
-
-
- if args.solver.freeze_conv:
- vars_to_optimize = list(set(tf.trainable_variables()) - set(vars_))
- else:
- vars_to_optimize = None
-
- m.lr_op, m.global_step_op, m.train_op, m.should_stop_op, m.optimizer, \
- m.sync_optimizer = tf_utils.setup_training(
- m.total_loss_op,
- args.solver.initial_learning_rate,
- args.solver.steps_per_decay,
- args.solver.learning_rate_decay,
- args.solver.momentum,
- args.solver.max_steps,
- args.solver.sync,
- args.solver.adjust_lr_sync,
- args.solver.num_workers,
- args.solver.task,
- vars_to_optimize=vars_to_optimize,
- clip_gradient_norm=args.solver.clip_gradient_norm,
- typ=args.solver.typ, momentum2=args.solver.momentum2,
- adam_eps=args.solver.adam_eps)
-
-
- if args.arch.sample_gt_prob_type == 'inverse_sigmoid_decay':
- m.sample_gt_prob_op = tf_utils.inverse_sigmoid_decay(args.arch.isd_k,
- m.global_step_op)
- elif args.arch.sample_gt_prob_type == 'zero':
- m.sample_gt_prob_op = tf.constant(-1.0, dtype=tf.float32)
- elif args.arch.sample_gt_prob_type.split('_')[0] == 'step':
- step = int(args.arch.sample_gt_prob_type.split('_')[1])
- m.sample_gt_prob_op = tf_utils.step_gt_prob(
- step, m.input_tensors['step']['step_number'][0,0,0])
-
- m.sample_action_type = args.arch.action_sample_type
- m.sample_action_combine_type = args.arch.action_sample_combine_type
- _add_summaries(m, summary_mode, args.summary.arop_full_summary_iters)
-
- m.init_op = tf.group(tf.global_variables_initializer(),
- tf.local_variables_initializer())
- m.saver_op = tf.train.Saver(keep_checkpoint_every_n_hours=4,
- write_version=tf.train.SaverDef.V2)
-
- return m
diff --git a/research/compression/README.md b/research/compression/README.md
deleted file mode 100644
index 7f431b5eac6805fbecc276783cef2bc6c62068e5..0000000000000000000000000000000000000000
--- a/research/compression/README.md
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-# Compression with Neural Networks
-
-This is a [TensorFlow](http://www.tensorflow.org/) model repo containing
-research on compression with neural networks. This repo currently contains
-code for the following papers:
-
-[Full Resolution Image Compression with Recurrent Neural Networks](https://arxiv.org/abs/1608.05148)
-
-## Organization
-[Image Encoder](image_encoder/): Encoding and decoding images into their binary representation.
-
-[Entropy Coder](entropy_coder/): Lossless compression of the binary representation.
-
-## Contact Info
-Model repository maintained by Nick Johnston ([nmjohn](https://github.com/nmjohn)).
diff --git a/research/compression/entropy_coder/README.md b/research/compression/entropy_coder/README.md
deleted file mode 100644
index 59e889990aab71e12ed13122c9b5a796a048402a..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/README.md
+++ /dev/null
@@ -1,109 +0,0 @@
-# Neural net based entropy coding
-
-This is a [TensorFlow](http://www.tensorflow.org/) model for additional
-lossless compression of bitstreams generated by neural net based image
-encoders as described in
-[https://arxiv.org/abs/1703.10114](https://arxiv.org/abs/1703.10114).
-
-To be more specific, the entropy coder aims at compressing further binary
-codes which have a 3D tensor structure with:
-
-* the first two dimensions of the tensors corresponding to the height and
-the width of the binary codes,
-* the last dimension being the depth of the codes. The last dimension can be
-sliced into N groups of K, where each additional group is used by the image
-decoder to add more details to the reconstructed image.
-
-The code in this directory only contains the underlying code probability model
-but does not perform the actual compression using arithmetic coding.
-The code probability model is enough to compute the theoretical compression
-ratio.
-
-
-## Prerequisites
-The only software requirements for running the encoder and decoder is having
-Tensorflow installed.
-
-You will also need to add the top level source directory of the entropy coder
-to your `PYTHONPATH`, for example:
-
-`export PYTHONPATH=${PYTHONPATH}:/tmp/models/compression`
-
-
-## Training the entropy coder
-
-### Synthetic dataset
-If you do not have a training dataset, there is a simple code generative model
-that you can use to generate a dataset and play with the entropy coder.
-The generative model is located under dataset/gen\_synthetic\_dataset.py. Note
-that this simple generative model is not going to give good results on real
-images as it is not supposed to be close to the statistics of the binary
-representation of encoded images. Consider it as a toy dataset, no more, no
-less.
-
-To generate a synthetic dataset with 20000 samples:
-
-`mkdir -p /tmp/dataset`
-
-`python ./dataset/gen_synthetic_dataset.py --dataset_dir=/tmp/dataset/
---count=20000`
-
-Note that the generator has not been optimized at all, generating the synthetic
-dataset is currently pretty slow.
-
-### Training
-
-If you just want to play with the entropy coder trainer, here is the command
-line that can be used to train the entropy coder on the synthetic dataset:
-
-`mkdir -p /tmp/entropy_coder_train`
-
-`python ./core/entropy_coder_train.py --task=0
---train_dir=/tmp/entropy_coder_train/
---model=progressive
---model_config=./configs/synthetic/model_config.json
---train_config=./configs/synthetic/train_config.json
---input_config=./configs/synthetic/input_config.json
-`
-
-Training is configured using 3 files formatted using JSON:
-
-* One file is used to configure the underlying entropy coder model.
- Currently, only the *progressive* model is supported.
- This model takes 2 mandatory parameters and an optional one:
- * `layer_depth`: the number of bits per layer (a.k.a. iteration).
- Background: the image decoder takes each layer to add more detail
- to the image.
- * `layer_count`: the maximum number of layers that should be supported
- by the model. This should be equal or greater than the maximum number
- of layers in the input binary codes.
- * `coded_layer_count`: This can be used to consider only partial codes,
- keeping only the first `coded_layer_count` layers and ignoring the
- remaining layers. If left empty, the binary codes are left unchanged.
-* One file to configure the training, including the learning rate, ...
- The meaning of the parameters are pretty straightforward. Note that this
- file is only used during training and is not needed during inference.
-* One file to specify the input dataset to use during training.
- The dataset is formatted using tf.RecordIO.
-
-
-## Inference: file size after entropy coding.
-
-### Using a synthetic sample
-
-Here is the command line to generate a single synthetic sample formatted
-in the same way as what is provided by the image encoder:
-
-`python ./dataset/gen_synthetic_single.py
---sample_filename=/tmp/dataset/sample_0000.npz`
-
-To actually compute the additional compression ratio using the entropy coder
-trained in the previous step:
-
-`python ./core/entropy_coder_single.py
---model=progressive
---model_config=./configs/synthetic/model_config.json
---input_codes=/tmp/dataset/sample_0000.npz
---checkpoint=/tmp/entropy_coder_train/model.ckpt-209078`
-
-where the checkpoint number should be adjusted accordingly.
diff --git a/research/compression/entropy_coder/__init__.py b/research/compression/entropy_coder/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/compression/entropy_coder/all_models/__init__.py b/research/compression/entropy_coder/all_models/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/compression/entropy_coder/all_models/all_models.py b/research/compression/entropy_coder/all_models/all_models.py
deleted file mode 100644
index e376dac737667a348065eec622920b0a81ed1ac9..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/all_models/all_models.py
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Import and register all the entropy coder models."""
-
-# pylint: disable=unused-import
-from entropy_coder.progressive import progressive
diff --git a/research/compression/entropy_coder/all_models/all_models_test.py b/research/compression/entropy_coder/all_models/all_models_test.py
deleted file mode 100644
index b8aff504a0a00d579d1b2768164b78b6c095b235..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/all_models/all_models_test.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Basic test of all registered models."""
-
-import tensorflow as tf
-
-# pylint: disable=unused-import
-import all_models
-# pylint: enable=unused-import
-from entropy_coder.model import model_factory
-
-
-class AllModelsTest(tf.test.TestCase):
-
- def testBuildModelForTraining(self):
- factory = model_factory.GetModelRegistry()
- model_names = factory.GetAvailableModels()
-
- for m in model_names:
- tf.reset_default_graph()
-
- global_step = tf.Variable(tf.zeros([], dtype=tf.int64),
- trainable=False,
- name='global_step')
-
- optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1)
-
- batch_size = 3
- height = 40
- width = 20
- depth = 5
- binary_codes = tf.placeholder(dtype=tf.float32,
- shape=[batch_size, height, width, depth])
-
- # Create a model with the default configuration.
- print('Creating model: {}'.format(m))
- model = factory.CreateModel(m)
- model.Initialize(global_step,
- optimizer,
- model.GetConfigStringForUnitTest())
- self.assertTrue(model.loss is None, 'model: {}'.format(m))
- self.assertTrue(model.train_op is None, 'model: {}'.format(m))
- self.assertTrue(model.average_code_length is None, 'model: {}'.format(m))
-
- # Build the Tensorflow graph corresponding to the model.
- model.BuildGraph(binary_codes)
- self.assertTrue(model.loss is not None, 'model: {}'.format(m))
- self.assertTrue(model.average_code_length is not None,
- 'model: {}'.format(m))
- if model.train_op is None:
- print('Model {} is not trainable'.format(m))
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/compression/entropy_coder/configs/gru_prime3/model_config.json b/research/compression/entropy_coder/configs/gru_prime3/model_config.json
deleted file mode 100644
index cf63a4c454df5c47c732c5eaeea481b2aa714665..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/configs/gru_prime3/model_config.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "layer_count": 16,
- "layer_depth": 32
-}
diff --git a/research/compression/entropy_coder/configs/synthetic/input_config.json b/research/compression/entropy_coder/configs/synthetic/input_config.json
deleted file mode 100644
index 18455e65120cd45cb04106ed8b6b2d6641e1d49a..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/configs/synthetic/input_config.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "data": "/tmp/dataset/synthetic_dataset",
- "unique_code_size": true
-}
diff --git a/research/compression/entropy_coder/configs/synthetic/model_config.json b/research/compression/entropy_coder/configs/synthetic/model_config.json
deleted file mode 100644
index c6f1f3e11547a75c05019e24c59a7fc6d2a29e3b..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/configs/synthetic/model_config.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "layer_depth": 2,
- "layer_count": 8
-}
diff --git a/research/compression/entropy_coder/configs/synthetic/train_config.json b/research/compression/entropy_coder/configs/synthetic/train_config.json
deleted file mode 100644
index 79e4909fd3f93df983d79890e25b7b61ba14aa40..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/configs/synthetic/train_config.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
- "batch_size": 4,
- "learning_rate": 0.1,
- "decay_rate": 0.9,
- "samples_per_decay": 20000
-}
diff --git a/research/compression/entropy_coder/core/code_loader.py b/research/compression/entropy_coder/core/code_loader.py
deleted file mode 100644
index 603ab724afb0e6c4e94db9c121d7799eaf30fa02..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/core/code_loader.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Load binary codes stored as tf.Example in a TFRecord table."""
-
-import tensorflow as tf
-
-
-def ReadFirstCode(dataset):
- """Read the first example from a binary code RecordIO table."""
- for record in tf.python_io.tf_record_iterator(dataset):
- tf_example = tf.train.Example()
- tf_example.ParseFromString(record)
- break
- return tf_example
-
-
-def LoadBinaryCode(input_config, batch_size):
- """Load a batch of binary codes from a tf.Example dataset.
-
- Args:
- input_config: An InputConfig proto containing the input configuration.
- batch_size: Output batch size of examples.
-
- Returns:
- A batched tensor of binary codes.
- """
- data = input_config.data
-
- # TODO: Possibly use multiple files (instead of just one).
- file_list = [data]
- filename_queue = tf.train.string_input_producer(file_list,
- capacity=4)
- reader = tf.TFRecordReader()
- _, values = reader.read(filename_queue)
-
- serialized_example = tf.reshape(values, shape=[1])
- serialized_features = {
- 'code_shape': tf.FixedLenFeature([3],
- dtype=tf.int64),
- 'code': tf.VarLenFeature(tf.float32),
- }
- example = tf.parse_example(serialized_example, serialized_features)
-
- # 3D shape: height x width x binary_code_depth
- z = example['code_shape']
- code_shape = tf.reshape(tf.cast(z, tf.int32), [3])
- # Un-flatten the binary codes.
- code = tf.reshape(tf.sparse_tensor_to_dense(example['code']), code_shape)
-
- queue_size = 10
- queue = tf.PaddingFIFOQueue(
- queue_size + 3 * batch_size,
- dtypes=[code.dtype],
- shapes=[[None, None, None]])
- enqueue_op = queue.enqueue([code])
- dequeue_code = queue.dequeue_many(batch_size)
- queue_runner = tf.train.queue_runner.QueueRunner(queue, [enqueue_op])
- tf.add_to_collection(tf.GraphKeys.QUEUE_RUNNERS, queue_runner)
-
- return dequeue_code
diff --git a/research/compression/entropy_coder/core/config_helper.py b/research/compression/entropy_coder/core/config_helper.py
deleted file mode 100644
index a7d949e329b93f33d330d1ba494f71ae1704fa3f..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/core/config_helper.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Helper functions used in both train and inference."""
-
-import json
-import os.path
-
-import tensorflow as tf
-
-
-def GetConfigString(config_file):
- config_string = ''
- if config_file is not None:
- config_string = open(config_file).read()
- return config_string
-
-
-class InputConfig(object):
-
- def __init__(self, config_string):
- config = json.loads(config_string)
- self.data = config["data"]
- self.unique_code_size = config["unique_code_size"]
-
-
-class TrainConfig(object):
-
- def __init__(self, config_string):
- config = json.loads(config_string)
- self.batch_size = config["batch_size"]
- self.learning_rate = config["learning_rate"]
- self.decay_rate = config["decay_rate"]
- self.samples_per_decay = config["samples_per_decay"]
-
-
-def SaveConfig(directory, filename, config_string):
- path = os.path.join(directory, filename)
- with tf.gfile.Open(path, mode='w') as f:
- f.write(config_string)
diff --git a/research/compression/entropy_coder/core/entropy_coder_single.py b/research/compression/entropy_coder/core/entropy_coder_single.py
deleted file mode 100644
index 8a61b488b6bdd11e1cff4a2da672129240eb7240..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/core/entropy_coder_single.py
+++ /dev/null
@@ -1,116 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Compute the additional compression ratio after entropy coding."""
-
-import io
-import os
-
-import numpy as np
-import tensorflow as tf
-
-import config_helper
-
-# pylint: disable=unused-import
-from entropy_coder.all_models import all_models
-# pylint: enable=unused-import
-from entropy_coder.model import model_factory
-
-
-# Checkpoint used to restore the model parameters.
-tf.app.flags.DEFINE_string('checkpoint', None,
- """Model checkpoint.""")
-
-# Model selection and configuration.
-tf.app.flags.DEFINE_string('model', None, """Underlying encoder model.""")
-tf.app.flags.DEFINE_string('model_config', None,
- """Model config protobuf given as text file.""")
-
-# File holding the binary codes.
-tf.flags.DEFINE_string('input_codes', None, 'Location of binary code file.')
-
-FLAGS = tf.flags.FLAGS
-
-
-def main(_):
- if (FLAGS.input_codes is None or FLAGS.model is None):
- print ('\nUsage: python entropy_coder_single.py --model=progressive '
- '--model_config=model_config.json'
- '--iteration=15\n\n')
- return
-
- #if FLAGS.iteration < -1 or FLAGS.iteration > 15:
- # print ('\n--iteration must be between 0 and 15 inclusive, or -1 to infer '
- # 'from file.\n')
- # return
- #iteration = FLAGS.iteration
-
- if not tf.gfile.Exists(FLAGS.input_codes):
- print('\nInput codes not found.\n')
- return
-
- with tf.gfile.FastGFile(FLAGS.input_codes, 'rb') as code_file:
- contents = code_file.read()
- loaded_codes = np.load(io.BytesIO(contents))
- assert ['codes', 'shape'] not in loaded_codes.files
- loaded_shape = loaded_codes['shape']
- loaded_array = loaded_codes['codes']
-
- # Unpack and recover code shapes.
- unpacked_codes = np.reshape(np.unpackbits(loaded_array)
- [:np.prod(loaded_shape)],
- loaded_shape)
-
- numpy_int_codes = unpacked_codes.transpose([1, 2, 3, 0, 4])
- numpy_int_codes = numpy_int_codes.reshape([numpy_int_codes.shape[0],
- numpy_int_codes.shape[1],
- numpy_int_codes.shape[2],
- -1])
- numpy_codes = numpy_int_codes.astype(np.float32) * 2.0 - 1.0
-
- with tf.Graph().as_default() as graph:
- # TF tensor to hold the binary codes to losslessly compress.
- batch_size = 1
- codes = tf.placeholder(tf.float32, shape=numpy_codes.shape)
-
- # Create the entropy coder model.
- global_step = None
- optimizer = None
- model = model_factory.GetModelRegistry().CreateModel(FLAGS.model)
- model_config_string = config_helper.GetConfigString(FLAGS.model_config)
- model.Initialize(global_step, optimizer, model_config_string)
- model.BuildGraph(codes)
-
- saver = tf.train.Saver(sharded=True, keep_checkpoint_every_n_hours=12.0)
-
- with tf.Session(graph=graph) as sess:
- # Initialize local variables.
- sess.run(tf.local_variables_initializer())
-
- # Restore model variables.
- saver.restore(sess, FLAGS.checkpoint)
-
- tf_tensors = {
- 'code_length': model.average_code_length
- }
- feed_dict = {codes: numpy_codes}
- np_tensors = sess.run(tf_tensors, feed_dict=feed_dict)
-
- print('Additional compression ratio: {}'.format(
- np_tensors['code_length']))
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/compression/entropy_coder/core/entropy_coder_train.py b/research/compression/entropy_coder/core/entropy_coder_train.py
deleted file mode 100644
index 27c489037d27095b578aed6ad10a5a190ec49b18..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/core/entropy_coder_train.py
+++ /dev/null
@@ -1,184 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Train an entropy coder model."""
-
-import time
-
-import tensorflow as tf
-
-import code_loader
-import config_helper
-
-# pylint: disable=unused-import
-from entropy_coder.all_models import all_models
-# pylint: enable=unused-import
-from entropy_coder.model import model_factory
-
-
-FLAGS = tf.app.flags.FLAGS
-
-# Hardware resources configuration.
-tf.app.flags.DEFINE_string('master', '',
- """Name of the TensorFlow master to use.""")
-tf.app.flags.DEFINE_string('train_dir', None,
- """Directory where to write event logs.""")
-tf.app.flags.DEFINE_integer('task', None,
- """Task id of the replica running the training.""")
-tf.app.flags.DEFINE_integer('ps_tasks', 0, """Number of tasks in the ps job.
- If 0 no ps job is used.""")
-
-# Model selection and configuration.
-tf.app.flags.DEFINE_string('model', None, """Underlying encoder model.""")
-tf.app.flags.DEFINE_string('model_config', None,
- """Model config protobuf given as text file.""")
-
-# Training data and parameters configuration.
-tf.app.flags.DEFINE_string('input_config', None,
- """Path to the training input config file.""")
-tf.app.flags.DEFINE_string('train_config', None,
- """Path to the training experiment config file.""")
-
-
-def train():
- if FLAGS.train_dir is None:
- raise ValueError('Parameter train_dir must be provided')
- if FLAGS.task is None:
- raise ValueError('Parameter task must be provided')
- if FLAGS.model is None:
- raise ValueError('Parameter model must be provided')
-
- input_config_string = config_helper.GetConfigString(FLAGS.input_config)
- input_config = config_helper.InputConfig(input_config_string)
-
- # Training parameters.
- train_config_string = config_helper.GetConfigString(FLAGS.train_config)
- train_config = config_helper.TrainConfig(train_config_string)
-
- batch_size = train_config.batch_size
- initial_learning_rate = train_config.learning_rate
- decay_rate = train_config.decay_rate
- samples_per_decay = train_config.samples_per_decay
-
- # Parameters for learning-rate decay.
- # The formula is decay_rate ** floor(steps / decay_steps).
- decay_steps = samples_per_decay / batch_size
- decay_steps = max(decay_steps, 1)
-
- first_code = code_loader.ReadFirstCode(input_config.data)
- first_code_height = (
- first_code.features.feature['code_shape'].int64_list.value[0])
- first_code_width = (
- first_code.features.feature['code_shape'].int64_list.value[1])
- max_bit_depth = (
- first_code.features.feature['code_shape'].int64_list.value[2])
- print('Maximum code depth: {}'.format(max_bit_depth))
-
- with tf.Graph().as_default():
- ps_ops = ["Variable", "VariableV2", "AutoReloadVariable", "VarHandleOp"]
- with tf.device(tf.train.replica_device_setter(FLAGS.ps_tasks,
- ps_ops=ps_ops)):
- codes = code_loader.LoadBinaryCode(
- input_config=input_config,
- batch_size=batch_size)
- if input_config.unique_code_size:
- print('Input code size: {} x {}'.format(first_code_height,
- first_code_width))
- codes.set_shape(
- [batch_size, first_code_height, first_code_width, max_bit_depth])
- else:
- codes.set_shape([batch_size, None, None, max_bit_depth])
- codes_effective_shape = tf.shape(codes)
-
- global_step = tf.contrib.framework.create_global_step()
-
- # Apply learning-rate decay.
- learning_rate = tf.train.exponential_decay(
- learning_rate=initial_learning_rate,
- global_step=global_step,
- decay_steps=decay_steps,
- decay_rate=decay_rate,
- staircase=True)
- tf.summary.scalar('Learning Rate', learning_rate)
- optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate,
- epsilon=1.0)
-
- # Create the entropy coder model.
- model = model_factory.GetModelRegistry().CreateModel(FLAGS.model)
- model_config_string = config_helper.GetConfigString(FLAGS.model_config)
- model.Initialize(global_step, optimizer, model_config_string)
- model.BuildGraph(codes)
-
- summary_op = tf.summary.merge_all()
-
- # Verify that the model can actually be trained.
- if model.train_op is None:
- raise ValueError('Input model {} is not trainable'.format(FLAGS.model))
-
- # We disable the summary thread run by Supervisor class by passing
- # summary_op=None. We still pass save_summaries_secs because it is used by
- # the global step counter thread.
- is_chief = (FLAGS.task == 0)
- sv = tf.train.Supervisor(logdir=FLAGS.train_dir,
- is_chief=is_chief,
- global_step=global_step,
- # saver=model.saver,
- summary_op=None,
- save_summaries_secs=120,
- save_model_secs=600,
- recovery_wait_secs=30)
-
- sess = sv.PrepareSession(FLAGS.master)
- sv.StartQueueRunners(sess)
-
- step = sess.run(global_step)
- print('Trainer initial step: {}.'.format(step))
-
- # Once everything has been setup properly, save the configs.
- if is_chief:
- config_helper.SaveConfig(FLAGS.train_dir, 'input_config.json',
- input_config_string)
- config_helper.SaveConfig(FLAGS.train_dir, 'model_config.json',
- model_config_string)
- config_helper.SaveConfig(FLAGS.train_dir, 'train_config.json',
- train_config_string)
-
- # Train the model.
- next_summary_time = time.time()
- while not sv.ShouldStop():
- feed_dict = None
-
- # Once in a while, update the summaries on the chief worker.
- if is_chief and next_summary_time < time.time():
- summary_str = sess.run(summary_op, feed_dict=feed_dict)
- sv.SummaryComputed(sess, summary_str)
- next_summary_time = time.time() + sv.save_summaries_secs
- else:
- tf_tensors = {
- 'train': model.train_op,
- 'code_length': model.average_code_length
- }
- np_tensors = sess.run(tf_tensors, feed_dict=feed_dict)
- print(np_tensors['code_length'])
-
- sv.Stop()
-
-
-def main(argv=None): # pylint: disable=unused-argument
- train()
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/compression/entropy_coder/dataset/gen_synthetic_dataset.py b/research/compression/entropy_coder/dataset/gen_synthetic_dataset.py
deleted file mode 100644
index de60aee324d4a6209d00a873ee681aa59aae0d8e..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/dataset/gen_synthetic_dataset.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Generate a synthetic dataset."""
-
-import os
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-import synthetic_model
-
-
-FLAGS = tf.app.flags.FLAGS
-
-tf.app.flags.DEFINE_string(
- 'dataset_dir', None,
- """Directory where to write the dataset and the configs.""")
-tf.app.flags.DEFINE_integer(
- 'count', 1000,
- """Number of samples to generate.""")
-
-
-def int64_feature(values):
- """Returns a TF-Feature of int64s.
-
- Args:
- values: A scalar or list of values.
-
- Returns:
- A TF-Feature.
- """
- if not isinstance(values, (tuple, list)):
- values = [values]
- return tf.train.Feature(int64_list=tf.train.Int64List(value=values))
-
-
-def float_feature(values):
- """Returns a TF-Feature of floats.
-
- Args:
- values: A scalar of list of values.
-
- Returns:
- A TF-Feature.
- """
- if not isinstance(values, (tuple, list)):
- values = [values]
- return tf.train.Feature(float_list=tf.train.FloatList(value=values))
-
-
-def AddToTFRecord(code, tfrecord_writer):
- example = tf.train.Example(features=tf.train.Features(feature={
- 'code_shape': int64_feature(code.shape),
- 'code': float_feature(code.flatten().tolist()),
- }))
- tfrecord_writer.write(example.SerializeToString())
-
-
-def GenerateDataset(filename, count, code_shape):
- with tf.python_io.TFRecordWriter(filename) as tfrecord_writer:
- for _ in xrange(count):
- code = synthetic_model.GenerateSingleCode(code_shape)
- # Convert {0,1} codes to {-1,+1} codes.
- code = 2.0 * code - 1.0
- AddToTFRecord(code, tfrecord_writer)
-
-
-def main(argv=None): # pylint: disable=unused-argument
- GenerateDataset(os.path.join(FLAGS.dataset_dir + '/synthetic_dataset'),
- FLAGS.count,
- [35, 48, 8])
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/compression/entropy_coder/dataset/gen_synthetic_single.py b/research/compression/entropy_coder/dataset/gen_synthetic_single.py
deleted file mode 100644
index b8c3821c38b6a0b95f01ad7ffb283cca4beb34b3..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/dataset/gen_synthetic_single.py
+++ /dev/null
@@ -1,72 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Generate a single synthetic sample."""
-
-import io
-import os
-
-import numpy as np
-import tensorflow as tf
-
-import synthetic_model
-
-
-FLAGS = tf.app.flags.FLAGS
-
-tf.app.flags.DEFINE_string(
- 'sample_filename', None,
- """Output file to store the generated binary code.""")
-
-
-def GenerateSample(filename, code_shape, layer_depth):
- # {0, +1} binary codes.
- # No conversion since the output file is expected to store
- # codes using {0, +1} codes (and not {-1, +1}).
- code = synthetic_model.GenerateSingleCode(code_shape)
- code = np.round(code)
-
- # Reformat the code so as to be compatible with what is generated
- # by the image encoder.
- # The image encoder generates a tensor of size:
- # iteration_count x batch_size x height x width x iteration_depth.
- # Here: batch_size = 1
- if code_shape[-1] % layer_depth != 0:
- raise ValueError('Number of layers is not an integer')
- height = code_shape[0]
- width = code_shape[1]
- code = code.reshape([1, height, width, -1, layer_depth])
- code = np.transpose(code, [3, 0, 1, 2, 4])
-
- int_codes = code.astype(np.int8)
- exported_codes = np.packbits(int_codes.reshape(-1))
-
- output = io.BytesIO()
- np.savez_compressed(output, shape=int_codes.shape, codes=exported_codes)
- with tf.gfile.FastGFile(filename, 'wb') as code_file:
- code_file.write(output.getvalue())
-
-
-def main(argv=None): # pylint: disable=unused-argument
- # Note: the height and the width is different from the training dataset.
- # The main purpose is to show that the entropy coder model is fully
- # convolutional and can be used on any image size.
- layer_depth = 2
- GenerateSample(FLAGS.sample_filename, [31, 36, 8], layer_depth)
-
-
-if __name__ == '__main__':
- tf.app.run()
-
diff --git a/research/compression/entropy_coder/dataset/synthetic_model.py b/research/compression/entropy_coder/dataset/synthetic_model.py
deleted file mode 100644
index 9cccb64a136aba5a623c95e7c2dede2191d2cd62..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/dataset/synthetic_model.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Binary code sample generator."""
-
-import numpy as np
-from six.moves import xrange
-
-
-_CRC_LINE = [
- [0, 1, 0],
- [1, 1, 0],
- [1, 0, 0]
-]
-
-_CRC_DEPTH = [1, 1, 0, 1]
-
-
-def ComputeLineCrc(code, width, y, x, d):
- crc = 0
- for dy in xrange(len(_CRC_LINE)):
- i = y - 1 - dy
- if i < 0:
- continue
- for dx in xrange(len(_CRC_LINE[dy])):
- j = x - 2 + dx
- if j < 0 or j >= width:
- continue
- crc += 1 if (code[i, j, d] != _CRC_LINE[dy][dx]) else 0
- return crc
-
-
-def ComputeDepthCrc(code, y, x, d):
- crc = 0
- for delta in xrange(len(_CRC_DEPTH)):
- k = d - 1 - delta
- if k < 0:
- continue
- crc += 1 if (code[y, x, k] != _CRC_DEPTH[delta]) else 0
- return crc
-
-
-def GenerateSingleCode(code_shape):
- code = np.zeros(code_shape, dtype=np.int)
-
- keep_value_proba = 0.8
-
- height = code_shape[0]
- width = code_shape[1]
- depth = code_shape[2]
-
- for d in xrange(depth):
- for y in xrange(height):
- for x in xrange(width):
- v1 = ComputeLineCrc(code, width, y, x, d)
- v2 = ComputeDepthCrc(code, y, x, d)
- v = 1 if (v1 + v2 >= 6) else 0
- if np.random.rand() < keep_value_proba:
- code[y, x, d] = v
- else:
- code[y, x, d] = 1 - v
-
- return code
diff --git a/research/compression/entropy_coder/lib/__init__.py b/research/compression/entropy_coder/lib/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/compression/entropy_coder/lib/block_base.py b/research/compression/entropy_coder/lib/block_base.py
deleted file mode 100644
index 615dff82829dbbcab46c7217cd35f6259de01161..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/lib/block_base.py
+++ /dev/null
@@ -1,258 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Base class for Tensorflow building blocks."""
-
-import collections
-import contextlib
-import itertools
-
-import tensorflow as tf
-
-_block_stacks = collections.defaultdict(lambda: [])
-
-
-class BlockBase(object):
- """Base class for transform wrappers of Tensorflow.
-
- To implement a Tensorflow transform block, inherit this class.
-
- 1. To create a variable, use NewVar() method. Do not overload this method!
- For example, use as follows.
- a_variable = self.NewVar(initial_value)
-
- 2. All Tensorflow-related code must be done inside 'with self._BlockScope().'
- Otherwise, name scoping and block hierarchy will not work. An exception
- is _Apply() method, which is already called inside the context manager
- by __call__() method.
-
- 3. Override and implement _Apply() method. This method is called by
- __call__() method.
-
- The users would use blocks like the following.
- nn1 = NN(128, bias=Bias(0), act=tf.nn.relu)
- y = nn1(x)
-
- Some things to consider.
-
- - Use lazy-initialization if possible. That is, initialize at first Apply()
- rather than at __init__().
-
- Note: if needed, the variables can be created on a specific parameter
- server by creating blocks in a scope like:
- with g.device(device):
- linear = Linear(...)
- """
-
- def __init__(self, name):
- self._variables = []
- self._subblocks = []
- self._called = False
-
- # Intentionally distinguishing empty string and None.
- # If name is an empty string, then do not use name scope.
- self.name = name if name is not None else self.__class__.__name__
- self._graph = tf.get_default_graph()
-
- if self.name:
- # Capture the scope string at the init time.
- with self._graph.name_scope(self.name) as scope:
- self._scope_str = scope
- else:
- self._scope_str = ''
-
- # Maintain hierarchy structure of blocks.
- self._stack = _block_stacks[self._graph]
- if self.__class__ is BlockBase:
- # This code is only executed to create the root, which starts in the
- # initialized state.
- assert not self._stack
- self._parent = None
- self._called = True # The root is initialized.
- return
-
- # Create a fake root if a root is not already present.
- if not self._stack:
- self._stack.append(BlockBase('NoOpRoot'))
-
- self._parent = self._stack[-1]
- self._parent._subblocks.append(self) # pylint: disable=protected-access
-
- def __repr__(self):
- return '"{}" ({})'.format(self._scope_str, self.__class__.__name__)
-
- @contextlib.contextmanager
- def _OptionalNameScope(self, scope_str):
- if scope_str:
- with self._graph.name_scope(scope_str):
- yield
- else:
- yield
-
- @contextlib.contextmanager
- def _BlockScope(self):
- """Context manager that handles graph, namescope, and nested blocks."""
- self._stack.append(self)
-
- try:
- with self._graph.as_default():
- with self._OptionalNameScope(self._scope_str):
- yield self
- finally: # Pop from the stack no matter exception is raised or not.
- # The following line is executed when leaving 'with self._BlockScope()'
- self._stack.pop()
-
- def __call__(self, *args, **kwargs):
- assert self._stack is _block_stacks[self._graph]
-
- with self._BlockScope():
- ret = self._Apply(*args, **kwargs)
-
- self._called = True
- return ret
-
- def _Apply(self, *args, **kwargs):
- """Implementation of __call__()."""
- raise NotImplementedError()
-
- # Redirect all variable creation to this single function, so that we can
- # switch to better variable creation scheme.
- def NewVar(self, value, **kwargs):
- """Creates a new variable.
-
- This function creates a variable, then returns a local copy created by
- Identity operation. To get the Variable class object, use LookupRef()
- method.
-
- Note that each time Variable class object is used as an input to an
- operation, Tensorflow will create a new Send/Recv pair. This hurts
- performance.
-
- If not for assign operations, use the local copy returned by this method.
-
- Args:
- value: Initialization value of the variable. The shape and the data type
- of the variable is determined by this initial value.
- **kwargs: Extra named arguments passed to Variable.__init__().
-
- Returns:
- A local copy of the new variable.
- """
- v = tf.Variable(value, **kwargs)
-
- self._variables.append(v)
- return v
-
- @property
- def initialized(self):
- """Returns bool if the block is initialized.
-
- By default, BlockBase assumes that a block is initialized when __call__()
- is executed for the first time. If this is an incorrect assumption for some
- subclasses, override this property in those subclasses.
-
- Returns:
- True if initialized, False otherwise.
- """
- return self._called
-
- def AssertInitialized(self):
- """Asserts initialized property."""
- if not self.initialized:
- raise RuntimeError('{} has not been initialized.'.format(self))
-
- def VariableList(self):
- """Returns the list of all tensorflow variables used inside this block."""
- variables = list(itertools.chain(
- itertools.chain.from_iterable(
- t.VariableList() for t in self._subblocks),
- self._VariableList()))
- return variables
-
- def _VariableList(self):
- """Returns the list of all tensorflow variables owned by this block."""
- self.AssertInitialized()
- return self._variables
-
- def CreateWeightLoss(self):
- """Returns L2 loss list of (almost) all variables used inside this block.
-
- When this method needs to be overridden, there are two choices.
-
- 1. Override CreateWeightLoss() to change the weight loss of all variables
- that belong to this block, both directly and indirectly.
- 2. Override _CreateWeightLoss() to change the weight loss of all
- variables that directly belong to this block but not to the sub-blocks.
-
- Returns:
- A Tensor object or None.
- """
- losses = list(itertools.chain(
- itertools.chain.from_iterable(
- t.CreateWeightLoss() for t in self._subblocks),
- self._CreateWeightLoss()))
- return losses
-
- def _CreateWeightLoss(self):
- """Returns weight loss list of variables that belong to this block."""
- self.AssertInitialized()
- with self._BlockScope():
- return [tf.nn.l2_loss(v) for v in self._variables]
-
- def CreateUpdateOps(self):
- """Creates update operations for this block and its sub-blocks."""
- ops = list(itertools.chain(
- itertools.chain.from_iterable(
- t.CreateUpdateOps() for t in self._subblocks),
- self._CreateUpdateOps()))
- return ops
-
- def _CreateUpdateOps(self):
- """Creates update operations for this block."""
- self.AssertInitialized()
- return []
-
- def MarkAsNonTrainable(self):
- """Mark all the variables of this block as non-trainable.
-
- All the variables owned directly or indirectly (through subblocks) are
- marked as non trainable.
-
- This function along with CheckpointInitOp can be used to load a pretrained
- model that consists in only one part of the whole graph.
- """
- assert self._called
-
- all_variables = self.VariableList()
- collection = tf.get_collection_ref(tf.GraphKeys.TRAINABLE_VARIABLES)
- for v in all_variables:
- if v in collection:
- collection.remove(v)
-
-
-def CreateWeightLoss():
- """Returns all weight losses from the blocks in the graph."""
- stack = _block_stacks[tf.get_default_graph()]
- if not stack:
- return []
- return stack[0].CreateWeightLoss()
-
-
-def CreateBlockUpdates():
- """Combines all updates from the blocks in the graph."""
- stack = _block_stacks[tf.get_default_graph()]
- if not stack:
- return []
- return stack[0].CreateUpdateOps()
diff --git a/research/compression/entropy_coder/lib/block_util.py b/research/compression/entropy_coder/lib/block_util.py
deleted file mode 100644
index 80479cc66df95338aa119ba1216cd213ecfbe08d..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/lib/block_util.py
+++ /dev/null
@@ -1,101 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Utility functions for blocks."""
-
-from __future__ import division
-from __future__ import unicode_literals
-
-import math
-
-import numpy as np
-import six
-import tensorflow as tf
-
-
-class RsqrtInitializer(object):
- """Gaussian initializer with standard deviation 1/sqrt(n).
-
- Note that tf.truncated_normal is used internally. Therefore any random sample
- outside two-sigma will be discarded and re-sampled.
- """
-
- def __init__(self, dims=(0,), **kwargs):
- """Creates an initializer.
-
- Args:
- dims: Dimension(s) index to compute standard deviation:
- 1.0 / sqrt(product(shape[dims]))
- **kwargs: Extra keyword arguments to pass to tf.truncated_normal.
- """
- if isinstance(dims, six.integer_types):
- self._dims = [dims]
- else:
- self._dims = dims
- self._kwargs = kwargs
-
- def __call__(self, shape, dtype):
- stddev = 1.0 / np.sqrt(np.prod([shape[x] for x in self._dims]))
- return tf.truncated_normal(
- shape=shape, dtype=dtype, stddev=stddev, **self._kwargs)
-
-
-class RectifierInitializer(object):
- """Gaussian initializer with standard deviation sqrt(2/fan_in).
-
- Note that tf.random_normal is used internally to ensure the expected weight
- distribution. This is intended to be used with ReLU activations, specially
- in ResNets.
-
- For details please refer to:
- Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet
- Classification
- """
-
- def __init__(self, dims=(0,), scale=2.0, **kwargs):
- """Creates an initializer.
-
- Args:
- dims: Dimension(s) index to compute standard deviation:
- sqrt(scale / product(shape[dims]))
- scale: A constant scaling for the initialization used as
- sqrt(scale / product(shape[dims])).
- **kwargs: Extra keyword arguments to pass to tf.truncated_normal.
- """
- if isinstance(dims, six.integer_types):
- self._dims = [dims]
- else:
- self._dims = dims
- self._kwargs = kwargs
- self._scale = scale
-
- def __call__(self, shape, dtype):
- stddev = np.sqrt(self._scale / np.prod([shape[x] for x in self._dims]))
- return tf.random_normal(
- shape=shape, dtype=dtype, stddev=stddev, **self._kwargs)
-
-
-class GaussianInitializer(object):
- """Gaussian initializer with a given standard deviation.
-
- Note that tf.truncated_normal is used internally. Therefore any random sample
- outside two-sigma will be discarded and re-sampled.
- """
-
- def __init__(self, stddev=1.0):
- self._stddev = stddev
-
- def __call__(self, shape, dtype):
- return tf.truncated_normal(shape=shape, dtype=dtype, stddev=self._stddev)
diff --git a/research/compression/entropy_coder/lib/blocks.py b/research/compression/entropy_coder/lib/blocks.py
deleted file mode 100644
index 002384eb07045f1cad963d217a205ade51ba03b6..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/lib/blocks.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-from block_base import *
-from block_util import *
-from blocks_binarizer import *
-from blocks_entropy_coding import *
-from blocks_lstm import *
-from blocks_masked_conv2d import *
-from blocks_masked_conv2d_lstm import *
-from blocks_operator import *
-from blocks_std import *
diff --git a/research/compression/entropy_coder/lib/blocks_binarizer.py b/research/compression/entropy_coder/lib/blocks_binarizer.py
deleted file mode 100644
index 8206731610613af2cf3ec15210fd5b9977f4a916..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/lib/blocks_binarizer.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Activation and weight binarizer implementations."""
-
-import math
-
-import numpy as np
-import tensorflow as tf
-
-
-def ConvertSignCodeToZeroOneCode(x):
- """Conversion from codes {-1, +1} to codes {0, 1}."""
- return 0.5 * (x + 1.0)
-
-
-def ConvertZeroOneCodeToSignCode(x):
- """Convert from codes {0, 1} to codes {-1, +1}."""
- return 2.0 * x - 1.0
-
-
-def CheckZeroOneCode(x):
- return tf.reduce_all(tf.equal(x * (x - 1.0), 0))
diff --git a/research/compression/entropy_coder/lib/blocks_entropy_coding.py b/research/compression/entropy_coder/lib/blocks_entropy_coding.py
deleted file mode 100644
index 6ee5d97926c1b50b12cb9853d16caa25ba31e8d7..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/lib/blocks_entropy_coding.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Set of blocks related to entropy coding."""
-
-import math
-
-import tensorflow as tf
-
-import block_base
-
-# pylint does not recognize block_base.BlockBase.__call__().
-# pylint: disable=not-callable
-
-
-class CodeLength(block_base.BlockBase):
- """Theoretical bound for a code length given a probability distribution.
- """
-
- def __init__(self, name=None):
- super(CodeLength, self).__init__(name)
-
- def _Apply(self, c, p):
- """Theoretical bound of the coded length given a probability distribution.
-
- Args:
- c: The binary codes. Belong to {0, 1}.
- p: The probability of: P(code==+1)
-
- Returns:
- The average code length.
- Note: the average code length can be greater than 1 bit (e.g. when
- encoding the least likely symbol).
- """
- entropy = ((1.0 - c) * tf.log(1.0 - p) + c * tf.log(p)) / (-math.log(2))
- entropy = tf.reduce_mean(entropy)
- return entropy
diff --git a/research/compression/entropy_coder/lib/blocks_entropy_coding_test.py b/research/compression/entropy_coder/lib/blocks_entropy_coding_test.py
deleted file mode 100644
index 5209865f5991598ee873ed24a4be572e3f9fc515..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/lib/blocks_entropy_coding_test.py
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests for basic tensorflow blocks_entropy_coding."""
-
-from __future__ import division
-from __future__ import unicode_literals
-
-import math
-
-import numpy as np
-import tensorflow as tf
-
-import blocks_entropy_coding
-
-
-class BlocksEntropyCodingTest(tf.test.TestCase):
-
- def testCodeLength(self):
- shape = [2, 4]
- proba_feed = [[0.65, 0.25, 0.70, 0.10],
- [0.28, 0.20, 0.44, 0.54]]
- symbol_feed = [[1.0, 0.0, 1.0, 0.0],
- [0.0, 0.0, 0.0, 1.0]]
- mean_code_length = - (
- (math.log(0.65) + math.log(0.75) + math.log(0.70) + math.log(0.90) +
- math.log(0.72) + math.log(0.80) + math.log(0.56) + math.log(0.54)) /
- math.log(2.0)) / (shape[0] * shape[1])
-
- symbol = tf.placeholder(dtype=tf.float32, shape=shape)
- proba = tf.placeholder(dtype=tf.float32, shape=shape)
- code_length_calculator = blocks_entropy_coding.CodeLength()
- code_length = code_length_calculator(symbol, proba)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- code_length_eval = code_length.eval(
- feed_dict={symbol: symbol_feed, proba: proba_feed})
-
- self.assertAllClose(mean_code_length, code_length_eval)
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/compression/entropy_coder/lib/blocks_lstm.py b/research/compression/entropy_coder/lib/blocks_lstm.py
deleted file mode 100644
index 6e474e3e3fcb6eeb3f18daf320e21a3acc88a2bf..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/lib/blocks_lstm.py
+++ /dev/null
@@ -1,263 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Blocks of LSTM and its variants."""
-
-import numpy as np
-import tensorflow as tf
-
-import block_base
-import block_util
-import blocks_std
-
-# pylint does not recognize block_base.BlockBase.__call__().
-# pylint: disable=not-callable
-
-
-def LSTMBiasInit(shape, dtype):
- """Returns ones for forget-gate, and zeros for the others."""
- shape = np.array(shape)
-
- # Check internal consistencies.
- assert shape.shape == (1,), shape
- assert shape[0] % 4 == 0, shape
-
- n = shape[0] // 4
- ones = tf.fill([n], tf.constant(1, dtype=dtype))
- zeros = tf.fill([3 * n], tf.constant(0, dtype=dtype))
- return tf.concat([ones, zeros], 0)
-
-
-class LSTMBase(block_base.BlockBase):
- """Base class for LSTM implementations.
-
- These LSTM implementations use the pattern found in [1]. No peephole
- connection, i.e., cell content is not used in recurrence computation.
- Hidden units are also output units.
-
- [1] Zaremba, Sutskever, Vinyals. Recurrent Neural Network Regularization,
- 2015. arxiv:1409.2329.
- """
-
- def __init__(self, output_shape, name):
- """Initializes LSTMBase class object.
-
- Args:
- output_shape: List representing the LSTM output shape. This argument
- does not include batch dimension. For example, if the LSTM output has
- shape [batch, depth], then pass [depth].
- name: Name of this block.
- """
- super(LSTMBase, self).__init__(name)
-
- with self._BlockScope():
- self._output_shape = [None] + list(output_shape)
- self._hidden = None
- self._cell = None
-
- @property
- def hidden(self):
- """Returns the hidden units of this LSTM."""
- return self._hidden
-
- @hidden.setter
- def hidden(self, value):
- """Assigns to the hidden units of this LSTM.
-
- Args:
- value: The new value for the hidden units. If None, the hidden units are
- considered to be filled with zeros.
- """
- if value is not None:
- value.get_shape().assert_is_compatible_with(self._output_shape)
- self._hidden = value
-
- @property
- def cell(self):
- """Returns the cell units of this LSTM."""
- return self._cell
-
- @cell.setter
- def cell(self, value):
- """Assigns to the cell units of this LSTM.
-
- Args:
- value: The new value for the cell units. If None, the cell units are
- considered to be filled with zeros.
- """
- if value is not None:
- value.get_shape().assert_is_compatible_with(self._output_shape)
- self._cell = value
-
- # Consider moving bias terms to the base, and require this method to be
- # linear.
- def _TransformInputs(self, _):
- """Transforms the input units to (4 * depth) units.
-
- The forget-gate, input-gate, output-gate, and cell update is computed as
- f, i, j, o = T(h) + R(x)
- where h is hidden units, x is input units, and T, R are transforms of
- h, x, respectively.
-
- This method implements R. Note that T is strictly linear, so if LSTM is
- going to use bias, this method must include the bias to the transformation.
-
- Subclasses must implement this method. See _Apply() for more details.
- """
- raise NotImplementedError()
-
- def _TransformHidden(self, _):
- """Transforms the hidden units to (4 * depth) units.
-
- The forget-gate, input-gate, output-gate, and cell update is computed as
- f, i, j, o = T(h) + R(x)
- where h is hidden units, x is input units, and T, R are transforms of
- h, x, respectively.
-
- This method implements T in the equation. The method must implement a
- strictly linear transformation. For example, it may use MatMul or Conv2D,
- but must not add bias. This is because when hidden units are zeros, then
- the LSTM implementation will skip calling this method, instead of passing
- zeros to this function.
-
- Subclasses must implement this method. See _Apply() for more details.
- """
- raise NotImplementedError()
-
- def _Apply(self, *args):
- xtransform = self._TransformInputs(*args)
- depth_axis = len(self._output_shape) - 1
-
- if self.hidden is not None:
- htransform = self._TransformHidden(self.hidden)
- f, i, j, o = tf.split(
- value=htransform + xtransform, num_or_size_splits=4, axis=depth_axis)
- else:
- f, i, j, o = tf.split(
- value=xtransform, num_or_size_splits=4, axis=depth_axis)
-
- if self.cell is not None:
- self.cell = tf.sigmoid(f) * self.cell + tf.sigmoid(i) * tf.tanh(j)
- else:
- self.cell = tf.sigmoid(i) * tf.tanh(j)
-
- self.hidden = tf.sigmoid(o) * tf.tanh(self.cell)
- return self.hidden
-
-
-class LSTM(LSTMBase):
- """Efficient LSTM implementation used in [1].
-
- [1] Zaremba, Sutskever, Vinyals. Recurrent Neural Network Regularization,
- 2015. arxiv:1409.2329.
- """
-
- def __init__(self,
- depth,
- bias=LSTMBiasInit,
- initializer=block_util.RsqrtInitializer(),
- name=None):
- super(LSTM, self).__init__([depth], name)
-
- with self._BlockScope():
- self._depth = depth
- self._nn = blocks_std.NN(
- 4 * depth, bias=bias, act=None, initializer=initializer)
- self._hidden_linear = blocks_std.Linear(
- 4 * depth, initializer=initializer)
-
- def _TransformInputs(self, *args):
- return self._nn(*args)
-
- def _TransformHidden(self, h):
- return self._hidden_linear(h)
-
-
-class Conv2DLSTM(LSTMBase):
- """Convolutional LSTM implementation with optimizations inspired by [1].
-
- Note that when using the batch normalization feature, the bias initializer
- will not be used, since BN effectively cancels its effect out.
-
- [1] Zaremba, Sutskever, Vinyals. Recurrent Neural Network Regularization,
- 2015. arxiv:1409.2329.
- """
-
- def __init__(self,
- depth,
- filter_size,
- hidden_filter_size,
- strides,
- padding,
- bias=LSTMBiasInit,
- initializer=block_util.RsqrtInitializer(dims=(0, 1, 2)),
- use_moving_average=False,
- name=None):
- super(Conv2DLSTM, self).__init__([None, None, depth], name)
- self._iter = 0
-
- with self._BlockScope():
- self._input_conv = blocks_std.Conv2D(
- 4 * depth,
- filter_size,
- strides,
- padding,
- bias=None,
- act=None,
- initializer=initializer,
- name='input_conv2d')
-
- self._hidden_conv = blocks_std.Conv2D(
- 4 * depth,
- hidden_filter_size,
- [1, 1],
- 'SAME',
- bias=None,
- act=None,
- initializer=initializer,
- name='hidden_conv2d')
-
- if bias is not None:
- self._bias = blocks_std.BiasAdd(bias, name='biases')
- else:
- self._bias = blocks_std.PassThrough()
-
- def _TransformInputs(self, x):
- return self._bias(self._input_conv(x))
-
- def _TransformHidden(self, h):
- return self._hidden_conv(h)
-
- def _Apply(self, *args):
- xtransform = self._TransformInputs(*args)
- depth_axis = len(self._output_shape) - 1
-
- if self.hidden is not None:
- htransform = self._TransformHidden(self.hidden)
- f, i, j, o = tf.split(
- value=htransform + xtransform, num_or_size_splits=4, axis=depth_axis)
- else:
- f, i, j, o = tf.split(
- value=xtransform, num_or_size_splits=4, axis=depth_axis)
-
- if self.cell is not None:
- self.cell = tf.sigmoid(f) * self.cell + tf.sigmoid(i) * tf.tanh(j)
- else:
- self.cell = tf.sigmoid(i) * tf.tanh(j)
-
- self.hidden = tf.sigmoid(o) * tf.tanh(self.cell)
-
- self._iter += 1
- return self.hidden
diff --git a/research/compression/entropy_coder/lib/blocks_lstm_test.py b/research/compression/entropy_coder/lib/blocks_lstm_test.py
deleted file mode 100644
index 03c32dc136effda11163f2e35c5a48496f0187c0..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/lib/blocks_lstm_test.py
+++ /dev/null
@@ -1,113 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests for LSTM tensorflow blocks."""
-from __future__ import division
-
-import numpy as np
-import tensorflow as tf
-
-import block_base
-import blocks_std
-import blocks_lstm
-
-
-class BlocksLSTMTest(tf.test.TestCase):
-
- def CheckUnary(self, y, op_type):
- self.assertEqual(op_type, y.op.type)
- self.assertEqual(1, len(y.op.inputs))
- return y.op.inputs[0]
-
- def CheckBinary(self, y, op_type):
- self.assertEqual(op_type, y.op.type)
- self.assertEqual(2, len(y.op.inputs))
- return y.op.inputs
-
- def testLSTM(self):
- lstm = blocks_lstm.LSTM(10)
- lstm.hidden = tf.zeros(shape=[10, 10], dtype=tf.float32)
- lstm.cell = tf.zeros(shape=[10, 10], dtype=tf.float32)
- x = tf.placeholder(dtype=tf.float32, shape=[10, 11])
- y = lstm(x)
-
- o, tanhc = self.CheckBinary(y, 'Mul')
- self.assertEqual(self.CheckUnary(o, 'Sigmoid').name, 'LSTM/split:3')
-
- self.assertIs(lstm.cell, self.CheckUnary(tanhc, 'Tanh'))
- fc, ij = self.CheckBinary(lstm.cell, 'Add')
-
- f, _ = self.CheckBinary(fc, 'Mul')
- self.assertEqual(self.CheckUnary(f, 'Sigmoid').name, 'LSTM/split:0')
-
- i, j = self.CheckBinary(ij, 'Mul')
- self.assertEqual(self.CheckUnary(i, 'Sigmoid').name, 'LSTM/split:1')
- j = self.CheckUnary(j, 'Tanh')
- self.assertEqual(j.name, 'LSTM/split:2')
-
- def testLSTMBiasInit(self):
- lstm = blocks_lstm.LSTM(9)
- x = tf.placeholder(dtype=tf.float32, shape=[15, 7])
- lstm(x)
- b = lstm._nn._bias
-
- with self.test_session():
- tf.global_variables_initializer().run()
- bias_var = b._bias.eval()
-
- comp = ([1.0] * 9) + ([0.0] * 27)
- self.assertAllEqual(bias_var, comp)
-
- def testConv2DLSTM(self):
- lstm = blocks_lstm.Conv2DLSTM(depth=10,
- filter_size=[1, 1],
- hidden_filter_size=[1, 1],
- strides=[1, 1],
- padding='SAME')
- lstm.hidden = tf.zeros(shape=[10, 11, 11, 10], dtype=tf.float32)
- lstm.cell = tf.zeros(shape=[10, 11, 11, 10], dtype=tf.float32)
- x = tf.placeholder(dtype=tf.float32, shape=[10, 11, 11, 1])
- y = lstm(x)
-
- o, tanhc = self.CheckBinary(y, 'Mul')
- self.assertEqual(self.CheckUnary(o, 'Sigmoid').name, 'Conv2DLSTM/split:3')
-
- self.assertIs(lstm.cell, self.CheckUnary(tanhc, 'Tanh'))
- fc, ij = self.CheckBinary(lstm.cell, 'Add')
-
- f, _ = self.CheckBinary(fc, 'Mul')
- self.assertEqual(self.CheckUnary(f, 'Sigmoid').name, 'Conv2DLSTM/split:0')
-
- i, j = self.CheckBinary(ij, 'Mul')
- self.assertEqual(self.CheckUnary(i, 'Sigmoid').name, 'Conv2DLSTM/split:1')
- j = self.CheckUnary(j, 'Tanh')
- self.assertEqual(j.name, 'Conv2DLSTM/split:2')
-
- def testConv2DLSTMBiasInit(self):
- lstm = blocks_lstm.Conv2DLSTM(9, 1, 1, [1, 1], 'SAME')
- x = tf.placeholder(dtype=tf.float32, shape=[1, 7, 7, 7])
- lstm(x)
- b = lstm._bias
-
- with self.test_session():
- tf.global_variables_initializer().run()
- bias_var = b._bias.eval()
-
- comp = ([1.0] * 9) + ([0.0] * 27)
- self.assertAllEqual(bias_var, comp)
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/compression/entropy_coder/lib/blocks_masked_conv2d.py b/research/compression/entropy_coder/lib/blocks_masked_conv2d.py
deleted file mode 100644
index 3f562384a681964554ead02477da24c13715d4d1..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/lib/blocks_masked_conv2d.py
+++ /dev/null
@@ -1,226 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Define some typical masked 2D convolutions."""
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-import block_util
-import blocks_std
-
-# pylint does not recognize block_base.BlockBase.__call__().
-# pylint: disable=not-callable
-
-
-class RasterScanConv2D(blocks_std.Conv2DBase):
- """Conv2D with no dependency on future pixels (in raster scan order).
-
- For example, assuming a 5 x 5 kernel, the kernel is applied a spatial mask:
- T T T T T
- T T T T T
- T T x F F
- F F F F F
- F F F F F
- where 'T' are pixels which are available when computing the convolution
- for pixel 'x'. All the pixels marked with 'F' are not available.
- 'x' itself is not available if strict_order is True, otherwise, it is
- available.
- """
-
- def __init__(self, depth, filter_size, strides, padding,
- strict_order=True,
- bias=None, act=None, initializer=None, name=None):
- super(RasterScanConv2D, self).__init__(
- depth, filter_size, strides, padding, bias, act, name=name)
-
- if (filter_size[0] % 2) != 1 or (filter_size[1] % 2) != 1:
- raise ValueError('Kernel size should be odd.')
-
- with self._BlockScope():
- if initializer is None:
- initializer = block_util.RsqrtInitializer(dims=(0, 1, 2))
- self._initializer = initializer
- self._strict_order = strict_order
-
- def _CreateKernel(self, shape, dtype):
- init = self._initializer(shape, dtype)
- kernel = self.NewVar(init)
-
- mask = np.ones(shape[:2], dtype=dtype.as_numpy_dtype)
- center = shape[:2] // 2
- mask[center[0] + 1:, :] = 0
- if not self._strict_order:
- mask[center[0], center[1] + 1:] = 0
- else:
- mask[center[0], center[1]:] = 0
- mask = mask.reshape(mask.shape + (1, 1))
-
- return tf.convert_to_tensor(mask, dtype) * kernel
-
-
-class DepthOrderConv2D(blocks_std.Conv2DBase):
- """Conv2D with no dependency on higher depth dimensions.
-
- More precisely, the output depth #n has only dependencies on input depths #k
- for k < n (if strict_order is True) or for k <= n (if strict_order is False).
- """
-
- def __init__(self, depth, filter_size, strides, padding,
- strict_order=True,
- bias=None, act=None, initializer=None, name=None):
- super(DepthOrderConv2D, self).__init__(
- depth, filter_size, strides, padding, bias, act, name=name)
-
- with self._BlockScope():
- if initializer is None:
- initializer = block_util.RsqrtInitializer(dims=(0, 1, 2))
- self._initializer = initializer
- self._strict_order = strict_order
-
- def _CreateKernel(self, shape, dtype):
- init = self._initializer(shape, dtype)
- kernel = self.NewVar(init)
-
- mask = np.ones(shape[2:], dtype=dtype.as_numpy_dtype)
- depth_output = shape[3]
- for d in xrange(depth_output):
- if self._strict_order:
- mask[d:, d] = 0
- else:
- mask[d + 1:, d] = 0
- mask = mask.reshape((1, 1) + mask.shape)
-
- return tf.convert_to_tensor(mask, dtype) * kernel
-
-
-class GroupRasterScanConv2D(blocks_std.Conv2DBase):
- """Conv2D with no dependency on future pixels (in raster scan order).
-
- This version only introduces dependencies on previous pixels in raster scan
- order. It can also introduce some dependencies on previous depth positions
- of the current pixel (current pixel = center pixel of the kernel) in the
- following way:
- the depth dimension of the input is split into Ki groups of size
- |input_group_size|, the output dimension is split into Ko groups of size
- |output_group_size| (usually Ki == Ko). Each output group ko of the current
- pixel position can only depend on previous input groups ki
- (i.e. ki < ko if strict_order is True or ki <= ko if strict_order is False).
-
- Notes:
- - Block RasterScanConv2D is a special case of GroupRasterScanConv2D
- where Ki == Ko == 1 (i.e. input_group_size == input_depth and
- output_group_size == output_depth).
- - For 1x1 convolution, block DepthOrderConv2D is a special case of
- GroupRasterScanConv2D where input_group_size == 1 and
- output_group_size == 1.
- """
-
- def __init__(self, depth, filter_size, strides, padding,
- strict_order=True,
- input_group_size=1,
- output_group_size=1,
- bias=None, act=None, initializer=None, name=None):
- super(GroupRasterScanConv2D, self).__init__(
- depth, filter_size, strides, padding, bias, act, name=name)
-
- if (filter_size[0] % 2) != 1 or (filter_size[1] % 2) != 1:
- raise ValueError('Kernel size should be odd.')
-
- with self._BlockScope():
- if initializer is None:
- initializer = block_util.RsqrtInitializer(dims=(0, 1, 2))
- self._initializer = initializer
- self._input_group_size = input_group_size
- self._output_group_size = output_group_size
- self._strict_order = strict_order
-
- if depth % self._output_group_size != 0:
- raise ValueError(
- 'Invalid depth group size: {} for depth {}'.format(
- self._output_group_size, depth))
- self._output_group_count = depth // self._output_group_size
-
- def _CreateKernel(self, shape, dtype):
- init = self._initializer(shape, dtype)
- kernel = self.NewVar(init)
-
- depth_input = shape[2]
- if depth_input % self._input_group_size != 0:
- raise ValueError(
- 'Invalid depth group size: {} for depth {}'.format(
- self._input_group_size, depth_input))
- input_group_count = depth_input // self._input_group_size
- output_group_count = self._output_group_count
-
- # Set the mask to 0 for future pixels in raster scan order.
- center = shape[:2] // 2
- mask = np.ones([shape[0], shape[1],
- input_group_count, self._input_group_size,
- output_group_count, self._output_group_size],
- dtype=dtype.as_numpy_dtype)
- mask[center[0] + 1:, :, :, :, :, :] = 0
- mask[center[0], center[1] + 1:, :, :, :, :] = 0
-
- # Adjust the mask for the current position (the center position).
- depth_output = shape[3]
- for d in xrange(output_group_count):
- mask[center[0], center[1], d + 1:, :, d:d + 1, :] = 0
- if self._strict_order:
- mask[center[0], center[1], d, :, d:d + 1, :] = 0
-
- mask = mask.reshape([shape[0], shape[1], depth_input, depth_output])
- return tf.convert_to_tensor(mask, dtype) * kernel
-
-
-class InFillingConv2D(blocks_std.Conv2DBase):
- """Conv2D with kernel having no dependency on the current pixel.
-
- For example, assuming a 5 x 5 kernel, the kernel is applied a spatial mask:
- T T T T T
- T T T T T
- T T x T T
- T T T T T
- T T T T T
- where 'T' marks a pixel which is available when computing the convolution
- for pixel 'x'. 'x' itself is not available.
- """
-
- def __init__(self, depth, filter_size, strides, padding,
- bias=None, act=None, initializer=None, name=None):
- super(InFillingConv2D, self).__init__(
- depth, filter_size, strides, padding, bias, act, name=name)
-
- if (filter_size[0] % 2) != 1 or (filter_size[1] % 2) != 1:
- raise ValueError('Kernel size should be odd.')
- if filter_size[0] == 1 and filter_size[1] == 1:
- raise ValueError('Kernel size should be larger than 1x1.')
-
- with self._BlockScope():
- if initializer is None:
- initializer = block_util.RsqrtInitializer(dims=(0, 1, 2))
- self._initializer = initializer
-
- def _CreateKernel(self, shape, dtype):
- init = self._initializer(shape, dtype)
- kernel = self.NewVar(init)
-
- mask = np.ones(shape[:2], dtype=dtype.as_numpy_dtype)
- center = shape[:2] // 2
- mask[center[0], center[1]] = 0
- mask = mask.reshape(mask.shape + (1, 1))
-
- return tf.convert_to_tensor(mask, dtype) * kernel
diff --git a/research/compression/entropy_coder/lib/blocks_masked_conv2d_lstm.py b/research/compression/entropy_coder/lib/blocks_masked_conv2d_lstm.py
deleted file mode 100644
index 2d6dfeffcaff1289adf3bdec33cb0560db6b0416..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/lib/blocks_masked_conv2d_lstm.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Masked conv2d LSTM."""
-
-import block_base
-import block_util
-import blocks_masked_conv2d
-import blocks_lstm
-import blocks_std
-
-# pylint: disable=not-callable
-
-
-class RasterScanConv2DLSTM(blocks_lstm.LSTMBase):
- """Convolutional LSTM implementation with optimizations inspired by [1].
-
- Note that when using the batch normalization feature, the bias initializer
- will not be used, since BN effectively cancels its effect out.
-
- [1] Zaremba, Sutskever, Vinyals. Recurrent Neural Network Regularization,
- 2015. arxiv:1409.2329.
- """
-
- def __init__(self,
- depth,
- filter_size,
- hidden_filter_size,
- strides,
- padding,
- bias=blocks_lstm.LSTMBiasInit,
- initializer=block_util.RsqrtInitializer(dims=(0, 1, 2)),
- name=None):
- super(RasterScanConv2DLSTM, self).__init__([None, None, depth], name)
-
- with self._BlockScope():
- self._input_conv = blocks_masked_conv2d.RasterScanConv2D(
- 4 * depth,
- filter_size,
- strides,
- padding,
- strict_order=False,
- bias=None,
- act=None,
- initializer=initializer,
- name='input_conv2d')
-
- self._hidden_conv = blocks_std.Conv2D(
- 4 * depth,
- hidden_filter_size,
- [1, 1],
- 'SAME',
- bias=None,
- act=None,
- initializer=initializer,
- name='hidden_conv2d')
-
- if bias is not None:
- self._bias = blocks_std.BiasAdd(bias, name='biases')
- else:
- self._bias = blocks_std.PassThrough()
-
- def _TransformInputs(self, x):
- return self._bias(self._input_conv(x))
-
- def _TransformHidden(self, h):
- return self._hidden_conv(h)
diff --git a/research/compression/entropy_coder/lib/blocks_masked_conv2d_test.py b/research/compression/entropy_coder/lib/blocks_masked_conv2d_test.py
deleted file mode 100644
index 1d284ebffe5a24b91c96936c17d6c23febdf76d5..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/lib/blocks_masked_conv2d_test.py
+++ /dev/null
@@ -1,207 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests of the 2D masked convolution blocks."""
-
-from __future__ import division
-from __future__ import unicode_literals
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-import blocks_masked_conv2d
-
-
-class MaskedConv2DTest(tf.test.TestCase):
-
- def testRasterScanKernel(self):
- kernel_size = 5
- input_depth = 1
- output_depth = 1
- kernel_shape = [kernel_size, kernel_size, input_depth, output_depth]
-
- # pylint: disable=bad-whitespace
- kernel_feed = [[ 1.0, 2.0, 3.0, 4.0, 5.0],
- [ 6.0, 7.0, 8.0, 9.0, 10.0],
- [11.0, 12.0, 13.0, 14.0, 15.0],
- [16.0, 17.0, 18.0, 19.0, 20.0],
- [21.0, 22.0, 23.0, 24.0, 25.0]]
- kernel_feed = np.reshape(kernel_feed, kernel_shape)
- kernel_expected = [[ 1.0, 2.0, 3.0, 4.0, 5.0],
- [ 6.0, 7.0, 8.0, 9.0, 10.0],
- [11.0, 12.0, 0.0, 0.0, 0.0],
- [ 0.0, 0.0, 0.0, 0.0, 0.0],
- [ 0.0, 0.0, 0.0, 0.0, 0.0]]
- kernel_expected = np.reshape(kernel_expected, kernel_shape)
- # pylint: enable=bad-whitespace
-
- init_kernel = lambda s, t: tf.constant(kernel_feed, dtype=t, shape=s)
- masked_conv2d = blocks_masked_conv2d.RasterScanConv2D(
- output_depth, [kernel_size] * 2, [1] * 2, 'SAME',
- initializer=init_kernel)
- x = tf.placeholder(dtype=tf.float32, shape=[10] * 3 + [input_depth])
- _ = masked_conv2d(x)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- kernel_value = masked_conv2d._kernel.eval()
-
- self.assertAllEqual(kernel_expected, kernel_value)
-
- def testDepthOrderKernel(self):
- kernel_size = 1
- input_depth = 7
- output_depth = input_depth
- kernel_shape = [kernel_size, kernel_size, input_depth, output_depth]
-
- kernel_feed = np.ones(kernel_shape)
- x_shape = [5] * 3 + [input_depth]
- x_feed = np.ones(x_shape)
- y_expected = np.zeros(x_shape[0:3] + [output_depth])
- y_expected[:, :, :] = np.arange(output_depth)
-
- init_kernel = lambda s, t: tf.constant(kernel_feed, dtype=t, shape=s)
- masked_conv2d = blocks_masked_conv2d.DepthOrderConv2D(
- output_depth, [kernel_size] * 2, [1] * 2, 'SAME',
- strict_order=True,
- initializer=init_kernel)
- x = tf.placeholder(dtype=tf.float32, shape=x_shape)
- y = masked_conv2d(x)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- y_value = y.eval(feed_dict={x: x_feed})
-
- self.assertAllEqual(y_expected, y_value)
-
- def testGroupRasterScanKernel(self):
- kernel_size = 3
- input_depth = 4
- input_group_size = 2
- output_depth = 2
- output_group_size = 1
- kernel_shape = [kernel_size, kernel_size, input_depth, output_depth]
- kernel_feed = np.ones(shape=kernel_shape)
-
- height = 5
- width = 5
- x_shape = [1, height, width, input_depth]
- x_feed = np.ones(shape=x_shape)
-
- # pylint: disable=bad-whitespace
- y_expected = [
- [[ 0, 2], [ 4, 6], [ 4, 6], [ 4, 6], [ 4, 6]],
- [[ 8, 10], [16, 18], [16, 18], [16, 18], [12, 14]],
- [[ 8, 10], [16, 18], [16, 18], [16, 18], [12, 14]],
- [[ 8, 10], [16, 18], [16, 18], [16, 18], [12, 14]],
- [[ 8, 10], [16, 18], [16, 18], [16, 18], [12, 14]],
- ]
- y_expected = np.reshape(y_expected, [1, height, width, output_depth])
- # pylint: enable=bad-whitespace
-
- init_kernel = lambda s, t: tf.constant(kernel_feed, dtype=t, shape=s)
- masked_conv2d = blocks_masked_conv2d.GroupRasterScanConv2D(
- output_depth, [kernel_size] * 2, [1] * 2, 'SAME',
- strict_order=True,
- input_group_size=input_group_size,
- output_group_size=output_group_size,
- initializer=init_kernel)
- x = tf.placeholder(dtype=tf.float32, shape=x_shape)
- y = masked_conv2d(x)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- y_value = y.eval(feed_dict={x: x_feed})
-
- self.assertAllEqual(y_expected, y_value)
-
- def testInFillingKernel(self):
- kernel_size = 5
- input_depth = 1
- output_depth = 1
- kernel_shape = [kernel_size, kernel_size, input_depth, output_depth]
-
- # pylint: disable=bad-whitespace
- kernel_feed = [[ 1.0, 2.0, 3.0, 4.0, 5.0],
- [ 6.0, 7.0, 8.0, 9.0, 10.0],
- [11.0, 12.0, 13.0, 14.0, 15.0],
- [16.0, 17.0, 18.0, 19.0, 20.0],
- [21.0, 22.0, 23.0, 24.0, 25.0]]
- kernel_feed = np.reshape(kernel_feed, kernel_shape)
- kernel_expected = [[ 1.0, 2.0, 3.0, 4.0, 5.0],
- [ 6.0, 7.0, 8.0, 9.0, 10.0],
- [11.0, 12.0, 0.0, 14.0, 15.0],
- [16.0, 17.0, 18.0, 19.0, 20.0],
- [21.0, 22.0, 23.0, 24.0, 25.0]]
- kernel_expected = np.reshape(kernel_expected, kernel_shape)
- # pylint: enable=bad-whitespace
-
- init_kernel = lambda s, t: tf.constant(kernel_feed, dtype=t, shape=s)
- masked_conv2d = blocks_masked_conv2d.InFillingConv2D(
- output_depth, [kernel_size] * 2, [1] * 2, 'SAME',
- initializer=init_kernel)
- x = tf.placeholder(dtype=tf.float32, shape=[10] * 3 + [input_depth])
- _ = masked_conv2d(x)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- kernel_value = masked_conv2d._kernel.eval()
-
- self.assertAllEqual(kernel_expected, kernel_value)
-
- def testConv2DMaskedNumerics(self):
- kernel_size = 5
- input_shape = [1, 10, 10, 1]
- filter_shape = [kernel_size, kernel_size, 1, 1]
- strides = [1, 1, 1, 1]
- output_shape = [1, 10, 10, 1]
-
- conv = blocks_masked_conv2d.RasterScanConv2D(
- depth=filter_shape[-1],
- filter_size=filter_shape[0:2],
- strides=strides[1:3],
- padding='SAME',
- initializer=tf.constant_initializer(value=1.0))
- x = tf.placeholder(dtype=tf.float32, shape=input_shape)
- y = conv(x)
-
- x_feed = - np.ones(input_shape, dtype=float)
- y_expected = np.ones(output_shape, dtype=float)
- for i in xrange(input_shape[1]):
- for j in xrange(input_shape[2]):
- x_feed[0, i, j, 0] = 10 * (j + 1) + i
- v = 0
- ki_start = max(i - kernel_size // 2, 0)
- kj_start = max(j - kernel_size // 2, 0)
- kj_end = min(j + kernel_size // 2, input_shape[2] - 1)
- for ki in range(ki_start, i + 1):
- for kj in range(kj_start, kj_end + 1):
- if ki > i:
- continue
- if ki == i and kj >= j:
- continue
- v += 10 * (kj + 1) + ki
- y_expected[0, i, j, 0] = v
-
- with self.test_session():
- tf.global_variables_initializer().run()
- y_value = y.eval(feed_dict={x: x_feed})
-
- self.assertAllEqual(y_expected, y_value)
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/compression/entropy_coder/lib/blocks_operator.py b/research/compression/entropy_coder/lib/blocks_operator.py
deleted file mode 100644
index e35e37b27aa416ed48f91eda866d372601741cba..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/lib/blocks_operator.py
+++ /dev/null
@@ -1,87 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Common blocks which work as operators on other blocks."""
-
-import tensorflow as tf
-
-import block_base
-
-# pylint: disable=not-callable
-
-
-class CompositionOperator(block_base.BlockBase):
- """Composition of several blocks."""
-
- def __init__(self, block_list, name=None):
- """Initialization of the composition operator.
-
- Args:
- block_list: List of blocks.BlockBase that are chained to create
- a new blocks.BlockBase.
- name: Name of this block.
- """
- super(CompositionOperator, self).__init__(name)
- self._blocks = block_list
-
- def _Apply(self, x):
- """Apply successively all the blocks on the given input tensor."""
- h = x
- for layer in self._blocks:
- h = layer(h)
- return h
-
-
-class LineOperator(block_base.BlockBase):
- """Repeat the same block over all the lines of an input tensor."""
-
- def __init__(self, block, name=None):
- super(LineOperator, self).__init__(name)
- self._block = block
-
- def _Apply(self, x):
- height = x.get_shape()[1].value
- if height is None:
- raise ValueError('Unknown tensor height')
- all_line_x = tf.split(value=x, num_or_size_splits=height, axis=1)
-
- y = []
- for line_x in all_line_x:
- y.append(self._block(line_x))
- y = tf.concat(values=y, axis=1)
-
- return y
-
-
-class TowerOperator(block_base.BlockBase):
- """Parallel execution with concatenation of several blocks."""
-
- def __init__(self, block_list, dim=3, name=None):
- """Initialization of the parallel exec + concat (Tower).
-
- Args:
- block_list: List of blocks.BlockBase that are chained to create
- a new blocks.BlockBase.
- dim: the dimension on which to concat.
- name: Name of this block.
- """
- super(TowerOperator, self).__init__(name)
- self._blocks = block_list
- self._concat_dim = dim
-
- def _Apply(self, x):
- """Apply successively all the blocks on the given input tensor."""
- outputs = [layer(x) for layer in self._blocks]
- return tf.concat(outputs, self._concat_dim)
diff --git a/research/compression/entropy_coder/lib/blocks_operator_test.py b/research/compression/entropy_coder/lib/blocks_operator_test.py
deleted file mode 100644
index 8b6d80da1d09102585e4725dd5c59f48d48eafcd..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/lib/blocks_operator_test.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests of the block operators."""
-
-import numpy as np
-import tensorflow as tf
-
-import block_base
-import blocks_operator
-
-
-class AddOneBlock(block_base.BlockBase):
-
- def __init__(self, name=None):
- super(AddOneBlock, self).__init__(name)
-
- def _Apply(self, x):
- return x + 1.0
-
-
-class SquareBlock(block_base.BlockBase):
-
- def __init__(self, name=None):
- super(SquareBlock, self).__init__(name)
-
- def _Apply(self, x):
- return x * x
-
-
-class BlocksOperatorTest(tf.test.TestCase):
-
- def testComposition(self):
- x_value = np.array([[1.0, 2.0, 3.0],
- [-1.0, -2.0, -3.0]])
- y_expected_value = np.array([[4.0, 9.0, 16.0],
- [0.0, 1.0, 4.0]])
-
- x = tf.placeholder(dtype=tf.float32, shape=[2, 3])
- complex_block = blocks_operator.CompositionOperator(
- [AddOneBlock(),
- SquareBlock()])
- y = complex_block(x)
-
- with self.test_session():
- y_value = y.eval(feed_dict={x: x_value})
-
- self.assertAllClose(y_expected_value, y_value)
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/compression/entropy_coder/lib/blocks_std.py b/research/compression/entropy_coder/lib/blocks_std.py
deleted file mode 100644
index 2c617485342452f500d4b1b0b18e33b07d51e487..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/lib/blocks_std.py
+++ /dev/null
@@ -1,363 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Basic blocks for building tensorflow models."""
-
-import numpy as np
-import tensorflow as tf
-
-import block_base
-import block_util
-
-# pylint does not recognize block_base.BlockBase.__call__().
-# pylint: disable=not-callable
-
-
-def HandleConvPaddingModes(x, padding, kernel_shape, strides):
- """Returns an updated tensor and padding type for REFLECT and SYMMETRIC.
-
- Args:
- x: A 4D tensor with shape [batch_size, height, width, depth].
- padding: Padding mode (SAME, VALID, REFLECT, or SYMMETRIC).
- kernel_shape: Shape of convolution kernel that will be applied.
- strides: Convolution stride that will be used.
-
- Returns:
- x and padding after adjustments for REFLECT and SYMMETRIC.
- """
- # For 1x1 convolution, all padding modes are the same.
- if np.all(kernel_shape[:2] == 1):
- return x, 'VALID'
-
- if padding == 'REFLECT' or padding == 'SYMMETRIC':
- # We manually compute the number of paddings as if 'SAME'.
- # From Tensorflow kernel, the formulas are as follows.
- # output_shape = ceil(input_shape / strides)
- # paddings = (output_shape - 1) * strides + filter_size - input_shape
- # Let x, y, s be a shorthand notations for input_shape, output_shape, and
- # strides, respectively. Let (x - 1) = sn + r where 0 <= r < s. Note that
- # y - 1 = ceil(x / s) - 1 = floor((x - 1) / s) = n
- # provided that x > 0. Therefore
- # paddings = n * s + filter_size - (sn + r + 1)
- # = filter_size - r - 1.
- input_shape = x.get_shape() # shape at graph construction time
- img_shape = tf.shape(x)[1:3] # image shape (no batch) at run time
- remainder = tf.mod(img_shape - 1, strides[1:3])
- pad_sizes = kernel_shape[:2] - remainder - 1
-
- pad_rows = pad_sizes[0]
- pad_cols = pad_sizes[1]
- pad = tf.stack([[0, 0], tf.stack([pad_rows // 2, (pad_rows + 1) // 2]),
- tf.stack([pad_cols // 2, (pad_cols + 1) // 2]), [0, 0]])
-
- # Manually pad the input and switch the padding mode to 'VALID'.
- x = tf.pad(x, pad, mode=padding)
- x.set_shape([input_shape[0], x.get_shape()[1],
- x.get_shape()[2], input_shape[3]])
- padding = 'VALID'
-
- return x, padding
-
-
-class PassThrough(block_base.BlockBase):
- """A dummy transform block that does nothing."""
-
- def __init__(self):
- # Pass an empty string to disable name scoping.
- super(PassThrough, self).__init__(name='')
-
- def _Apply(self, inp):
- return inp
-
- @property
- def initialized(self):
- """Always returns True."""
- return True
-
-
-class Bias(object):
- """An initialization helper class for BiasAdd block below."""
-
- def __init__(self, value=0):
- self.value = value
-
-
-class BiasAdd(block_base.BlockBase):
- """A tf.nn.bias_add wrapper.
-
- This wrapper may act as a PassThrough block depending on the initializer
- provided, to make easier optional bias applications in NN blocks, etc.
- See __init__() for the details.
- """
-
- def __init__(self, initializer=Bias(0), name=None):
- """Initializes Bias block.
-
- |initializer| parameter have two special cases.
-
- 1. If initializer is None, then this block works as a PassThrough.
- 2. If initializer is a Bias class object, then tf.constant_initializer is
- used with the stored value.
-
- Args:
- initializer: An initializer for the bias variable.
- name: Name of this block.
- """
- super(BiasAdd, self).__init__(name)
-
- with self._BlockScope():
- if isinstance(initializer, Bias):
- self._initializer = tf.constant_initializer(value=initializer.value)
- else:
- self._initializer = initializer
-
- self._bias = None
-
- def _Apply(self, x):
- if not self._bias:
- init = self._initializer([int(x.get_shape()[-1])], x.dtype)
- self._bias = self.NewVar(init)
-
- return tf.nn.bias_add(x, self._bias)
-
- def CreateWeightLoss(self):
- return []
-
-
-class LinearBase(block_base.BlockBase):
- """A matmul wrapper.
-
- Returns input * W, where matrix W can be customized through derivation.
- """
-
- def __init__(self, depth, name=None):
- super(LinearBase, self).__init__(name)
-
- with self._BlockScope():
- self._depth = depth
- self._matrix = None
-
- def _CreateKernel(self, shape, dtype):
- raise NotImplementedError('This method must be sub-classed.')
-
- def _Apply(self, x):
- if not self._matrix:
- shape = [int(x.get_shape()[-1]), self._depth]
- self._matrix = self._CreateKernel(shape, x.dtype)
-
- return tf.matmul(x, self._matrix)
-
-
-class Linear(LinearBase):
- """A matmul wrapper.
-
- Returns input * W, where matrix W is learned.
- """
-
- def __init__(self,
- depth,
- initializer=block_util.RsqrtInitializer(),
- name=None):
- super(Linear, self).__init__(depth, name)
-
- with self._BlockScope():
- self._initializer = initializer
-
- def _CreateKernel(self, shape, dtype):
- init = self._initializer(shape, dtype)
- return self.NewVar(init)
-
-
-class NN(block_base.BlockBase):
- """A neural network layer wrapper.
-
- Returns act(input * W + b), where matrix W, bias b are learned, and act is an
- optional activation function (i.e., nonlinearity).
-
- This transform block can handle multiple inputs. If x_1, x_2, ..., x_m are
- the inputs, then returns act(x_1 * W_1 + ... + x_m * W_m + b).
-
- Attributes:
- nunits: The dimension of the output.
- """
-
- def __init__(self,
- depth,
- bias=Bias(0),
- act=None, # e.g., tf.nn.relu
- initializer=block_util.RsqrtInitializer(),
- linear_block_factory=(lambda d, i: Linear(d, initializer=i)),
- name=None):
- """Initializes NN block.
-
- Args:
- depth: The depth of the output.
- bias: An initializer for the bias, or a Bias class object. If None, there
- will be no bias term for this NN block. See BiasAdd block.
- act: Optional activation function. If None, no activation is applied.
- initializer: The initialization method for the matrix weights.
- linear_block_factory: A function used to create a linear block.
- name: The name of this block.
- """
- super(NN, self).__init__(name)
-
- with self._BlockScope():
- self._linear_block_factory = linear_block_factory
- self._depth = depth
- self._initializer = initializer
- self._matrices = None
-
- self._bias = BiasAdd(bias) if bias else PassThrough()
- self._act = act if act else PassThrough()
-
- def _Apply(self, *args):
- if not self._matrices:
- self._matrices = [
- self._linear_block_factory(self._depth, self._initializer)
- for _ in args]
-
- if len(self._matrices) != len(args):
- raise ValueError('{} expected {} inputs, but observed {} inputs'.format(
- self.name, len(self._matrices), len(args)))
-
- if len(args) > 1:
- y = tf.add_n([m(x) for m, x in zip(self._matrices, args)])
- else:
- y = self._matrices[0](args[0])
-
- return self._act(self._bias(y))
-
-
-class Conv2DBase(block_base.BlockBase):
- """A tf.nn.conv2d operator."""
-
- def __init__(self, depth, filter_size, strides, padding,
- bias=None, act=None, atrous_rate=None, conv=tf.nn.conv2d,
- name=None):
- """Initializes a Conv2DBase block.
-
- Arguments:
- depth: The output depth of the block (i.e. #filters); if negative, the
- output depth will be set to be the same as the input depth.
- filter_size: The size of the 2D filter. If it's specified as an integer,
- it's going to create a square filter. Otherwise, this is a tuple
- specifying the height x width of the filter.
- strides: A tuple specifying the y and x stride.
- padding: One of the valid padding modes allowed by tf.nn.conv2d, or
- 'REFLECT'/'SYMMETRIC' for mirror padding.
- bias: An initializer for the bias, or a Bias class object. If None, there
- will be no bias in this block. See BiasAdd block.
- act: Optional activation function applied to the output.
- atrous_rate: optional input rate for ATrous convolution. If not None, this
- will be used and the strides will be ignored.
- conv: The convolution function to use (e.g. tf.nn.conv2d).
- name: The name for this conv2d op.
- """
- super(Conv2DBase, self).__init__(name)
-
- with self._BlockScope():
- self._act = act if act else PassThrough()
- self._bias = BiasAdd(bias) if bias else PassThrough()
-
- self._kernel_shape = np.zeros((4,), dtype=np.int32)
- self._kernel_shape[:2] = filter_size
- self._kernel_shape[3] = depth
-
- self._strides = np.ones((4,), dtype=np.int32)
- self._strides[1:3] = strides
- self._strides = list(self._strides)
-
- self._padding = padding
-
- self._kernel = None
- self._conv = conv
-
- self._atrous_rate = atrous_rate
-
- def _CreateKernel(self, shape, dtype):
- raise NotImplementedError('This method must be sub-classed')
-
- def _Apply(self, x):
- """Apply the self._conv op.
-
- Arguments:
- x: input tensor. It needs to be a 4D tensor of the form
- [batch, height, width, channels].
- Returns:
- The output of the convolution of x with the current convolutional
- kernel.
- Raises:
- ValueError: if number of channels is not defined at graph construction.
- """
- input_shape = x.get_shape().with_rank(4)
- input_shape[3:].assert_is_fully_defined() # channels must be defined
- if self._kernel is None:
- assert self._kernel_shape[2] == 0, self._kernel_shape
- self._kernel_shape[2] = input_shape[3].value
- if self._kernel_shape[3] < 0:
- # Make output depth be the same as input depth.
- self._kernel_shape[3] = self._kernel_shape[2]
- self._kernel = self._CreateKernel(self._kernel_shape, x.dtype)
-
- x, padding = HandleConvPaddingModes(
- x, self._padding, self._kernel_shape, self._strides)
- if self._atrous_rate is None:
- x = self._conv(x, self._kernel, strides=self._strides, padding=padding)
- else:
- x = self._conv(x, self._kernel, rate=self._atrous_rate, padding=padding)
-
- if self._padding != 'VALID':
- # Manually update shape. Known shape information can be lost by tf.pad().
- height = (1 + (input_shape[1].value - 1) // self._strides[1]
- if input_shape[1].value else None)
- width = (1 + (input_shape[2].value - 1) // self._strides[2]
- if input_shape[2].value else None)
- shape = x.get_shape()
- x.set_shape([shape[0], height, width, shape[3]])
-
- return self._act(self._bias(x))
-
-
-class Conv2D(Conv2DBase):
- """A tf.nn.conv2d operator."""
-
- def __init__(self, depth, filter_size, strides, padding,
- bias=None, act=None, initializer=None, name=None):
- """Initializes a Conv2D block.
-
- Arguments:
- depth: The output depth of the block (i.e., #filters)
- filter_size: The size of the 2D filter. If it's specified as an integer,
- it's going to create a square filter. Otherwise, this is a tuple
- specifying the height x width of the filter.
- strides: A tuple specifying the y and x stride.
- padding: One of the valid padding modes allowed by tf.nn.conv2d, or
- 'REFLECT'/'SYMMETRIC' for mirror padding.
- bias: An initializer for the bias, or a Bias class object. If None, there
- will be no bias in this block. See BiasAdd block.
- act: Optional activation function applied to the output.
- initializer: Optional initializer for weights.
- name: The name for this conv2d op.
- """
- super(Conv2D, self).__init__(depth, filter_size, strides, padding, bias,
- act, conv=tf.nn.conv2d, name=name)
-
- with self._BlockScope():
- if initializer is None:
- initializer = block_util.RsqrtInitializer(dims=(0, 1, 2))
- self._initializer = initializer
-
- def _CreateKernel(self, shape, dtype):
- return self.NewVar(self._initializer(shape, dtype))
diff --git a/research/compression/entropy_coder/lib/blocks_std_test.py b/research/compression/entropy_coder/lib/blocks_std_test.py
deleted file mode 100644
index 328ebc9d2173436b2108b343b98650128a4613e3..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/lib/blocks_std_test.py
+++ /dev/null
@@ -1,340 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests for basic tensorflow blocks_std."""
-
-from __future__ import division
-from __future__ import unicode_literals
-
-import math
-import os
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-import blocks_std
-
-
-def _NumpyConv2D(x, f, strides, padding, rate=1):
- assert strides[0] == 1 and strides[3] == 1, strides
-
- if rate > 1:
- f_shape = f.shape
- expand_f = np.zeros([f_shape[0], ((f_shape[1] - 1) * rate + 1),
- f_shape[2], f_shape[3]])
- expand_f[:, [y * rate for y in range(f_shape[1])], :, :] = f
- f = np.zeros([((f_shape[0] - 1) * rate + 1), expand_f.shape[1],
- f_shape[2], f_shape[3]])
- f[[y * rate for y in range(f_shape[0])], :, :, :] = expand_f
-
- if padding != 'VALID':
- assert x.shape[1] > 0 and x.shape[2] > 0, x.shape
- # Compute the number of padded rows and cols.
- # See Conv2D block comments for a math explanation.
- remainder = ((x.shape[1] - 1) % strides[1], (x.shape[2] - 1) % strides[2])
- pad_rows = f.shape[0] - remainder[0] - 1
- pad_cols = f.shape[1] - remainder[1] - 1
- pad = ((0, 0),
- (pad_rows // 2, (pad_rows + 1) // 2),
- (pad_cols // 2, (pad_cols + 1) // 2),
- (0, 0))
-
- # Pad the input using numpy.pad().
- mode = None
- if padding == 'SAME':
- mode = str('constant')
- if padding == 'REFLECT':
- mode = str('reflect')
- if padding == 'SYMMETRIC':
- mode = str('symmetric')
- x = np.pad(x, pad, mode=mode)
-
- # Since x is now properly padded, proceed as if padding mode is VALID.
- x_window = np.empty(
- (x.shape[0],
- int(math.ceil((x.shape[1] - f.shape[0] + 1) / strides[1])),
- int(math.ceil((x.shape[2] - f.shape[1] + 1) / strides[2])),
- np.prod(f.shape[:3])))
-
- # The output at pixel location (i, j) is the result of linear transformation
- # applied to the window whose top-left corner is at
- # (i * row_stride, j * col_stride).
- for i in xrange(x_window.shape[1]):
- k = i * strides[1]
- for j in xrange(x_window.shape[2]):
- l = j * strides[2]
- x_window[:, i, j, :] = x[:,
- k:(k + f.shape[0]),
- l:(l + f.shape[1]),
- :].reshape((x_window.shape[0], -1))
-
- y = np.tensordot(x_window, f.reshape((-1, f.shape[3])), axes=1)
- return y
-
-
-class BlocksStdTest(tf.test.TestCase):
-
- def CheckUnary(self, y, op_type):
- self.assertEqual(op_type, y.op.type)
- self.assertEqual(1, len(y.op.inputs))
- return y.op.inputs[0]
-
- def CheckBinary(self, y, op_type):
- self.assertEqual(op_type, y.op.type)
- self.assertEqual(2, len(y.op.inputs))
- return y.op.inputs
-
- def testPassThrough(self):
- p = blocks_std.PassThrough()
- x = tf.placeholder(dtype=tf.float32, shape=[1])
- self.assertIs(p(x), x)
-
- def CheckBiasAdd(self, y, b):
- x, u = self.CheckBinary(y, 'BiasAdd')
- self.assertIs(u, b._bias.value())
- self.assertEqual(x.dtype, u.dtype.base_dtype)
- return x
-
- def testBiasAdd(self):
- b = blocks_std.BiasAdd()
- x = tf.placeholder(dtype=tf.float32, shape=[4, 8])
- y = b(x)
- self.assertEqual(b._bias.get_shape(), x.get_shape()[-1:])
- self.assertIs(x, self.CheckBiasAdd(y, b))
-
- def testBiasRankTest(self):
- b = blocks_std.BiasAdd()
- x = tf.placeholder(dtype=tf.float32, shape=[10])
- with self.assertRaises(ValueError):
- b(x)
-
- def CheckLinear(self, y, m):
- x, w = self.CheckBinary(y, 'MatMul')
- self.assertIs(w, m._matrix.value())
- self.assertEqual(x.dtype, w.dtype.base_dtype)
- return x
-
- def testLinear(self):
- m = blocks_std.Linear(10)
- x = tf.placeholder(dtype=tf.float32, shape=[8, 9])
- y = m(x)
- self.assertEqual(m._matrix.get_shape(), [9, 10])
- self.assertIs(x, self.CheckLinear(y, m))
-
- def testLinearShared(self):
- # Create a linear map which is applied twice on different inputs
- # (i.e. the weights of the map are shared).
- linear_map = blocks_std.Linear(6)
- x1 = tf.random_normal(shape=[1, 5])
- x2 = tf.random_normal(shape=[1, 5])
- xs = x1 + x2
-
- # Apply the transform with the same weights.
- y1 = linear_map(x1)
- y2 = linear_map(x2)
- ys = linear_map(xs)
-
- with self.test_session() as sess:
- # Initialize all the variables of the graph.
- tf.global_variables_initializer().run()
-
- y1_res, y2_res, ys_res = sess.run([y1, y2, ys])
- self.assertAllClose(y1_res + y2_res, ys_res)
-
- def CheckNN(self, y, nn, act=None):
- if act:
- pre_act = self.CheckUnary(y, act)
- else:
- pre_act = y
-
- if not isinstance(nn._bias, blocks_std.PassThrough):
- pre_bias = self.CheckBiasAdd(pre_act, nn._bias)
- else:
- pre_bias = pre_act
-
- if len(nn._matrices) > 1:
- self.assertEqual('AddN', pre_bias.op.type)
- pre_bias = pre_bias.op.inputs
- else:
- pre_bias = [pre_bias]
-
- self.assertEqual(len(pre_bias), len(nn._matrices))
- return [self.CheckLinear(u, m) for u, m in zip(pre_bias, nn._matrices)]
-
- def testNNWithoutActWithoutBias(self):
- nn = blocks_std.NN(10, act=None, bias=None)
- x = tf.placeholder(dtype=tf.float32, shape=[5, 7])
- y = nn(x)
- self.assertIs(x, self.CheckNN(y, nn)[0])
-
- def testNNWithoutBiasWithAct(self):
- nn = blocks_std.NN(10, act=tf.nn.relu, bias=None)
- x = tf.placeholder(dtype=tf.float32, shape=[5, 7])
- y = nn(x)
- self.assertIs(x, self.CheckNN(y, nn, 'Relu')[0])
-
- def testNNWithBiasWithoutAct(self):
- nn = blocks_std.NN(10, bias=blocks_std.Bias(0), act=None)
- x = tf.placeholder(dtype=tf.float32, shape=[5, 7])
- y = nn(x)
- self.assertIs(x, self.CheckNN(y, nn)[0])
-
- def testNNWithBiasWithAct(self):
- nn = blocks_std.NN(10, bias=blocks_std.Bias(0), act=tf.square)
- x = tf.placeholder(dtype=tf.float32, shape=[5, 7])
- y = nn(x)
- self.assertIs(x, self.CheckNN(y, nn, 'Square')[0])
-
- def testNNMultipleInputs(self):
- nn = blocks_std.NN(10, bias=blocks_std.Bias(0), act=tf.tanh)
- x = [tf.placeholder(dtype=tf.float32, shape=[5, 7]),
- tf.placeholder(dtype=tf.float32, shape=[5, 3]),
- tf.placeholder(dtype=tf.float32, shape=[5, 5])]
- y = nn(*x)
- xs = self.CheckNN(y, nn, 'Tanh')
- self.assertEqual(len(x), len(xs))
- for u, v in zip(x, xs):
- self.assertIs(u, v)
-
- def testConv2DSAME(self):
- np.random.seed(142536)
-
- x_shape = [4, 16, 11, 5]
- f_shape = [4, 3, 5, 6]
- strides = [1, 2, 2, 1]
- padding = 'SAME'
-
- conv = blocks_std.Conv2D(depth=f_shape[-1],
- filter_size=f_shape[0:2],
- strides=strides[1:3],
- padding=padding,
- act=None,
- bias=None)
- x_value = np.random.normal(size=x_shape)
- x = tf.convert_to_tensor(x_value, dtype=tf.float32)
- y = conv(x)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- f_value = conv._kernel.eval()
- y_value = y.eval()
-
- y_expected = _NumpyConv2D(x_value, f_value,
- strides=strides, padding=padding)
- self.assertAllClose(y_expected, y_value)
-
- def testConv2DValid(self):
- np.random.seed(253647)
-
- x_shape = [4, 11, 12, 5]
- f_shape = [5, 2, 5, 5]
- strides = [1, 2, 2, 1]
- padding = 'VALID'
-
- conv = blocks_std.Conv2D(depth=f_shape[-1],
- filter_size=f_shape[0:2],
- strides=strides[1:3],
- padding=padding,
- act=None,
- bias=None)
- x_value = np.random.normal(size=x_shape)
- x = tf.convert_to_tensor(x_value, dtype=tf.float32)
- y = conv(x)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- f_value = conv._kernel.eval()
- y_value = y.eval()
-
- y_expected = _NumpyConv2D(x_value, f_value,
- strides=strides, padding=padding)
- self.assertAllClose(y_expected, y_value)
-
- def testConv2DSymmetric(self):
- np.random.seed(364758)
-
- x_shape = [4, 10, 12, 6]
- f_shape = [3, 4, 6, 5]
- strides = [1, 1, 1, 1]
- padding = 'SYMMETRIC'
-
- conv = blocks_std.Conv2D(depth=f_shape[-1],
- filter_size=f_shape[0:2],
- strides=strides[1:3],
- padding=padding,
- act=None,
- bias=None)
- x_value = np.random.normal(size=x_shape)
- x = tf.convert_to_tensor(x_value, dtype=tf.float32)
- y = conv(x)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- f_value = conv._kernel.eval()
- y_value = y.eval()
-
- y_expected = _NumpyConv2D(x_value, f_value,
- strides=strides, padding=padding)
- self.assertAllClose(y_expected, y_value)
-
- def testConv2DReflect(self):
- np.random.seed(768798)
-
- x_shape = [4, 10, 12, 6]
- f_shape = [3, 4, 6, 5]
- strides = [1, 2, 2, 1]
- padding = 'REFLECT'
-
- conv = blocks_std.Conv2D(depth=f_shape[-1],
- filter_size=f_shape[0:2],
- strides=strides[1:3],
- padding=padding,
- act=None,
- bias=None)
- x_value = np.random.normal(size=x_shape)
- x = tf.convert_to_tensor(x_value, dtype=tf.float32)
- y = conv(x)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- f_value = conv._kernel.eval()
- y_value = y.eval()
-
- y_expected = _NumpyConv2D(x_value, f_value,
- strides=strides, padding=padding)
- self.assertAllClose(y_expected, y_value)
-
- def testConv2DBias(self):
- input_shape = [19, 14, 14, 64]
- filter_shape = [3, 7, 64, 128]
- strides = [1, 2, 2, 1]
- output_shape = [19, 6, 4, 128]
-
- conv = blocks_std.Conv2D(depth=filter_shape[-1],
- filter_size=filter_shape[0:2],
- strides=strides[1:3],
- padding='VALID',
- act=None,
- bias=blocks_std.Bias(1))
- x = tf.placeholder(dtype=tf.float32, shape=input_shape)
-
- y = conv(x)
- self.CheckBiasAdd(y, conv._bias)
- self.assertEqual(output_shape, y.get_shape().as_list())
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/compression/entropy_coder/model/__init__.py b/research/compression/entropy_coder/model/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/compression/entropy_coder/model/entropy_coder_model.py b/research/compression/entropy_coder/model/entropy_coder_model.py
deleted file mode 100644
index 67f7eb5bc05f3df7363529c19fa77d176caaabc1..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/model/entropy_coder_model.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Entropy coder model."""
-
-
-class EntropyCoderModel(object):
- """Entropy coder model."""
-
- def __init__(self):
- # Loss used for training the model.
- self.loss = None
-
- # Tensorflow op to run to train the model.
- self.train_op = None
-
- # Tensor corresponding to the average code length of the input bit field
- # tensor. The average code length is a number of output bits per input bit.
- # To get an effective compression, this number should be between 0.0
- # and 1.0 (1.0 corresponds to no compression).
- self.average_code_length = None
-
- def Initialize(self, global_step, optimizer, config_string):
- raise NotImplementedError()
-
- def BuildGraph(self, input_codes):
- """Build the Tensorflow graph corresponding to the entropy coder model.
-
- Args:
- input_codes: Tensor of size: batch_size x height x width x bit_depth
- corresponding to the codes to compress.
- The input codes are {-1, +1} codes.
- """
- # TODO:
- # - consider switching to {0, 1} codes.
- # - consider passing an extra tensor which gives for each (b, y, x)
- # what is the actual depth (which would allow to use more or less bits
- # for each (y, x) location.
- raise NotImplementedError()
-
- def GetConfigStringForUnitTest(self):
- """Returns a default model configuration to be used for unit tests."""
- return None
diff --git a/research/compression/entropy_coder/model/model_factory.py b/research/compression/entropy_coder/model/model_factory.py
deleted file mode 100644
index e6f9902f3bb720e76f228f2774a9eaf7774ef191..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/model/model_factory.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Entropy coder model registrar."""
-
-
-class ModelFactory(object):
- """Factory of encoder/decoder models."""
-
- def __init__(self):
- self._model_dictionary = dict()
-
- def RegisterModel(self,
- entropy_coder_model_name,
- entropy_coder_model_factory):
- self._model_dictionary[entropy_coder_model_name] = (
- entropy_coder_model_factory)
-
- def CreateModel(self, model_name):
- current_model_factory = self._model_dictionary[model_name]
- return current_model_factory()
-
- def GetAvailableModels(self):
- return self._model_dictionary.keys()
-
-
-_model_registry = ModelFactory()
-
-
-def GetModelRegistry():
- return _model_registry
-
-
-class RegisterEntropyCoderModel(object):
-
- def __init__(self, model_name):
- self._model_name = model_name
-
- def __call__(self, f):
- _model_registry.RegisterModel(self._model_name, f)
- return f
diff --git a/research/compression/entropy_coder/progressive/__init__.py b/research/compression/entropy_coder/progressive/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/compression/entropy_coder/progressive/progressive.py b/research/compression/entropy_coder/progressive/progressive.py
deleted file mode 100644
index 7b03a07db055b62aa1c0f9cc89ddd2472899db3c..0000000000000000000000000000000000000000
--- a/research/compression/entropy_coder/progressive/progressive.py
+++ /dev/null
@@ -1,242 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Code probability model used for entropy coding."""
-
-import json
-
-from six.moves import xrange
-import tensorflow as tf
-
-from entropy_coder.lib import blocks
-from entropy_coder.model import entropy_coder_model
-from entropy_coder.model import model_factory
-
-# pylint: disable=not-callable
-
-
-class BrnnPredictor(blocks.BlockBase):
- """BRNN prediction applied on one layer."""
-
- def __init__(self, code_depth, name=None):
- super(BrnnPredictor, self).__init__(name)
-
- with self._BlockScope():
- hidden_depth = 2 * code_depth
-
- # What is coming from the previous layer/iteration
- # is going through a regular Conv2D layer as opposed to the binary codes
- # of the current layer/iteration which are going through a masked
- # convolution.
- self._adaptation0 = blocks.RasterScanConv2D(
- hidden_depth, [7, 7], [1, 1], 'SAME',
- strict_order=True,
- bias=blocks.Bias(0), act=tf.tanh)
- self._adaptation1 = blocks.Conv2D(
- hidden_depth, [3, 3], [1, 1], 'SAME',
- bias=blocks.Bias(0), act=tf.tanh)
- self._predictor = blocks.CompositionOperator([
- blocks.LineOperator(
- blocks.RasterScanConv2DLSTM(
- depth=hidden_depth,
- filter_size=[1, 3],
- hidden_filter_size=[1, 3],
- strides=[1, 1],
- padding='SAME')),
- blocks.Conv2D(hidden_depth, [1, 1], [1, 1], 'SAME',
- bias=blocks.Bias(0), act=tf.tanh),
- blocks.Conv2D(code_depth, [1, 1], [1, 1], 'SAME',
- bias=blocks.Bias(0), act=tf.tanh)
- ])
-
- def _Apply(self, x, s):
- # Code estimation using both:
- # - the state from the previous iteration/layer,
- # - the binary codes that are before in raster scan order.
- h = tf.concat(values=[self._adaptation0(x), self._adaptation1(s)], axis=3)
-
- estimated_codes = self._predictor(h)
-
- return estimated_codes
-
-
-class LayerPrediction(blocks.BlockBase):
- """Binary code prediction for one layer."""
-
- def __init__(self, layer_count, code_depth, name=None):
- super(LayerPrediction, self).__init__(name)
-
- self._layer_count = layer_count
-
- # No previous layer.
- self._layer_state = None
- self._current_layer = 0
-
- with self._BlockScope():
- # Layers used to do the conditional code prediction.
- self._brnn_predictors = []
- for _ in xrange(layer_count):
- self._brnn_predictors.append(BrnnPredictor(code_depth))
-
- # Layers used to generate the input of the LSTM operating on the
- # iteration/depth domain.
- hidden_depth = 2 * code_depth
- self._state_blocks = []
- for _ in xrange(layer_count):
- self._state_blocks.append(blocks.CompositionOperator([
- blocks.Conv2D(
- hidden_depth, [3, 3], [1, 1], 'SAME',
- bias=blocks.Bias(0), act=tf.tanh),
- blocks.Conv2D(
- code_depth, [3, 3], [1, 1], 'SAME',
- bias=blocks.Bias(0), act=tf.tanh)
- ]))
-
- # Memory of the RNN is equivalent to the size of 2 layers of binary
- # codes.
- hidden_depth = 2 * code_depth
- self._layer_rnn = blocks.CompositionOperator([
- blocks.Conv2DLSTM(
- depth=hidden_depth,
- filter_size=[1, 1],
- hidden_filter_size=[1, 1],
- strides=[1, 1],
- padding='SAME'),
- blocks.Conv2D(hidden_depth, [1, 1], [1, 1], 'SAME',
- bias=blocks.Bias(0), act=tf.tanh),
- blocks.Conv2D(code_depth, [1, 1], [1, 1], 'SAME',
- bias=blocks.Bias(0), act=tf.tanh)
- ])
-
- def _Apply(self, x):
- assert self._current_layer < self._layer_count
-
- # Layer state is set to 0 when there is no previous iteration.
- if self._layer_state is None:
- self._layer_state = tf.zeros_like(x, dtype=tf.float32)
-
- # Code estimation using both:
- # - the state from the previous iteration/layer,
- # - the binary codes that are before in raster scan order.
- estimated_codes = self._brnn_predictors[self._current_layer](
- x, self._layer_state)
-
- # Compute the updated layer state.
- h = self._state_blocks[self._current_layer](x)
- self._layer_state = self._layer_rnn(h)
- self._current_layer += 1
-
- return estimated_codes
-
-
-class ProgressiveModel(entropy_coder_model.EntropyCoderModel):
- """Progressive BRNN entropy coder model."""
-
- def __init__(self):
- super(ProgressiveModel, self).__init__()
-
- def Initialize(self, global_step, optimizer, config_string):
- if config_string is None:
- raise ValueError('The progressive model requires a configuration.')
- config = json.loads(config_string)
- if 'coded_layer_count' not in config:
- config['coded_layer_count'] = 0
-
- self._config = config
- self._optimizer = optimizer
- self._global_step = global_step
-
- def BuildGraph(self, input_codes):
- """Build the graph corresponding to the progressive BRNN model."""
- layer_depth = self._config['layer_depth']
- layer_count = self._config['layer_count']
-
- code_shape = input_codes.get_shape()
- code_depth = code_shape[-1].value
- if self._config['coded_layer_count'] > 0:
- prefix_depth = self._config['coded_layer_count'] * layer_depth
- if code_depth < prefix_depth:
- raise ValueError('Invalid prefix depth: {} VS {}'.format(
- prefix_depth, code_depth))
- input_codes = input_codes[:, :, :, :prefix_depth]
-
- code_shape = input_codes.get_shape()
- code_depth = code_shape[-1].value
- if code_depth % layer_depth != 0:
- raise ValueError(
- 'Code depth must be a multiple of the layer depth: {} vs {}'.format(
- code_depth, layer_depth))
- code_layer_count = code_depth // layer_depth
- if code_layer_count > layer_count:
- raise ValueError('Input codes have too many layers: {}, max={}'.format(
- code_layer_count, layer_count))
-
- # Block used to estimate binary codes.
- layer_prediction = LayerPrediction(layer_count, layer_depth)
-
- # Block used to compute code lengths.
- code_length_block = blocks.CodeLength()
-
- # Loop over all the layers.
- code_length = []
- code_layers = tf.split(
- value=input_codes, num_or_size_splits=code_layer_count, axis=3)
- for k in xrange(code_layer_count):
- x = code_layers[k]
- predicted_x = layer_prediction(x)
- # Saturate the prediction to avoid infinite code length.
- epsilon = 0.001
- predicted_x = tf.clip_by_value(
- predicted_x, -1 + epsilon, +1 - epsilon)
- code_length.append(code_length_block(
- blocks.ConvertSignCodeToZeroOneCode(x),
- blocks.ConvertSignCodeToZeroOneCode(predicted_x)))
- tf.summary.scalar('code_length_layer_{:02d}'.format(k), code_length[-1])
- code_length = tf.stack(code_length)
- self.loss = tf.reduce_mean(code_length)
- tf.summary.scalar('loss', self.loss)
-
- # Loop over all the remaining layers just to make sure they are
- # instantiated. Otherwise, loading model params could fail.
- dummy_x = tf.zeros_like(code_layers[0])
- for _ in xrange(layer_count - code_layer_count):
- dummy_predicted_x = layer_prediction(dummy_x)
-
- # Average bitrate over total_line_count.
- self.average_code_length = tf.reduce_mean(code_length)
-
- if self._optimizer:
- optim_op = self._optimizer.minimize(self.loss,
- global_step=self._global_step)
- block_updates = blocks.CreateBlockUpdates()
- if block_updates:
- with tf.get_default_graph().control_dependencies([optim_op]):
- self.train_op = tf.group(*block_updates)
- else:
- self.train_op = optim_op
- else:
- self.train_op = None
-
- def GetConfigStringForUnitTest(self):
- s = '{\n'
- s += '"layer_depth": 1,\n'
- s += '"layer_count": 8\n'
- s += '}\n'
- return s
-
-
-@model_factory.RegisterEntropyCoderModel('progressive')
-def CreateProgressiveModel():
- return ProgressiveModel()
diff --git a/research/compression/image_encoder/README.md b/research/compression/image_encoder/README.md
deleted file mode 100644
index a47da977aa4db4be26528c5ebfe030024f31291b..0000000000000000000000000000000000000000
--- a/research/compression/image_encoder/README.md
+++ /dev/null
@@ -1,105 +0,0 @@
-# Image Compression with Neural Networks
-
-This is a [TensorFlow](http://www.tensorflow.org/) model for compressing and
-decompressing images using an already trained Residual GRU model as descibed
-in [Full Resolution Image Compression with Recurrent Neural Networks](https://arxiv.org/abs/1608.05148). Please consult the paper for more details
-on the architecture and compression results.
-
-This code will allow you to perform the lossy compression on an model
-already trained on compression. This code doesn't not currently contain the
-Entropy Coding portions of our paper.
-
-
-## Prerequisites
-The only software requirements for running the encoder and decoder is having
-Tensorflow installed. You will also need to [download](http://download.tensorflow.org/models/compression_residual_gru-2016-08-23.tar.gz)
-and extract the model residual_gru.pb.
-
-If you want to generate the perceptual similarity under MS-SSIM, you will also
-need to [Install SciPy](https://www.scipy.org/install.html).
-
-## Encoding
-The Residual GRU network is fully convolutional, but requires the images
-height and width in pixels by a multiple of 32. There is an image in this folder
-called example.png that is 768x1024 if one is needed for testing. We also
-rely on TensorFlow's built in decoding ops, which support only PNG and JPEG at
-time of release.
-
-To encode an image, simply run the following command:
-
-`python encoder.py --input_image=/your/image/here.png
---output_codes=output_codes.npz --iteration=15
---model=/path/to/model/residual_gru.pb
-`
-
-The iteration parameter specifies the lossy-quality to target for compression.
-The quality can be [0-15], where 0 corresponds to a target of 1/8 (bits per
-pixel) bpp and every increment results in an additional 1/8 bpp.
-
-| Iteration | BPP | Compression Ratio |
-|---: |---: |---: |
-|0 | 0.125 | 192:1|
-|1 | 0.250 | 96:1|
-|2 | 0.375 | 64:1|
-|3 | 0.500 | 48:1|
-|4 | 0.625 | 38.4:1|
-|5 | 0.750 | 32:1|
-|6 | 0.875 | 27.4:1|
-|7 | 1.000 | 24:1|
-|8 | 1.125 | 21.3:1|
-|9 | 1.250 | 19.2:1|
-|10 | 1.375 | 17.4:1|
-|11 | 1.500 | 16:1|
-|12 | 1.625 | 14.7:1|
-|13 | 1.750 | 13.7:1|
-|14 | 1.875 | 12.8:1|
-|15 | 2.000 | 12:1|
-
-The output_codes file contains the numpy shape and a flattened, bit-packed
-array of the codes. These can be inspected in python by using numpy.load().
-
-
-## Decoding
-After generating codes for an image, the lossy reconstructions for that image
-can be done as follows:
-
-`python decoder.py --input_codes=codes.npz --output_directory=/tmp/decoded/
---model=residual_gru.pb`
-
-The output_directory will contain images decoded at each quality level.
-
-
-## Comparing Similarity
-One of our primary metrics for comparing how similar two images are
-is MS-SSIM.
-
-To generate these metrics on your images you can run:
-`python msssim.py --original_image=/path/to/your/image.png
---compared_image=/tmp/decoded/image_15.png`
-
-
-## Results
-CSV results containing the post-entropy bitrates and MS-SSIM over Kodak can
-are available for reference. Each row of the CSV represents each of the Kodak
-images in their dataset number (1-24). Each column of the CSV represents each
-iteration of the model (1-16).
-
-[Post Entropy Bitrates](https://storage.googleapis.com/compression-ml/residual_gru_results/bitrate.csv)
-
-[MS-SSIM](https://storage.googleapis.com/compression-ml/residual_gru_results/msssim.csv)
-
-
-## FAQ
-
-#### How do I train my own compression network?
-We currently don't provide the code to build and train a compression
-graph from scratch.
-
-#### I get an InvalidArgumentError: Incompatible shapes.
-This is usually due to the fact that our network only supports images that are
-both height and width divisible by 32 pixel. Try padding your images to 32
-pixel boundaries.
-
-
-## Contact Info
-Model repository maintained by Nick Johnston ([nmjohn](https://github.com/nmjohn)).
diff --git a/research/compression/image_encoder/decoder.py b/research/compression/image_encoder/decoder.py
deleted file mode 100644
index 75bc18cad0fdd4055df7b42d5440635365504774..0000000000000000000000000000000000000000
--- a/research/compression/image_encoder/decoder.py
+++ /dev/null
@@ -1,127 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-r"""Neural Network Image Compression Decoder.
-
-Decompress an image from the numpy's npz format generated by the encoder.
-
-Example usage:
-python decoder.py --input_codes=output_codes.pkl --iteration=15 \
---output_directory=/tmp/compression_output/ --model=residual_gru.pb
-"""
-import io
-import os
-
-import numpy as np
-import tensorflow as tf
-
-tf.flags.DEFINE_string('input_codes', None, 'Location of binary code file.')
-tf.flags.DEFINE_integer('iteration', -1, 'The max quality level of '
- 'the images to output. Use -1 to infer from loaded '
- ' codes.')
-tf.flags.DEFINE_string('output_directory', None, 'Directory to save decoded '
- 'images.')
-tf.flags.DEFINE_string('model', None, 'Location of compression model.')
-
-FLAGS = tf.flags.FLAGS
-
-
-def get_input_tensor_names():
- name_list = ['GruBinarizer/SignBinarizer/Sign:0']
- for i in range(1, 16):
- name_list.append('GruBinarizer/SignBinarizer/Sign_{}:0'.format(i))
- return name_list
-
-
-def get_output_tensor_names():
- return ['loop_{0:02d}/add:0'.format(i) for i in range(0, 16)]
-
-
-def main(_):
- if (FLAGS.input_codes is None or FLAGS.output_directory is None or
- FLAGS.model is None):
- print('\nUsage: python decoder.py --input_codes=output_codes.pkl '
- '--iteration=15 --output_directory=/tmp/compression_output/ '
- '--model=residual_gru.pb\n\n')
- return
-
- if FLAGS.iteration < -1 or FLAGS.iteration > 15:
- print('\n--iteration must be between 0 and 15 inclusive, or -1 to infer '
- 'from file.\n')
- return
- iteration = FLAGS.iteration
-
- if not tf.gfile.Exists(FLAGS.output_directory):
- tf.gfile.MkDir(FLAGS.output_directory)
-
- if not tf.gfile.Exists(FLAGS.input_codes):
- print('\nInput codes not found.\n')
- return
-
- contents = ''
- with tf.gfile.FastGFile(FLAGS.input_codes, 'rb') as code_file:
- contents = code_file.read()
- loaded_codes = np.load(io.BytesIO(contents))
- assert ['codes', 'shape'] not in loaded_codes.files
- loaded_shape = loaded_codes['shape']
- loaded_array = loaded_codes['codes']
-
- # Unpack and recover code shapes.
- unpacked_codes = np.reshape(np.unpackbits(loaded_array)
- [:np.prod(loaded_shape)],
- loaded_shape)
-
- numpy_int_codes = np.split(unpacked_codes, len(unpacked_codes))
- if iteration == -1:
- iteration = len(unpacked_codes) - 1
- # Convert back to float and recover scale.
- numpy_codes = [np.squeeze(x.astype(np.float32), 0) * 2 - 1 for x in
- numpy_int_codes]
-
- with tf.Graph().as_default() as graph:
- # Load the inference model for decoding.
- with tf.gfile.FastGFile(FLAGS.model, 'rb') as model_file:
- graph_def = tf.GraphDef()
- graph_def.ParseFromString(model_file.read())
- _ = tf.import_graph_def(graph_def, name='')
-
- # For encoding the tensors into PNGs.
- input_image = tf.placeholder(tf.uint8)
- encoded_image = tf.image.encode_png(input_image)
-
- input_tensors = [graph.get_tensor_by_name(name) for name in
- get_input_tensor_names()][0:iteration+1]
- outputs = [graph.get_tensor_by_name(name) for name in
- get_output_tensor_names()][0:iteration+1]
-
- feed_dict = {key: value for (key, value) in zip(input_tensors,
- numpy_codes)}
-
- with tf.Session(graph=graph) as sess:
- results = sess.run(outputs, feed_dict=feed_dict)
-
- for index, result in enumerate(results):
- img = np.uint8(np.clip(result + 0.5, 0, 255))
- img = img.squeeze()
- png_img = sess.run(encoded_image, feed_dict={input_image: img})
-
- with tf.gfile.FastGFile(os.path.join(FLAGS.output_directory,
- 'image_{0:02d}.png'.format(index)),
- 'w') as output_image:
- output_image.write(png_img)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/compression/image_encoder/encoder.py b/research/compression/image_encoder/encoder.py
deleted file mode 100644
index 27754bdaea19779cea653408d17ed2e6a051f0c5..0000000000000000000000000000000000000000
--- a/research/compression/image_encoder/encoder.py
+++ /dev/null
@@ -1,105 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-r"""Neural Network Image Compression Encoder.
-
-Compresses an image to a binarized numpy array. The image must be padded to a
-multiple of 32 pixels in height and width.
-
-Example usage:
-python encoder.py --input_image=/your/image/here.png \
---output_codes=output_codes.pkl --iteration=15 --model=residual_gru.pb
-"""
-import io
-import os
-
-import numpy as np
-import tensorflow as tf
-
-tf.flags.DEFINE_string('input_image', None, 'Location of input image. We rely '
- 'on tf.image to decode the image, so only PNG and JPEG '
- 'formats are currently supported.')
-tf.flags.DEFINE_integer('iteration', 15, 'Quality level for encoding image. '
- 'Must be between 0 and 15 inclusive.')
-tf.flags.DEFINE_string('output_codes', None, 'File to save output encoding.')
-tf.flags.DEFINE_string('model', None, 'Location of compression model.')
-
-FLAGS = tf.flags.FLAGS
-
-
-def get_output_tensor_names():
- name_list = ['GruBinarizer/SignBinarizer/Sign:0']
- for i in range(1, 16):
- name_list.append('GruBinarizer/SignBinarizer/Sign_{}:0'.format(i))
- return name_list
-
-
-def main(_):
- if (FLAGS.input_image is None or FLAGS.output_codes is None or
- FLAGS.model is None):
- print('\nUsage: python encoder.py --input_image=/your/image/here.png '
- '--output_codes=output_codes.pkl --iteration=15 '
- '--model=residual_gru.pb\n\n')
- return
-
- if FLAGS.iteration < 0 or FLAGS.iteration > 15:
- print('\n--iteration must be between 0 and 15 inclusive.\n')
- return
-
- with tf.gfile.FastGFile(FLAGS.input_image, 'rb') as input_image:
- input_image_str = input_image.read()
-
- with tf.Graph().as_default() as graph:
- # Load the inference model for encoding.
- with tf.gfile.FastGFile(FLAGS.model, 'rb') as model_file:
- graph_def = tf.GraphDef()
- graph_def.ParseFromString(model_file.read())
- _ = tf.import_graph_def(graph_def, name='')
-
- input_tensor = graph.get_tensor_by_name('Placeholder:0')
- outputs = [graph.get_tensor_by_name(name) for name in
- get_output_tensor_names()]
-
- input_image = tf.placeholder(tf.string)
- _, ext = os.path.splitext(FLAGS.input_image)
- if ext == '.png':
- decoded_image = tf.image.decode_png(input_image, channels=3)
- elif ext == '.jpeg' or ext == '.jpg':
- decoded_image = tf.image.decode_jpeg(input_image, channels=3)
- else:
- assert False, 'Unsupported file format {}'.format(ext)
- decoded_image = tf.expand_dims(decoded_image, 0)
-
- with tf.Session(graph=graph) as sess:
- img_array = sess.run(decoded_image, feed_dict={input_image:
- input_image_str})
- results = sess.run(outputs, feed_dict={input_tensor: img_array})
-
- results = results[0:FLAGS.iteration + 1]
- int_codes = np.asarray([x.astype(np.int8) for x in results])
-
- # Convert int codes to binary.
- int_codes = (int_codes + 1)//2
- export = np.packbits(int_codes.reshape(-1))
-
- output = io.BytesIO()
- np.savez_compressed(output, shape=int_codes.shape, codes=export)
- with tf.gfile.FastGFile(FLAGS.output_codes, 'w') as code_file:
- code_file.write(output.getvalue())
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/compression/image_encoder/example.png b/research/compression/image_encoder/example.png
deleted file mode 100644
index d3409b01a557fe8c3058fad21ed969f8af28cb97..0000000000000000000000000000000000000000
Binary files a/research/compression/image_encoder/example.png and /dev/null differ
diff --git a/research/compression/image_encoder/msssim.py b/research/compression/image_encoder/msssim.py
deleted file mode 100644
index f07a3712785c62feb261feb90016e0f621a3ee1d..0000000000000000000000000000000000000000
--- a/research/compression/image_encoder/msssim.py
+++ /dev/null
@@ -1,217 +0,0 @@
-#!/usr/bin/python
-#
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Python implementation of MS-SSIM.
-
-Usage:
-
-python msssim.py --original_image=original.png --compared_image=distorted.png
-"""
-import numpy as np
-from scipy import signal
-from scipy.ndimage.filters import convolve
-import tensorflow as tf
-
-
-tf.flags.DEFINE_string('original_image', None, 'Path to PNG image.')
-tf.flags.DEFINE_string('compared_image', None, 'Path to PNG image.')
-FLAGS = tf.flags.FLAGS
-
-
-def _FSpecialGauss(size, sigma):
- """Function to mimic the 'fspecial' gaussian MATLAB function."""
- radius = size // 2
- offset = 0.0
- start, stop = -radius, radius + 1
- if size % 2 == 0:
- offset = 0.5
- stop -= 1
- x, y = np.mgrid[offset + start:stop, offset + start:stop]
- assert len(x) == size
- g = np.exp(-((x**2 + y**2)/(2.0 * sigma**2)))
- return g / g.sum()
-
-
-def _SSIMForMultiScale(img1, img2, max_val=255, filter_size=11,
- filter_sigma=1.5, k1=0.01, k2=0.03):
- """Return the Structural Similarity Map between `img1` and `img2`.
-
- This function attempts to match the functionality of ssim_index_new.m by
- Zhou Wang: http://www.cns.nyu.edu/~lcv/ssim/msssim.zip
-
- Arguments:
- img1: Numpy array holding the first RGB image batch.
- img2: Numpy array holding the second RGB image batch.
- max_val: the dynamic range of the images (i.e., the difference between the
- maximum the and minimum allowed values).
- filter_size: Size of blur kernel to use (will be reduced for small images).
- filter_sigma: Standard deviation for Gaussian blur kernel (will be reduced
- for small images).
- k1: Constant used to maintain stability in the SSIM calculation (0.01 in
- the original paper).
- k2: Constant used to maintain stability in the SSIM calculation (0.03 in
- the original paper).
-
- Returns:
- Pair containing the mean SSIM and contrast sensitivity between `img1` and
- `img2`.
-
- Raises:
- RuntimeError: If input images don't have the same shape or don't have four
- dimensions: [batch_size, height, width, depth].
- """
- if img1.shape != img2.shape:
- raise RuntimeError('Input images must have the same shape (%s vs. %s).',
- img1.shape, img2.shape)
- if img1.ndim != 4:
- raise RuntimeError('Input images must have four dimensions, not %d',
- img1.ndim)
-
- img1 = img1.astype(np.float64)
- img2 = img2.astype(np.float64)
- _, height, width, _ = img1.shape
-
- # Filter size can't be larger than height or width of images.
- size = min(filter_size, height, width)
-
- # Scale down sigma if a smaller filter size is used.
- sigma = size * filter_sigma / filter_size if filter_size else 0
-
- if filter_size:
- window = np.reshape(_FSpecialGauss(size, sigma), (1, size, size, 1))
- mu1 = signal.fftconvolve(img1, window, mode='valid')
- mu2 = signal.fftconvolve(img2, window, mode='valid')
- sigma11 = signal.fftconvolve(img1 * img1, window, mode='valid')
- sigma22 = signal.fftconvolve(img2 * img2, window, mode='valid')
- sigma12 = signal.fftconvolve(img1 * img2, window, mode='valid')
- else:
- # Empty blur kernel so no need to convolve.
- mu1, mu2 = img1, img2
- sigma11 = img1 * img1
- sigma22 = img2 * img2
- sigma12 = img1 * img2
-
- mu11 = mu1 * mu1
- mu22 = mu2 * mu2
- mu12 = mu1 * mu2
- sigma11 -= mu11
- sigma22 -= mu22
- sigma12 -= mu12
-
- # Calculate intermediate values used by both ssim and cs_map.
- c1 = (k1 * max_val) ** 2
- c2 = (k2 * max_val) ** 2
- v1 = 2.0 * sigma12 + c2
- v2 = sigma11 + sigma22 + c2
- ssim = np.mean((((2.0 * mu12 + c1) * v1) / ((mu11 + mu22 + c1) * v2)))
- cs = np.mean(v1 / v2)
- return ssim, cs
-
-
-def MultiScaleSSIM(img1, img2, max_val=255, filter_size=11, filter_sigma=1.5,
- k1=0.01, k2=0.03, weights=None):
- """Return the MS-SSIM score between `img1` and `img2`.
-
- This function implements Multi-Scale Structural Similarity (MS-SSIM) Image
- Quality Assessment according to Zhou Wang's paper, "Multi-scale structural
- similarity for image quality assessment" (2003).
- Link: https://ece.uwaterloo.ca/~z70wang/publications/msssim.pdf
-
- Author's MATLAB implementation:
- http://www.cns.nyu.edu/~lcv/ssim/msssim.zip
-
- Arguments:
- img1: Numpy array holding the first RGB image batch.
- img2: Numpy array holding the second RGB image batch.
- max_val: the dynamic range of the images (i.e., the difference between the
- maximum the and minimum allowed values).
- filter_size: Size of blur kernel to use (will be reduced for small images).
- filter_sigma: Standard deviation for Gaussian blur kernel (will be reduced
- for small images).
- k1: Constant used to maintain stability in the SSIM calculation (0.01 in
- the original paper).
- k2: Constant used to maintain stability in the SSIM calculation (0.03 in
- the original paper).
- weights: List of weights for each level; if none, use five levels and the
- weights from the original paper.
-
- Returns:
- MS-SSIM score between `img1` and `img2`.
-
- Raises:
- RuntimeError: If input images don't have the same shape or don't have four
- dimensions: [batch_size, height, width, depth].
- """
- if img1.shape != img2.shape:
- raise RuntimeError('Input images must have the same shape (%s vs. %s).',
- img1.shape, img2.shape)
- if img1.ndim != 4:
- raise RuntimeError('Input images must have four dimensions, not %d',
- img1.ndim)
-
- # Note: default weights don't sum to 1.0 but do match the paper / matlab code.
- weights = np.array(weights if weights else
- [0.0448, 0.2856, 0.3001, 0.2363, 0.1333])
- levels = weights.size
- downsample_filter = np.ones((1, 2, 2, 1)) / 4.0
- im1, im2 = [x.astype(np.float64) for x in [img1, img2]]
- mssim = np.array([])
- mcs = np.array([])
- for _ in range(levels):
- ssim, cs = _SSIMForMultiScale(
- im1, im2, max_val=max_val, filter_size=filter_size,
- filter_sigma=filter_sigma, k1=k1, k2=k2)
- mssim = np.append(mssim, ssim)
- mcs = np.append(mcs, cs)
- filtered = [convolve(im, downsample_filter, mode='reflect')
- for im in [im1, im2]]
- im1, im2 = [x[:, ::2, ::2, :] for x in filtered]
- return (np.prod(mcs[0:levels-1] ** weights[0:levels-1]) *
- (mssim[levels-1] ** weights[levels-1]))
-
-
-def main(_):
- if FLAGS.original_image is None or FLAGS.compared_image is None:
- print('\nUsage: python msssim.py --original_image=original.png '
- '--compared_image=distorted.png\n\n')
- return
-
- if not tf.gfile.Exists(FLAGS.original_image):
- print('\nCannot find --original_image.\n')
- return
-
- if not tf.gfile.Exists(FLAGS.compared_image):
- print('\nCannot find --compared_image.\n')
- return
-
- with tf.gfile.FastGFile(FLAGS.original_image) as image_file:
- img1_str = image_file.read('rb')
- with tf.gfile.FastGFile(FLAGS.compared_image) as image_file:
- img2_str = image_file.read('rb')
-
- input_img = tf.placeholder(tf.string)
- decoded_image = tf.expand_dims(tf.image.decode_png(input_img, channels=3), 0)
-
- with tf.Session() as sess:
- img1 = sess.run(decoded_image, feed_dict={input_img: img1_str})
- img2 = sess.run(decoded_image, feed_dict={input_img: img2_str})
-
- print((MultiScaleSSIM(img1, img2, max_val=255)))
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/deep_contextual_bandits/README.md b/research/deep_contextual_bandits/README.md
deleted file mode 100644
index b81309af5b08003eb727e079e70c3dd08eedb6f6..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/README.md
+++ /dev/null
@@ -1,444 +0,0 @@
-
-
-
-
-# Deep Bayesian Bandits Library
-
-This library corresponds to the *[Deep Bayesian Bandits Showdown: An Empirical
-Comparison of Bayesian Deep Networks for Thompson
-Sampling](https://arxiv.org/abs/1802.09127)* paper, published in
-[ICLR](https://iclr.cc/) 2018. We provide a benchmark to test decision-making
-algorithms for contextual-bandits. In particular, the current library implements
-a variety of algorithms (many of them based on approximate Bayesian Neural
-Networks and Thompson sampling), and a number of real and syntethic data
-problems exhibiting a diverse set of properties.
-
-It is a Python library that uses [TensorFlow](https://www.tensorflow.org/).
-
-We encourage contributors to add new approximate Bayesian Neural Networks or,
-more generally, contextual bandits algorithms to the library. Also, we would
-like to extend the data sources over time, so we warmly encourage contributions
-in this front too!
-
-Please, use the following when citing the code or the paper:
-
-```
-@article{riquelme2018deep, title={Deep Bayesian Bandits Showdown: An Empirical
-Comparison of Bayesian Deep Networks for Thompson Sampling},
-author={Riquelme, Carlos and Tucker, George and Snoek, Jasper},
-journal={International Conference on Learning Representations, ICLR.}, year={2018}}
-```
-
-**Contact**. This repository is maintained by [Carlos Riquelme](http://rikel.me) ([rikel](https://github.com/rikel)). Feel free to reach out directly at [rikel@google.com](mailto:rikel@google.com) with any questions or comments.
-
-
-We first briefly introduce contextual bandits, Thompson sampling, enumerate the
-implemented algorithms, and the available data sources. Then, we provide a
-simple complete example illustrating how to use the library.
-
-## Contextual Bandits
-
-Contextual bandits are a rich decision-making framework where an algorithm has
-to choose among a set of *k* actions at every time step *t*, after observing
-a context (or side-information) denoted by *Xt*. The general pseudocode for
-the process if we use algorithm **A** is as follows:
-
-```
-At time t = 1, ..., T:
- 1. Observe new context: X_t
- 2. Choose action: a_t = A.action(X_t)
- 3. Observe reward: r_t
- 4. Update internal state of the algorithm: A.update((X_t, a_t, r_t))
-```
-
-The goal is to maximize the total sum of rewards: ∑t rt
-
-For example, each *Xt* could encode the properties of a specific user (and
-the time or day), and we may have to choose an ad, discount coupon, treatment,
-hyper-parameters, or version of a website to show or provide to the user.
-Hopefully, over time, we will learn how to match each type of user to the most
-beneficial personalized action under some metric (the reward).
-
-## Thompson Sampling
-
-Thompson Sampling is a meta-algorithm that chooses an action for the contextual
-bandit in a statistically efficient manner, simultaneously finding the best arm
-while attempting to incur low cost. Informally speaking, we assume the expected
-reward is given by some function
-**E**[rt | Xt, at] = f(Xt, at).
-Unfortunately, function **f** is unknown, as otherwise we could just choose the
-action with highest expected value:
-at* = arg maxi f(Xt, at).
-
-The idea behind Thompson Sampling is based on keeping a posterior distribution
-πt over functions in some family f ∈ F after observing the first
-*t-1* datapoints. Then, at time *t*, we sample one potential explanation of
-the underlying process: ft ∼ πt, and act optimally (i.e., greedily)
-*according to ft*. In other words, we choose
-at = arg maxi ft(Xt, ai).
-Finally, we update our posterior distribution with the new collected
-datapoint (Xt, at, rt).
-
-The main issue is that keeping an updated posterior πt (or, even,
-sampling from it) is often intractable for highly parameterized models like deep
-neural networks. The algorithms we list in the next section provide tractable
-*approximations* that can be used in combination with Thompson Sampling to solve
-the contextual bandit problem.
-
-## Algorithms
-
-The Deep Bayesian Bandits library includes the following algorithms (see the
-[paper](https://arxiv.org/abs/1802.09127) for further details):
-
-1. **Linear Algorithms**. As a powerful baseline, we provide linear algorithms.
- In particular, we focus on the exact Bayesian linear regression
- implementation, while it is easy to derive the greedy OLS version (possibly,
- with epsilon-greedy exploration). The algorithm is implemented in
- *linear_full_posterior_sampling.py*, and it is instantiated as follows:
-
- ```
- linear_full = LinearFullPosteriorSampling('MyLinearTS', my_hparams)
- ```
-
-2. **Neural Linear**. We introduce an algorithm we call Neural Linear, which
- operates by learning a neural network to map contexts to rewards for each
- action, and ---simultaneously--- it updates a Bayesian linear regression in
- the last layer (i.e., the one that maps the final representation **z** to
- the rewards **r**). Thompson Sampling samples the linear parameters
- βi for each action *i*, but keeps the network that computes the
- representation. Then, both parts (network and Bayesian linear regression)
- are updated, possibly at different frequencies. The algorithm is implemented
- in *neural_linear_sampling.py*, and we create an algorithm instance like
- this:
-
- ```
- neural_linear = NeuralLinearPosteriorSampling('MyNLinear', my_hparams)
- ```
-
-3. **Neural Greedy**. Another standard benchmark is to train a neural network
- that maps contexts to rewards, and at each time *t* just acts greedily
- according to the current model. In particular, this approach does *not*
- explicitly use Thompson Sampling. However, due to stochastic gradient
- descent, there is still some randomness in its output. It is
- straight-forward to add epsilon-greedy exploration to choose random
- actions with probability ε ∈ (0, 1). The algorithm is
- implemented in *neural_bandit_model.py*, and it is used together with
- *PosteriorBNNSampling* (defined in *posterior_bnn_sampling.py*) by calling:
-
- ```
- neural_greedy = PosteriorBNNSampling('MyNGreedy', my_hparams, 'RMSProp')
- ```
-
-4. **Stochastic Variational Inference**, Bayes by Backpropagation. We implement
- a Bayesian neural network by modeling each individual weight posterior as a
- univariate Gaussian distribution: wij ∼ N(μij, σij2).
- Thompson sampling then samples a network at each time step
- by sampling each weight independently. The variational approach consists in
- maximizing a proxy for maximum likelihood of the observed data, the ELBO or
- variational lower bound, to fit the values of μij, σij2
- for every *i, j*.
-
- See [Weight Uncertainty in Neural
- Networks](https://arxiv.org/abs/1505.05424).
-
- The BNN algorithm is implemented in *variational_neural_bandit_model.py*,
- and it is used together with *PosteriorBNNSampling* (defined in
- *posterior_bnn_sampling.py*) by calling:
-
- ```
- bbb = PosteriorBNNSampling('myBBB', my_hparams, 'Variational')
- ```
-
-5. **Expectation-Propagation**, Black-box alpha-divergence minimization.
- The family of expectation-propagation algorithms is based on the message
- passing framework . They iteratively approximate the posterior by updating a
- single approximation factor (or site) at a time, which usually corresponds
- to the likelihood of one data point. We focus on methods that directly
- optimize the global EP objective via stochastic gradient descent, as, for
- instance, Power EP. For further details see original paper below.
-
- See [Black-box alpha-divergence
- Minimization](https://arxiv.org/abs/1511.03243).
-
- We create an instance of the algorithm like this:
-
- ```
- bb_adiv = PosteriorBNNSampling('MyEP', my_hparams, 'AlphaDiv')
- ```
-
-6. **Dropout**. Dropout is a training technique where the output of each neuron
- is independently zeroed out with probability *p* at each forward pass.
- Once the network has been trained, dropout can still be used to obtain a
- distribution of predictions for a specific input. Following the best action
- with respect to the random dropout prediction can be interpreted as an
- implicit form of Thompson sampling. The code for dropout is the same as for
- Neural Greedy (see above), but we need to set two hyper-parameters:
- *use_dropout=True* and *keep_prob=p* where *p* takes the desired value in
- (0, 1). Then:
-
- ```
- dropout = PosteriorBNNSampling('MyDropout', my_hparams, 'RMSProp')
- ```
-
-7. **Monte Carlo Methods**. To be added soon.
-
-8. **Bootstrapped Networks**. This algorithm trains simultaneously and in
- parallel **q** neural networks based on different datasets D1, ..., Dq. The way those datasets are collected is by adding each new collected
- datapoint (Xt, at, rt) to each dataset *Di* independently and with
- probability p ∈ (0, 1]. Therefore, the main hyperparameters of the
- algorithm are **(q, p)**. In order to choose an action for a new context,
- one of the **q** networks is first selected with uniform probability (i.e.,
- *1/q*). Then, the best action according to the *selected* network is
- played.
-
- See [Deep Exploration via Bootstrapped
- DQN](https://arxiv.org/abs/1602.04621).
-
- The algorithm is implemented in *bootstrapped_bnn_sampling.py*, and we
- instantiate it as (where *my_hparams* contains both **q** and **p**):
-
- ```
- bootstrap = BootstrappedBNNSampling('MyBoot', my_hparams)
- ```
-
-9. **Parameter-Noise**. Another approach to approximate a distribution over
- neural networks (or more generally, models) that map contexts to rewards,
- consists in randomly perturbing a point estimate trained by Stochastic
- Gradient Descent on the data. The Parameter-Noise algorithm uses a heuristic
- to control the amount of noise σt2 it adds independently to the
- parameters representing a neural network: θt' = θt + ε where
- ε ∼ N(0, σt2 Id).
- After using θt' for decision making, the following SGD
- training steps start again from θt. The key hyperparameters to set
- are those controlling the noise heuristic.
-
- See [Parameter Space Noise for
- Exploration](https://arxiv.org/abs/1706.01905).
-
- The algorithm is implemented in *parameter_noise_sampling.py*, and we create
- an instance by calling:
-
- ```
- parameter_noise = ParameterNoiseSampling('MyParamNoise', my_hparams)
- ```
-
-10. **Gaussian Processes**. Another standard benchmark are Gaussian Processes,
- see *Gaussian Processes for Machine Learning* by Rasmussen and Williams for
- an introduction. To model the expected reward of different actions, we fit a
- multitask GP.
-
- See [Multi-task Gaussian Process
- Prediction](http://papers.nips.cc/paper/3189-multi-task-gaussian-process-prediction.pdf).
-
- Our implementation is provided in *multitask_gp.py*, and it is instantiated
- as follows:
-
- ```
- gp = PosteriorBNNSampling('MyMultitaskGP', my_hparams, 'GP')
- ```
-
-In the code snippet at the bottom, we show how to instantiate some of these
-algorithms, and how to run the contextual bandit simulator, and display the
-high-level results.
-
-## Data
-
-In the paper we use two types of contextual datasets: synthetic and based on
-real-world data.
-
-We provide functions that sample problems from those datasets. In the case of
-real-world data, you first need to download the raw datasets, and pass the route
-to the functions. Links for the datasets are provided below.
-
-### Synthetic Datasets
-
-Synthetic datasets are contained in the *synthetic_data_sampler.py* file. In
-particular, it includes:
-
-1. **Linear data**. Provides a number of linear arms, and Gaussian contexts.
-
-2. **Sparse linear data**. Provides a number of sparse linear arms, and
- Gaussian contexts.
-
-3. **Wheel bandit data**. Provides sampled data from the wheel bandit data, see
- [Section 5.4](https://arxiv.org/abs/1802.09127) in the paper.
-
-### Real-World Datasets
-
-Real-world data generating functions are contained in the *data_sampler.py*
-file.
-
-In particular, it includes:
-
-1. **Mushroom data**. Each incoming context represents a different type of
- mushroom, and the actions are eat or no-eat. Eating an edible mushroom
- provides positive reward, while eating a poisonous one provides positive
- reward with probability *p*, and a large negative reward with probability
- *1-p*. All the rewards, and the value of *p* are customizable. The
- [dataset](https://archive.ics.uci.edu/ml/datasets/mushroom) is part of the
- UCI repository, and the bandit problem was proposed in Blundell et al.
- (2015). Data is available [here](https://storage.googleapis.com/bandits_datasets/mushroom.data)
- or alternatively [here](https://archive.ics.uci.edu/ml/machine-learning-databases/mushroom/),
- use the *agaricus-lepiota.data* file.
-
-2. **Stock data**. We created the Financial Dataset by pulling the stock prices
- of *d = 21* publicly traded companies in NYSE and Nasdaq, for the last 14
- years (*n = 3713*). For each day, the context was the price difference
- between the beginning and end of the session for each stock. We
- synthetically created the arms to be a linear combination of the contexts,
- representing *k = 8* different potential portfolios. Data is available
- [here](https://storage.googleapis.com/bandits_datasets/raw_stock_contexts).
-
-3. **Jester data**. We create a recommendation system bandit problem as
- follows. The Jester Dataset (Goldberg et al., 2001) provides continuous
- ratings in *[-10, 10]* for 100 jokes from a total of 73421 users. We find
- a *complete* subset of *n = 19181* users rating all 40 jokes. Following
- Riquelme et al. (2017), we take *d = 32* of the ratings as the context of
- the user, and *k = 8* as the arms. The agent recommends one joke, and
- obtains the reward corresponding to the rating of the user for the selected
- joke. Data is available [here](https://storage.googleapis.com/bandits_datasets/jester_data_40jokes_19181users.npy).
-
-4. **Statlog data**. The Shuttle Statlog Dataset (Asuncion & Newman, 2007)
- provides the value of *d = 9* indicators during a space shuttle flight,
- and the goal is to predict the state of the radiator subsystem of the
- shuttle. There are *k = 7* possible states, and if the agent selects the
- right state, then reward 1 is generated. Otherwise, the agent obtains no
- reward (*r = 0*). The most interesting aspect of the dataset is that one
- action is the optimal one in 80% of the cases, and some algorithms may
- commit to this action instead of further exploring. In this case, the number
- of contexts is *n = 43500*. Data is available [here](https://storage.googleapis.com/bandits_datasets/shuttle.trn) or alternatively
- [here](https://archive.ics.uci.edu/ml/datasets/Statlog+\(Shuttle\)), use
- *shuttle.trn* file.
-
-5. **Adult data**. The Adult Dataset (Kohavi, 1996; Asuncion & Newman, 2007)
- comprises personal information from the US Census Bureau database, and the
- standard prediction task is to determine if a person makes over 50K a year
- or not. However, we consider the *k = 14* different occupations as
- feasible actions, based on *d = 94* covariates (many of them binarized).
- As in previous datasets, the agent obtains a reward of 1 for making the
- right prediction, and 0 otherwise. The total number of contexts is *n =
- 45222*. Data is available [here](https://storage.googleapis.com/bandits_datasets/adult.full) or alternatively
- [here](https://archive.ics.uci.edu/ml/datasets/adult), use *adult.data*
- file.
-
-6. **Census data**. The US Census (1990) Dataset (Asuncion & Newman, 2007)
- contains a number of personal features (age, native language, education...)
- which we summarize in *d = 389* covariates, including binary dummy
- variables for categorical features. Our goal again is to predict the
- occupation of the individual among *k = 9* classes. The agent obtains
- reward 1 for making the right prediction, and 0 otherwise. Data is available
- [here](https://storage.googleapis.com/bandits_datasets/USCensus1990.data.txt) or alternatively [here](https://archive.ics.uci.edu/ml/datasets/US+Census+Data+\(1990\)), use
- *USCensus1990.data.txt* file.
-
-7. **Covertype data**. The Covertype Dataset (Asuncion & Newman, 2007)
- classifies the cover type of northern Colorado forest areas in *k = 7*
- classes, based on *d = 54* features, including elevation, slope, aspect,
- and soil type. Again, the agent obtains reward 1 if the correct class is
- selected, and 0 otherwise. Data is available [here](https://storage.googleapis.com/bandits_datasets/covtype.data) or alternatively
- [here](https://archive.ics.uci.edu/ml/datasets/covertype), use
- *covtype.data* file.
-
-In datasets 4-7, each feature of the dataset is normalized first.
-
-## Usage: Basic Example
-
-This library requires Tensorflow, Numpy, and Pandas.
-
-The file *example_main.py* provides a complete example on how to use the
-library. We run the code:
-
-```
- python example_main.py
-```
-
-**Do not forget to** configure the routes to the data files at the top of *example_main.py*.
-
-For example, we can run the Mushroom bandit for 2000 contexts on a few
-algorithms as follows:
-
-```
- # Problem parameters
- num_contexts = 2000
-
- # Choose data source among:
- # {linear, sparse_linear, mushroom, financial, jester,
- # statlog, adult, covertype, census, wheel}
- data_type = 'mushroom'
-
- # Create dataset
- sampled_vals = sample_data(data_type, num_contexts)
- dataset, opt_rewards, opt_actions, num_actions, context_dim = sampled_vals
-
- # Define hyperparameters and algorithms
- hparams_linear = tf.contrib.training.HParams(num_actions=num_actions,
- context_dim=context_dim,
- a0=6,
- b0=6,
- lambda_prior=0.25,
- initial_pulls=2)
-
- hparams_dropout = tf.contrib.training.HParams(num_actions=num_actions,
- context_dim=context_dim,
- init_scale=0.3,
- activation=tf.nn.relu,
- layer_sizes=[50],
- batch_size=512,
- activate_decay=True,
- initial_lr=0.1,
- max_grad_norm=5.0,
- show_training=False,
- freq_summary=1000,
- buffer_s=-1,
- initial_pulls=2,
- optimizer='RMS',
- reset_lr=True,
- lr_decay_rate=0.5,
- training_freq=50,
- training_epochs=100,
- keep_prob=0.80,
- use_dropout=True)
-
- ### Create hyper-parameter configurations for other algorithms
- [...]
-
- algos = [
- UniformSampling('Uniform Sampling', hparams),
- PosteriorBNNSampling('Dropout', hparams_dropout, 'RMSProp'),
- PosteriorBNNSampling('BBB', hparams_bbb, 'Variational'),
- NeuralLinearPosteriorSampling('NeuralLinear', hparams_nlinear),
- LinearFullPosteriorSampling('LinFullPost', hparams_linear),
- BootstrappedBNNSampling('BootRMS', hparams_boot),
- ParameterNoiseSampling('ParamNoise', hparams_pnoise),
- ]
-
- # Run contextual bandit problem
- t_init = time.time()
- results = run_contextual_bandit(context_dim, num_actions, dataset, algos)
- _, h_rewards = results
-
- # Display results
- display_results(algos, opt_rewards, opt_actions, h_rewards, t_init, data_type)
-
-```
-
-The previous code leads to final results that look like:
-
-```
----------------------------------------------------
----------------------------------------------------
-mushroom bandit completed after 69.8401839733 seconds.
----------------------------------------------------
- 0) LinFullPost | total reward = 4365.0.
- 1) NeuralLinear | total reward = 4110.0.
- 2) Dropout | total reward = 3430.0.
- 3) ParamNoise | total reward = 3270.0.
- 4) BootRMS | total reward = 3050.0.
- 5) BBB | total reward = 2505.0.
- 6) Uniform Sampling | total reward = -4930.0.
----------------------------------------------------
-Optimal total reward = 5235.
-Frequency of optimal actions (action, frequency):
-[[0, 953], [1, 1047]]
----------------------------------------------------
----------------------------------------------------
-```
diff --git a/research/deep_contextual_bandits/bandits/algorithms/bb_alpha_divergence_model.py b/research/deep_contextual_bandits/bandits/algorithms/bb_alpha_divergence_model.py
deleted file mode 100644
index 5b9c0ebd0988873eaf97d8d68d25dae5e5b9cd71..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/algorithms/bb_alpha_divergence_model.py
+++ /dev/null
@@ -1,373 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Bayesian NN using expectation propagation (Black-Box Alpha-Divergence).
-
-See https://arxiv.org/abs/1511.03243 for details.
-All formulas used in this implementation are derived in:
-https://www.overleaf.com/12837696kwzjxkyhdytk#/49028744/.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import sys
-import numpy as np
-import tensorflow as tf
-from absl import flags
-
-from bandits.core.bayesian_nn import BayesianNN
-
-
-FLAGS = flags.FLAGS
-tfd = tf.contrib.distributions # update to: tensorflow_probability.distributions
-
-
-def log_gaussian(x, mu, sigma, reduce_sum=True):
- res = tfd.Normal(mu, sigma).log_prob(x)
- if reduce_sum:
- return tf.reduce_sum(res)
- else:
- return res
-
-
-class BBAlphaDivergence(BayesianNN):
- """Implements an approximate Bayesian NN via Black-Box Alpha-Divergence."""
-
- def __init__(self, hparams, name):
-
- self.name = name
- self.hparams = hparams
-
- self.alpha = getattr(self.hparams, 'alpha', 1.0)
- self.num_mc_nn_samples = getattr(self.hparams, 'num_mc_nn_samples', 10)
-
- self.n_in = self.hparams.context_dim
- self.n_out = self.hparams.num_actions
- self.layers = self.hparams.layer_sizes
- self.batch_size = self.hparams.batch_size
-
- self.show_training = self.hparams.show_training
- self.freq_summary = self.hparams.freq_summary
- self.verbose = getattr(self.hparams, 'verbose', True)
-
- self.cleared_times_trained = self.hparams.cleared_times_trained
- self.initial_training_steps = self.hparams.initial_training_steps
- self.training_schedule = np.linspace(self.initial_training_steps,
- self.hparams.training_epochs,
- self.cleared_times_trained)
-
- self.times_trained = 0
- self.initialize_model()
-
- def initialize_model(self):
- """Builds and initialize the model."""
-
- self.num_w = 0
- self.num_b = 0
-
- self.weights_m = {}
- self.weights_std = {}
- self.biases_m = {}
- self.biases_std = {}
-
- self.h_max_var = []
-
- if self.hparams.use_sigma_exp_transform:
- self.sigma_transform = tfd.bijectors.Exp()
- else:
- self.sigma_transform = tfd.bijectors.Softplus()
-
- # Build the graph corresponding to the Bayesian NN instance.
- self.graph = tf.Graph()
-
- with self.graph.as_default():
-
- self.sess = tf.Session()
- self.x = tf.placeholder(shape=[None, self.n_in],
- dtype=tf.float32, name='x')
- self.y = tf.placeholder(shape=[None, self.n_out],
- dtype=tf.float32, name='y')
- self.weights = tf.placeholder(shape=[None, self.n_out],
- dtype=tf.float32, name='w')
- self.data_size = tf.placeholder(tf.float32, shape=(), name='data_size')
-
- self.prior_variance = self.hparams.prior_variance
- if self.prior_variance < 0:
- # if not fixed, we learn the prior.
- self.prior_variance = self.sigma_transform.forward(
- self.build_mu_variable([1, 1]))
-
- self.build_model()
- self.sess.run(tf.global_variables_initializer())
-
- def build_mu_variable(self, shape):
- """Returns a mean variable initialized as N(0, 0.05)."""
- return tf.Variable(tf.random_normal(shape, 0.0, 0.05))
-
- def build_sigma_variable(self, shape, init=-5.):
- """Returns a sigma variable initialized as N(init, 0.05)."""
- # Initialize sigma to be very small initially to encourage MAP opt first
- return tf.Variable(tf.random_normal(shape, init, 0.05))
-
- def build_layer(self, input_x, shape, layer_id, activation_fn=tf.nn.relu):
- """Builds a layer with N(mean, std) for each weight, and samples from it."""
-
- w_mu = self.build_mu_variable(shape)
- w_sigma = self.sigma_transform.forward(self.build_sigma_variable(shape))
-
- w_noise = tf.random_normal(shape)
- w = w_mu + w_sigma * w_noise
-
- b_mu = self.build_mu_variable([1, shape[1]])
- b_sigma = self.sigma_transform.forward(
- self.build_sigma_variable([1, shape[1]]))
-
- b_noise = tf.random_normal([1, shape[1]])
- b = b_mu + b_sigma * b_noise
-
- # Create outputs
- output_h = activation_fn(tf.matmul(input_x, w) + b)
-
- # Store means and stds
- self.weights_m[layer_id] = w_mu
- self.weights_std[layer_id] = w_sigma
- self.biases_m[layer_id] = b_mu
- self.biases_std[layer_id] = b_sigma
-
- return output_h
-
- def sample_neural_network(self, activation_fn=tf.nn.relu):
- """Samples a nn from posterior, computes data log lk and log f factor."""
-
- with self.graph.as_default():
-
- log_f = 0
- n = self.data_size
- input_x = self.x
-
- for layer_id in range(self.total_layers):
-
- # load mean and std of each weight
- w_mu = self.weights_m[layer_id]
- w_sigma = self.weights_std[layer_id]
- b_mu = self.biases_m[layer_id]
- b_sigma = self.biases_std[layer_id]
-
- # sample weights from Gaussian distribution
- shape = w_mu.shape
- w_noise = tf.random_normal(shape)
- b_noise = tf.random_normal([1, int(shape[1])])
- w = w_mu + w_sigma * w_noise
- b = b_mu + b_sigma * b_noise
-
- # compute contribution to log_f
- t1 = w * w_mu / (n * w_sigma ** 2)
- t2 = (0.5 * w ** 2 / n) * (1 / self.prior_variance - 1 / w_sigma ** 2)
- log_f += tf.reduce_sum(t1 + t2)
-
- t1 = b * b_mu / (n * b_sigma ** 2)
- t2 = (0.5 * b ** 2 / n) * (1 / self.prior_variance - 1 / b_sigma ** 2)
- log_f += tf.reduce_sum(t1 + t2)
-
- if layer_id < self.total_layers - 1:
- output_h = activation_fn(tf.matmul(input_x, w) + b)
- else:
- output_h = tf.matmul(input_x, w) + b
-
- input_x = output_h
-
- # compute log likelihood of the observed reward under the sampled nn
- log_likelihood = log_gaussian(
- self.y, output_h, self.noise_sigma, reduce_sum=False)
- weighted_log_likelihood = tf.reduce_sum(log_likelihood * self.weights, -1)
-
- return log_f, weighted_log_likelihood
-
- def log_z_q(self):
- """Computes log-partition function of current posterior parameters."""
-
- with self.graph.as_default():
-
- log_z_q = 0
-
- for layer_id in range(self.total_layers):
-
- w_mu = self.weights_m[layer_id]
- w_sigma = self.weights_std[layer_id]
- b_mu = self.biases_m[layer_id]
- b_sigma = self.biases_std[layer_id]
-
- w_term = 0.5 * tf.reduce_sum(w_mu ** 2 / w_sigma ** 2)
- w_term += 0.5 * tf.reduce_sum(tf.log(2 * np.pi) + 2 * tf.log(w_sigma))
-
- b_term = 0.5 * tf.reduce_sum(b_mu ** 2 / b_sigma ** 2)
- b_term += 0.5 * tf.reduce_sum(tf.log(2 * np.pi) + 2 * tf.log(b_sigma))
-
- log_z_q += w_term + b_term
-
- return log_z_q
-
- def log_z_prior(self):
- """Computes log-partition function of the prior parameters."""
- num_params = self.num_w + self.num_b
- return num_params * 0.5 * tf.log(2 * np.pi * self.prior_variance)
-
- def log_alpha_likelihood_ratio(self, activation_fn=tf.nn.relu):
-
- # each nn sample returns (log f, log likelihoods)
- nn_samples = [
- self.sample_neural_network(activation_fn)
- for _ in range(self.num_mc_nn_samples)
- ]
- nn_log_f_samples = [elt[0] for elt in nn_samples]
- nn_log_lk_samples = [elt[1] for elt in nn_samples]
-
- # we stack the (log f, log likelihoods) from the k nn samples
- nn_log_f_stack = tf.stack(nn_log_f_samples) # k x 1
- nn_log_lk_stack = tf.stack(nn_log_lk_samples) # k x N
- nn_f_tile = tf.tile(nn_log_f_stack, [self.batch_size])
- nn_f_tile = tf.reshape(nn_f_tile,
- [self.num_mc_nn_samples, self.batch_size])
-
- # now both the log f and log likelihood terms have shape: k x N
- # apply formula in https://www.overleaf.com/12837696kwzjxkyhdytk#/49028744/
- nn_log_ratio = nn_log_lk_stack - nn_f_tile
- nn_log_ratio = self.alpha * tf.transpose(nn_log_ratio)
- logsumexp_value = tf.reduce_logsumexp(nn_log_ratio, -1)
- log_k_scalar = tf.log(tf.cast(self.num_mc_nn_samples, tf.float32))
- log_k = log_k_scalar * tf.ones([self.batch_size])
-
- return tf.reduce_sum(logsumexp_value - log_k, -1)
-
- def build_model(self, activation_fn=tf.nn.relu):
- """Defines the actual NN model with fully connected layers.
-
- Args:
- activation_fn: Activation function for the neural network.
-
- The loss is computed for partial feedback settings (bandits), so only
- the observed outcome is backpropagated (see weighted loss).
- Selects the optimizer and, finally, it also initializes the graph.
- """
-
- print('Initializing model {}.'.format(self.name))
-
- # Build terms for the noise sigma estimation for each action.
- noise_sigma_mu = (self.build_mu_variable([1, self.n_out])
- + self.sigma_transform.inverse(self.hparams.noise_sigma))
- noise_sigma_sigma = self.sigma_transform.forward(
- self.build_sigma_variable([1, self.n_out]))
-
- pre_noise_sigma = noise_sigma_mu + tf.random_normal(
- [1, self.n_out]) * noise_sigma_sigma
- self.noise_sigma = self.sigma_transform.forward(pre_noise_sigma)
-
- # Build network
- input_x = self.x
- n_in = self.n_in
- self.total_layers = len(self.layers) + 1
- if self.layers[0] == 0:
- self.total_layers = 1
-
- for l_number, n_nodes in enumerate(self.layers):
- if n_nodes > 0:
- h = self.build_layer(input_x, [n_in, n_nodes], l_number)
- input_x = h
- n_in = n_nodes
- self.num_w += n_in * n_nodes
- self.num_b += n_nodes
-
- self.y_pred = self.build_layer(input_x, [n_in, self.n_out],
- self.total_layers - 1,
- activation_fn=lambda x: x)
-
- # Compute energy function based on sampled nn's
- log_coeff = self.data_size / (self.batch_size * self.alpha)
- log_ratio = log_coeff * self.log_alpha_likelihood_ratio(activation_fn)
- logzprior = self.log_z_prior()
- logzq = self.log_z_q()
- energy = logzprior - logzq - log_ratio
-
- self.loss = energy
- self.global_step = tf.train.get_or_create_global_step()
- self.train_op = tf.train.AdamOptimizer(self.hparams.initial_lr).minimize(
- self.loss, global_step=self.global_step)
-
- # Useful for debugging
- sq_loss = tf.squared_difference(self.y_pred, self.y)
- weighted_sq_loss = self.weights * sq_loss
- self.cost = tf.reduce_sum(weighted_sq_loss) / self.batch_size
-
- # Create tensorboard metrics
- self.create_summaries()
- self.summary_writer = tf.summary.FileWriter('{}/graph_{}'.format(
- FLAGS.logdir, self.name), self.sess.graph)
-
- def create_summaries(self):
- tf.summary.scalar('loss', self.loss)
- tf.summary.scalar('cost', self.cost)
- self.summary_op = tf.summary.merge_all()
-
- def assign_lr(self):
- """Resets the learning rate in dynamic schedules for subsequent trainings.
-
- In bandits settings, we do expand our dataset over time. Then, we need to
- re-train the network with the new data. Those algorithms that do not keep
- the step constant, can reset it at the start of each training process.
- """
-
- decay_steps = 1
- if self.hparams.activate_decay:
- current_gs = self.sess.run(self.global_step)
- with self.graph.as_default():
- self.lr = tf.train.inverse_time_decay(self.hparams.initial_lr,
- self.global_step - current_gs,
- decay_steps,
- self.hparams.lr_decay_rate)
-
- def train(self, data, num_steps):
- """Trains the BNN for num_steps, using the data in 'data'.
-
- Args:
- data: ContextualDataset object that provides the data.
- num_steps: Number of minibatches to train the network for.
- """
-
- if self.times_trained < self.cleared_times_trained:
- num_steps = int(self.training_schedule[self.times_trained])
- self.times_trained += 1
-
- if self.verbose:
- print('Training {} for {} steps...'.format(self.name, num_steps))
-
- with self.graph.as_default():
-
- for step in range(num_steps):
- x, y, w = data.get_batch_with_weights(self.hparams.batch_size)
- _, summary, global_step, loss = self.sess.run(
- [self.train_op, self.summary_op, self.global_step, self.loss],
- feed_dict={self.x: x, self.y: y, self.weights: w,
- self.data_size: data.num_points()})
-
- weights_l = self.sess.run(self.weights_std[0])
- self.h_max_var.append(np.max(weights_l))
-
- if step % self.freq_summary == 0:
- if self.show_training:
- print('step: {}, loss: {}'.format(step, loss))
- sys.stdout.flush()
- self.summary_writer.add_summary(summary, global_step)
diff --git a/research/deep_contextual_bandits/bandits/algorithms/bf_variational_neural_bandit_model.py b/research/deep_contextual_bandits/bandits/algorithms/bf_variational_neural_bandit_model.py
deleted file mode 100644
index cb87c23358f27bd93e30528b20f7a3bb3ba876dd..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/algorithms/bf_variational_neural_bandit_model.py
+++ /dev/null
@@ -1,352 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Bayesian NN using factorized VI (Bayes By Backprop. Blundell et al. 2014).
-
-See https://arxiv.org/abs/1505.05424 for details.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import tensorflow as tf
-# import tensorflow_probability as tfp
-
-from absl import flags
-from bandits.core.bayesian_nn import BayesianNN
-
-
-FLAGS = flags.FLAGS
-# tfd = tfp.distributions
-tfd = tf.contrib.distributions
-tfl = tf.contrib.layers
-
-
-def log_gaussian(x, mu, sigma, reduce_sum=True):
- """Returns log Gaussian pdf."""
- res = tfd.Normal(mu, sigma).log_prob(x)
- if reduce_sum:
- return tf.reduce_sum(res)
- else:
- return res
-
-
-def analytic_kl(mu_1, sigma_1, mu_2, sigma_2):
- """KL for two Gaussian distributions with diagonal covariance matrix."""
- kl = tfd.kl_divergence(tfd.MVNDiag(mu_1, sigma_1), tfd.MVNDiag(mu_2, sigma_2))
- return kl
-
-
-class BfVariationalNeuralBanditModel(BayesianNN):
- """Implements an approximate Bayesian NN using Variational Inference."""
-
- def __init__(self, hparams, name="BBBNN"):
-
- self.name = name
- self.hparams = hparams
-
- self.n_in = self.hparams.context_dim
- self.n_out = self.hparams.num_actions
- self.layers = self.hparams.layer_sizes
- self.init_scale = self.hparams.init_scale
- self.f_num_points = None
- if "f_num_points" in hparams:
- self.f_num_points = self.hparams.f_num_points
-
- self.cleared_times_trained = self.hparams.cleared_times_trained
- self.initial_training_steps = self.hparams.initial_training_steps
- self.training_schedule = np.linspace(self.initial_training_steps,
- self.hparams.training_epochs,
- self.cleared_times_trained)
- self.verbose = getattr(self.hparams, "verbose", True)
-
- self.weights_m = {}
- self.weights_std = {}
- self.biases_m = {}
- self.biases_std = {}
-
- self.times_trained = 0
-
- if self.hparams.use_sigma_exp_transform:
- self.sigma_transform = tf.exp
- self.inverse_sigma_transform = np.log
- else:
- self.sigma_transform = tf.nn.softplus
- self.inverse_sigma_transform = lambda y: y + np.log(1. - np.exp(-y))
-
- # Whether to use the local reparameterization trick to compute the loss.
- # See details in https://arxiv.org/abs/1506.02557
- self.use_local_reparameterization = True
-
- self.build_graph()
-
- def build_mu_variable(self, shape):
- """Returns a mean variable initialized as N(0, 0.05)."""
- return tf.Variable(tf.random_normal(shape, 0.0, 0.05))
-
- def build_sigma_variable(self, shape, init=-5.):
- """Returns a sigma variable initialized as N(init, 0.05)."""
- # Initialize sigma to be very small initially to encourage MAP opt first
- return tf.Variable(tf.random_normal(shape, init, 0.05))
-
- def build_layer(self, input_x, input_x_local, shape,
- layer_id, activation_fn=tf.nn.relu):
- """Builds a variational layer, and computes KL term.
-
- Args:
- input_x: Input to the variational layer.
- input_x_local: Input when the local reparameterization trick was applied.
- shape: [number_inputs, number_outputs] for the layer.
- layer_id: Number of layer in the architecture.
- activation_fn: Activation function to apply.
-
- Returns:
- output_h: Output of the variational layer.
- output_h_local: Output when local reparameterization trick was applied.
- neg_kl: Negative KL term for the layer.
- """
-
- w_mu = self.build_mu_variable(shape)
- w_sigma = self.sigma_transform(self.build_sigma_variable(shape))
- w_noise = tf.random_normal(shape)
- w = w_mu + w_sigma * w_noise
-
- b_mu = self.build_mu_variable([1, shape[1]])
- b_sigma = self.sigma_transform(self.build_sigma_variable([1, shape[1]]))
- b = b_mu
-
- # Store means and stds
- self.weights_m[layer_id] = w_mu
- self.weights_std[layer_id] = w_sigma
- self.biases_m[layer_id] = b_mu
- self.biases_std[layer_id] = b_sigma
-
- # Create outputs
- output_h = activation_fn(tf.matmul(input_x, w) + b)
-
- if self.use_local_reparameterization:
- # Use analytic KL divergence wrt the prior
- neg_kl = -analytic_kl(w_mu, w_sigma,
- 0., tf.to_float(np.sqrt(2./shape[0])))
- else:
- # Create empirical KL loss terms
- log_p = log_gaussian(w, 0., tf.to_float(np.sqrt(2./shape[0])))
- log_q = log_gaussian(w, tf.stop_gradient(w_mu), tf.stop_gradient(w_sigma))
- neg_kl = log_p - log_q
-
- # Apply local reparameterization trick: sample activations pre nonlinearity
- m_h = tf.matmul(input_x_local, w_mu) + b
- v_h = tf.matmul(tf.square(input_x_local), tf.square(w_sigma))
- output_h_local = m_h + tf.sqrt(v_h + 1e-6) * tf.random_normal(tf.shape(v_h))
- output_h_local = activation_fn(output_h_local)
-
- return output_h, output_h_local, neg_kl
-
- def build_action_noise(self):
- """Defines a model for additive noise per action, and its KL term."""
-
- # Define mean and std variables (log-normal dist) for each action.
- noise_sigma_mu = (self.build_mu_variable([1, self.n_out])
- + self.inverse_sigma_transform(self.hparams.noise_sigma))
- noise_sigma_sigma = self.sigma_transform(
- self.build_sigma_variable([1, self.n_out]))
-
- pre_noise_sigma = (noise_sigma_mu
- + tf.random_normal([1, self.n_out]) * noise_sigma_sigma)
- self.noise_sigma = self.sigma_transform(pre_noise_sigma)
-
- # Compute KL for additive noise sigma terms.
- if getattr(self.hparams, "infer_noise_sigma", False):
- neg_kl_term = log_gaussian(
- pre_noise_sigma,
- self.inverse_sigma_transform(self.hparams.noise_sigma),
- self.hparams.prior_sigma
- )
- neg_kl_term -= log_gaussian(pre_noise_sigma,
- noise_sigma_mu,
- noise_sigma_sigma)
- else:
- neg_kl_term = 0.
-
- return neg_kl_term
-
- def build_model(self, activation_fn=tf.nn.relu):
- """Defines the actual NN model with fully connected layers.
-
- The loss is computed for partial feedback settings (bandits), so only
- the observed outcome is backpropagated (see weighted loss).
- Selects the optimizer and, finally, it also initializes the graph.
-
- Args:
- activation_fn: the activation function used in the nn layers.
- """
-
- def weight_prior(dtype, shape, c, d, e):
- del c, d, e
- return tfd.Independent(
- tfd.Normal(loc=tf.zeros(shape, dtype),
- scale=tf.to_float(np.sqrt(2) / shape[0])),
- reinterpreted_batch_ndims=tf.size(shape))
-
- if self.verbose:
- print("Initializing model {}.".format(self.name))
-
- # Compute model additive noise for each action with log-normal distribution
- neg_kl_term = self.build_action_noise()
-
- # Build variational network using self.x as input.
- input_x = self.x
-
- # Create Keras model using DenseLocalReparameterization (prior N(0, 1)).
- model_layers = [
- tfl.DenseLocalReparameterization(
- n_nodes,
- activation=tf.nn.relu,
- kernel_prior_fn=weight_prior
- )
- for n_nodes in self.layers if n_nodes > 0
- ]
-
- output_layer = tfl.DenseLocalReparameterization(
- self.n_out,
- activation=lambda x: x,
- kernel_prior_fn=weight_prior
- )
- model_layers.append(output_layer)
-
- model = tf.keras.Sequential(model_layers)
- self.y_pred = model(input_x)
-
- # Compute KL term
- neg_kl_term -= tf.add_n(model.losses)
-
- # Compute log likelihood (with learned or fixed noise level)
- if getattr(self.hparams, "infer_noise_sigma", False):
- log_likelihood = log_gaussian(
- self.y, self.y_pred, self.noise_sigma, reduce_sum=False)
- else:
- log_likelihood = log_gaussian(
- self.y, self.y_pred, self.hparams.noise_sigma, reduce_sum=False)
-
- # Only take into account observed outcomes (bandits setting)
- batch_size = tf.to_float(tf.shape(self.x)[0])
- weighted_log_likelihood = tf.reduce_sum(
- log_likelihood * self.weights) / batch_size
-
- # The objective is 1/n * (\sum_i log_like_i - KL); neg_kl_term estimates -KL
- elbo = weighted_log_likelihood + (neg_kl_term / self.n)
-
- self.loss = -elbo
- self.global_step = tf.train.get_or_create_global_step()
- self.train_op = tf.train.AdamOptimizer(self.hparams.initial_lr).minimize(
- self.loss, global_step=self.global_step)
-
- # Create tensorboard metrics
- self.create_summaries()
- self.summary_writer = tf.summary.FileWriter(
- "{}/graph_{}".format(FLAGS.logdir, self.name), self.sess.graph)
-
- def build_graph(self):
- """Defines graph, session, placeholders, and model.
-
- Placeholders are: n (size of the dataset), x and y (context and observed
- reward for each action), and weights (one-hot encoding of selected action
- for each context, i.e., only possibly non-zero element in each y).
- """
-
- self.graph = tf.Graph()
- with self.graph.as_default():
-
- self.sess = tf.Session()
-
- self.n = tf.placeholder(shape=[], dtype=tf.float32)
-
- self.x = tf.placeholder(shape=[None, self.n_in], dtype=tf.float32)
- self.y = tf.placeholder(shape=[None, self.n_out], dtype=tf.float32)
- self.weights = tf.placeholder(shape=[None, self.n_out], dtype=tf.float32)
-
- self.build_model()
- self.sess.run(tf.global_variables_initializer())
-
- def create_summaries(self):
- """Defines summaries including mean loss, and global step."""
-
- with self.graph.as_default():
- with tf.name_scope(self.name + "_summaries"):
- tf.summary.scalar("loss", self.loss)
- tf.summary.scalar("global_step", self.global_step)
- self.summary_op = tf.summary.merge_all()
-
- def assign_lr(self):
- """Resets the learning rate in dynamic schedules for subsequent trainings.
-
- In bandits settings, we do expand our dataset over time. Then, we need to
- re-train the network with the new data. The algorithms that do not keep
- the step constant, can reset it at the start of each *training* process.
- """
-
- decay_steps = 1
- if self.hparams.activate_decay:
- current_gs = self.sess.run(self.global_step)
- with self.graph.as_default():
- self.lr = tf.train.inverse_time_decay(self.hparams.initial_lr,
- self.global_step - current_gs,
- decay_steps,
- self.hparams.lr_decay_rate)
-
- def train(self, data, num_steps):
- """Trains the BNN for num_steps, using the data in 'data'.
-
- Args:
- data: ContextualDataset object that provides the data.
- num_steps: Number of minibatches to train the network for.
-
- Returns:
- losses: Loss history during training.
- """
-
- if self.times_trained < self.cleared_times_trained:
- num_steps = int(self.training_schedule[self.times_trained])
- self.times_trained += 1
-
- losses = []
-
- with self.graph.as_default():
-
- if self.verbose:
- print("Training {} for {} steps...".format(self.name, num_steps))
-
- for step in range(num_steps):
- x, y, weights = data.get_batch_with_weights(self.hparams.batch_size)
- _, summary, global_step, loss = self.sess.run(
- [self.train_op, self.summary_op, self.global_step, self.loss],
- feed_dict={
- self.x: x,
- self.y: y,
- self.weights: weights,
- self.n: data.num_points(self.f_num_points),
- })
-
- losses.append(loss)
-
- if step % self.hparams.freq_summary == 0:
- if self.hparams.show_training:
- print("{} | step: {}, loss: {}".format(
- self.name, global_step, loss))
- self.summary_writer.add_summary(summary, global_step)
-
- return losses
diff --git a/research/deep_contextual_bandits/bandits/algorithms/bootstrapped_bnn_sampling.py b/research/deep_contextual_bandits/bandits/algorithms/bootstrapped_bnn_sampling.py
deleted file mode 100644
index 7c44b681c7bd1da113ec29c1bb6d370c88d7053f..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/algorithms/bootstrapped_bnn_sampling.py
+++ /dev/null
@@ -1,98 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Contextual algorithm based on boostrapping neural networks."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-
-from bandits.core.bandit_algorithm import BanditAlgorithm
-from bandits.core.contextual_dataset import ContextualDataset
-from bandits.algorithms.neural_bandit_model import NeuralBanditModel
-
-
-class BootstrappedBNNSampling(BanditAlgorithm):
- """Thompson Sampling algorithm based on training several neural networks."""
-
- def __init__(self, name, hparams, optimizer='RMS'):
- """Creates a BootstrappedSGDSampling object based on a specific optimizer.
-
- hparams.q: Number of models that are independently trained.
- hparams.p: Prob of independently including each datapoint in each model.
-
- Args:
- name: Name given to the instance.
- hparams: Hyperparameters for each individual model.
- optimizer: Neural network optimization algorithm.
- """
-
- self.name = name
- self.hparams = hparams
- self.optimizer_n = optimizer
-
- self.training_freq = hparams.training_freq
- self.training_epochs = hparams.training_epochs
- self.t = 0
-
- self.q = hparams.q
- self.p = hparams.p
-
- self.datasets = [
- ContextualDataset(hparams.context_dim,
- hparams.num_actions,
- hparams.buffer_s)
- for _ in range(self.q)
- ]
-
- self.bnn_boot = [
- NeuralBanditModel(optimizer, hparams, '{}-{}-bnn'.format(name, i))
- for i in range(self.q)
- ]
-
- def action(self, context):
- """Selects action for context based on Thompson Sampling using one BNN."""
-
- if self.t < self.hparams.num_actions * self.hparams.initial_pulls:
- # round robin until each action has been taken "initial_pulls" times
- return self.t % self.hparams.num_actions
-
- # choose model uniformly at random
- model_index = np.random.randint(self.q)
-
- with self.bnn_boot[model_index].graph.as_default():
- c = context.reshape((1, self.hparams.context_dim))
- output = self.bnn_boot[model_index].sess.run(
- self.bnn_boot[model_index].y_pred,
- feed_dict={self.bnn_boot[model_index].x: c})
- return np.argmax(output)
-
- def update(self, context, action, reward):
- """Updates the data buffer, and re-trains the BNN every self.freq_update."""
-
- self.t += 1
- for i in range(self.q):
- # include the data point with probability p independently in each dataset
- if np.random.random() < self.p or self.t < 2:
- self.datasets[i].add(context, action, reward)
-
- if self.t % self.training_freq == 0:
- # update all the models:
- for i in range(self.q):
- if self.hparams.reset_lr:
- self.bnn_boot[i].assign_lr()
- self.bnn_boot[i].train(self.datasets[i], self.training_epochs)
diff --git a/research/deep_contextual_bandits/bandits/algorithms/fixed_policy_sampling.py b/research/deep_contextual_bandits/bandits/algorithms/fixed_policy_sampling.py
deleted file mode 100644
index d5ad6e3ed9ed9d1478e6ac132b41cfb5ae1bb47a..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/algorithms/fixed_policy_sampling.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Contextual bandit algorithm that selects an action at random."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-
-from bandits.core.bandit_algorithm import BanditAlgorithm
-
-
-class FixedPolicySampling(BanditAlgorithm):
- """Defines a baseline; returns an action at random with probs given by p."""
-
- def __init__(self, name, p, hparams):
- """Creates a FixedPolicySampling object.
-
- Args:
- name: Name of the algorithm.
- p: Vector of normalized probabilities corresponding to sampling each arm.
- hparams: Hyper-parameters, including the number of arms (num_actions).
-
- Raises:
- ValueError: when p dimension does not match the number of actions.
- """
-
- self.name = name
- self.p = p
- self.hparams = hparams
-
- if len(p) != self.hparams.num_actions:
- raise ValueError('Policy needs k probabilities.')
-
- def action(self, context):
- """Selects an action at random according to distribution p."""
- return np.random.choice(range(self.hparams.num_actions), p=self.p)
diff --git a/research/deep_contextual_bandits/bandits/algorithms/linear_full_posterior_sampling.py b/research/deep_contextual_bandits/bandits/algorithms/linear_full_posterior_sampling.py
deleted file mode 100644
index 15ef8fa9b562101111042dc2ce7b17174018ab6e..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/algorithms/linear_full_posterior_sampling.py
+++ /dev/null
@@ -1,164 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Contextual algorithm that keeps a full linear posterior for each arm."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-from scipy.stats import invgamma
-
-from bandits.core.bandit_algorithm import BanditAlgorithm
-from bandits.core.contextual_dataset import ContextualDataset
-
-
-class LinearFullPosteriorSampling(BanditAlgorithm):
- """Thompson Sampling with independent linear models and unknown noise var."""
-
- def __init__(self, name, hparams):
- """Initialize posterior distributions and hyperparameters.
-
- Assume a linear model for each action i: reward = context^T beta_i + noise
- Each beta_i has a Gaussian prior (lambda parameter), each sigma2_i (noise
- level) has an inverse Gamma prior (a0, b0 parameters). Mean, covariance,
- and precision matrices are initialized, and the ContextualDataset created.
-
- Args:
- name: Name of the algorithm.
- hparams: Hyper-parameters of the algorithm.
- """
-
- self.name = name
- self.hparams = hparams
-
- # Gaussian prior for each beta_i
- self._lambda_prior = self.hparams.lambda_prior
-
- self.mu = [
- np.zeros(self.hparams.context_dim + 1)
- for _ in range(self.hparams.num_actions)
- ]
-
- self.cov = [(1.0 / self.lambda_prior) * np.eye(self.hparams.context_dim + 1)
- for _ in range(self.hparams.num_actions)]
-
- self.precision = [
- self.lambda_prior * np.eye(self.hparams.context_dim + 1)
- for _ in range(self.hparams.num_actions)
- ]
-
- # Inverse Gamma prior for each sigma2_i
- self._a0 = self.hparams.a0
- self._b0 = self.hparams.b0
-
- self.a = [self._a0 for _ in range(self.hparams.num_actions)]
- self.b = [self._b0 for _ in range(self.hparams.num_actions)]
-
- self.t = 0
- self.data_h = ContextualDataset(hparams.context_dim,
- hparams.num_actions,
- intercept=True)
-
- def action(self, context):
- """Samples beta's from posterior, and chooses best action accordingly.
-
- Args:
- context: Context for which the action need to be chosen.
-
- Returns:
- action: Selected action for the context.
- """
-
- # Round robin until each action has been selected "initial_pulls" times
- if self.t < self.hparams.num_actions * self.hparams.initial_pulls:
- return self.t % self.hparams.num_actions
-
- # Sample sigma2, and beta conditional on sigma2
- sigma2_s = [
- self.b[i] * invgamma.rvs(self.a[i])
- for i in range(self.hparams.num_actions)
- ]
-
- try:
- beta_s = [
- np.random.multivariate_normal(self.mu[i], sigma2_s[i] * self.cov[i])
- for i in range(self.hparams.num_actions)
- ]
- except np.linalg.LinAlgError as e:
- # Sampling could fail if covariance is not positive definite
- print('Exception when sampling from {}.'.format(self.name))
- print('Details: {} | {}.'.format(e.message, e.args))
- d = self.hparams.context_dim + 1
- beta_s = [
- np.random.multivariate_normal(np.zeros((d)), np.eye(d))
- for i in range(self.hparams.num_actions)
- ]
-
- # Compute sampled expected values, intercept is last component of beta
- vals = [
- np.dot(beta_s[i][:-1], context.T) + beta_s[i][-1]
- for i in range(self.hparams.num_actions)
- ]
-
- return np.argmax(vals)
-
- def update(self, context, action, reward):
- """Updates action posterior using the linear Bayesian regression formula.
-
- Args:
- context: Last observed context.
- action: Last observed action.
- reward: Last observed reward.
- """
-
- self.t += 1
- self.data_h.add(context, action, reward)
-
- # Update posterior of action with formulas: \beta | x,y ~ N(mu_q, cov_q)
- x, y = self.data_h.get_data(action)
-
- # The algorithm could be improved with sequential update formulas (cheaper)
- s = np.dot(x.T, x)
-
- # Some terms are removed as we assume prior mu_0 = 0.
- precision_a = s + self.lambda_prior * np.eye(self.hparams.context_dim + 1)
- cov_a = np.linalg.inv(precision_a)
- mu_a = np.dot(cov_a, np.dot(x.T, y))
-
- # Inverse Gamma posterior update
- a_post = self.a0 + x.shape[0] / 2.0
- b_upd = 0.5 * (np.dot(y.T, y) - np.dot(mu_a.T, np.dot(precision_a, mu_a)))
- b_post = self.b0 + b_upd
-
- # Store new posterior distributions
- self.mu[action] = mu_a
- self.cov[action] = cov_a
- self.precision[action] = precision_a
- self.a[action] = a_post
- self.b[action] = b_post
-
- @property
- def a0(self):
- return self._a0
-
- @property
- def b0(self):
- return self._b0
-
- @property
- def lambda_prior(self):
- return self._lambda_prior
diff --git a/research/deep_contextual_bandits/bandits/algorithms/multitask_gp.py b/research/deep_contextual_bandits/bandits/algorithms/multitask_gp.py
deleted file mode 100644
index 0c35dfaeaf9e30993d49d807f16dd64e15d3fc66..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/algorithms/multitask_gp.py
+++ /dev/null
@@ -1,374 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""A Multitask Gaussian process."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from absl import flags
-from absl import logging
-
-import numpy as np
-import tensorflow as tf
-from bandits.core.bayesian_nn import BayesianNN
-
-FLAGS = flags.FLAGS
-tfd = tf.contrib.distributions
-
-class MultitaskGP(BayesianNN):
- """Implements a Gaussian process with multi-task outputs.
-
- Optimizes the hyperparameters over the log marginal likelihood.
- Uses a Matern 3/2 + linear covariance and returns
- sampled predictions for test inputs. The outputs are optionally
- correlated where the correlation structure is learned through latent
- embeddings of the tasks.
- """
-
- def __init__(self, hparams):
- self.name = "MultiTaskGP"
- self.hparams = hparams
-
- self.n_in = self.hparams.context_dim
- self.n_out = self.hparams.num_outputs
- self.keep_fixed_after_max_obs = self.hparams.keep_fixed_after_max_obs
-
- self._show_training = self.hparams.show_training
- self._freq_summary = self.hparams.freq_summary
-
- # Dimensionality of the latent task vectors
- self.task_latent_dim = self.hparams.task_latent_dim
-
- # Maximum number of observations to include
- self.max_num_points = self.hparams.max_num_points
-
- if self.hparams.learn_embeddings:
- self.learn_embeddings = self.hparams.learn_embeddings
- else:
- self.learn_embeddings = False
-
- # create the graph corresponding to the BNN instance
- self.graph = tf.Graph()
- with self.graph.as_default():
- # store a new session for the graph
- self.sess = tf.Session()
-
- with tf.variable_scope(self.name, reuse=tf.AUTO_REUSE):
- self.n = tf.placeholder(shape=[], dtype=tf.float64)
- self.x = tf.placeholder(shape=[None, self.n_in], dtype=tf.float64)
- self.x_in = tf.placeholder(shape=[None, self.n_in], dtype=tf.float64)
- self.y = tf.placeholder(shape=[None, self.n_out], dtype=tf.float64)
- self.weights = tf.placeholder(shape=[None, self.n_out],
- dtype=tf.float64)
-
- self.build_model()
- self.sess.run(tf.global_variables_initializer())
-
- def atleast_2d(self, x, dims):
- return tf.reshape(tf.expand_dims(x, axis=0), (-1, dims))
-
- def sq_dist(self, x, x2):
- a2 = tf.reduce_sum(tf.square(x), 1)
- b2 = tf.reduce_sum(tf.square(x2), 1)
- sqdists = tf.expand_dims(a2, 1) + b2 - 2.0 * tf.matmul(x, tf.transpose(x2))
- return sqdists
-
- # Covariance between outputs
- def task_cov(self, x, x2):
- """Squared Exponential Covariance Kernel over latent task embeddings."""
- # Index into latent task vectors
- x_vecs = tf.gather(self.task_vectors, tf.argmax(x, axis=1), axis=0)
- x2_vecs = tf.gather(self.task_vectors, tf.argmax(x2, axis=1), axis=0)
- r = self.sq_dist(self.atleast_2d(x_vecs, self.task_latent_dim),
- self.atleast_2d(x2_vecs, self.task_latent_dim))
- return tf.exp(-r)
-
- def cov(self, x, x2):
- """Matern 3/2 + Linear Gaussian Process Covariance Function."""
- ls = tf.clip_by_value(self.length_scales, -5.0, 5.0)
- ls_lin = tf.clip_by_value(self.length_scales_lin, -5.0, 5.0)
- r = self.sq_dist(self.atleast_2d(x, self.n_in)/tf.nn.softplus(ls),
- self.atleast_2d(x2, self.n_in)/tf.nn.softplus(ls))
- r = tf.clip_by_value(r, 0, 1e8)
-
- # Matern 3/2 Covariance
- matern = (1.0 + tf.sqrt(3.0*r + 1e-16)) * tf.exp(-tf.sqrt(3.0*r + 1e-16))
- # Linear Covariance
- lin = tf.matmul(x / tf.nn.softplus(ls_lin),
- x2 / tf.nn.softplus(ls_lin), transpose_b=True)
- return (tf.nn.softplus(self.amplitude) * matern +
- tf.nn.softplus(self.amplitude_linear) * lin)
-
- def build_model(self):
- """Defines the GP model.
-
- The loss is computed for partial feedback settings (bandits), so only
- the observed outcome is backpropagated (see weighted loss).
- Selects the optimizer and, finally, it also initializes the graph.
- """
-
- logging.info("Initializing model %s.", self.name)
- self.global_step = tf.train.get_or_create_global_step()
-
- # Define state for the model (inputs, etc.)
- self.x_train = tf.get_variable(
- "training_data",
- initializer=tf.ones(
- [self.hparams.batch_size, self.n_in], dtype=tf.float64),
- validate_shape=False,
- trainable=False)
- self.y_train = tf.get_variable(
- "training_labels",
- initializer=tf.zeros([self.hparams.batch_size, 1], dtype=tf.float64),
- validate_shape=False,
- trainable=False)
- self.weights_train = tf.get_variable(
- "weights_train",
- initializer=tf.ones(
- [self.hparams.batch_size, self.n_out], dtype=tf.float64),
- validate_shape=False,
- trainable=False)
- self.input_op = tf.assign(self.x_train, self.x_in, validate_shape=False)
- self.input_w_op = tf.assign(
- self.weights_train, self.weights, validate_shape=False)
-
- self.input_std = tf.get_variable(
- "data_standard_deviation",
- initializer=tf.ones([1, self.n_out], dtype=tf.float64),
- dtype=tf.float64,
- trainable=False)
- self.input_mean = tf.get_variable(
- "data_mean",
- initializer=tf.zeros([1, self.n_out], dtype=tf.float64),
- dtype=tf.float64,
- trainable=True)
-
- # GP Hyperparameters
- self.noise = tf.get_variable(
- "noise", initializer=tf.cast(0.0, dtype=tf.float64))
- self.amplitude = tf.get_variable(
- "amplitude", initializer=tf.cast(1.0, dtype=tf.float64))
- self.amplitude_linear = tf.get_variable(
- "linear_amplitude", initializer=tf.cast(1.0, dtype=tf.float64))
- self.length_scales = tf.get_variable(
- "length_scales", initializer=tf.zeros([1, self.n_in], dtype=tf.float64))
- self.length_scales_lin = tf.get_variable(
- "length_scales_linear",
- initializer=tf.zeros([1, self.n_in], dtype=tf.float64))
-
- # Latent embeddings of the different outputs for task covariance
- self.task_vectors = tf.get_variable(
- "latent_task_vectors",
- initializer=tf.random_normal(
- [self.n_out, self.task_latent_dim], dtype=tf.float64))
-
- # Normalize outputs across each dimension
- # Since we have different numbers of observations across each task, we
- # normalize by their respective counts.
- index_counts = self.atleast_2d(tf.reduce_sum(self.weights, axis=0),
- self.n_out)
- index_counts = tf.where(index_counts > 0, index_counts,
- tf.ones(tf.shape(index_counts), dtype=tf.float64))
- self.mean_op = tf.assign(self.input_mean,
- tf.reduce_sum(self.y, axis=0) / index_counts)
- self.var_op = tf.assign(
- self.input_std, tf.sqrt(1e-4 + tf.reduce_sum(tf.square(
- self.y - tf.reduce_sum(self.y, axis=0) / index_counts), axis=0)
- / index_counts))
-
- with tf.control_dependencies([self.var_op]):
- y_normed = self.atleast_2d(
- (self.y - self.input_mean) / self.input_std, self.n_out)
- y_normed = self.atleast_2d(tf.boolean_mask(y_normed, self.weights > 0), 1)
- self.out_op = tf.assign(self.y_train, y_normed, validate_shape=False)
-
- # Observation noise
- alpha = tf.nn.softplus(self.noise) + 1e-6
-
- # Covariance
- with tf.control_dependencies([self.input_op, self.input_w_op, self.out_op]):
- self.self_cov = (self.cov(self.x_in, self.x_in) *
- self.task_cov(self.weights, self.weights) +
- tf.eye(tf.shape(self.x_in)[0], dtype=tf.float64) * alpha)
-
- self.chol = tf.cholesky(self.self_cov)
- self.kinv = tf.cholesky_solve(self.chol, tf.eye(tf.shape(self.x_in)[0],
- dtype=tf.float64))
-
- self.input_inv = tf.Variable(
- tf.eye(self.hparams.batch_size, dtype=tf.float64),
- validate_shape=False,
- trainable=False)
- self.input_cov_op = tf.assign(self.input_inv, self.kinv,
- validate_shape=False)
-
- # Log determinant by taking the singular values along the diagonal
- # of self.chol
- with tf.control_dependencies([self.input_cov_op]):
- logdet = 2.0 * tf.reduce_sum(tf.log(tf.diag_part(self.chol) + 1e-16))
-
- # Log Marginal likelihood
- self.marginal_ll = -tf.reduce_sum(-0.5 * tf.matmul(
- tf.transpose(y_normed), tf.matmul(self.kinv, y_normed)) - 0.5 * logdet -
- 0.5 * self.n * np.log(2 * np.pi))
-
- zero = tf.cast(0., dtype=tf.float64)
- one = tf.cast(1., dtype=tf.float64)
- standard_normal = tfd.Normal(loc=zero, scale=one)
-
- # Loss is marginal likelihood and priors
- self.loss = tf.reduce_sum(
- self.marginal_ll -
- (standard_normal.log_prob(self.amplitude) +
- standard_normal.log_prob(tf.exp(self.noise)) +
- standard_normal.log_prob(self.amplitude_linear) +
- tfd.Normal(loc=zero, scale=one * 10.).log_prob(
- self.task_vectors))
- )
-
- # Optimizer for hyperparameters
- optimizer = tf.train.AdamOptimizer(learning_rate=self.hparams.lr)
- vars_to_optimize = [
- self.amplitude, self.length_scales, self.length_scales_lin,
- self.amplitude_linear, self.noise, self.input_mean
- ]
-
- if self.learn_embeddings:
- vars_to_optimize.append(self.task_vectors)
- grads = optimizer.compute_gradients(self.loss, vars_to_optimize)
- self.train_op = optimizer.apply_gradients(grads,
- global_step=self.global_step)
-
- # Predictions for test data
- self.y_mean, self.y_pred = self.posterior_mean_and_sample(self.x)
-
- # create tensorboard metrics
- self.create_summaries()
- self.summary_writer = tf.summary.FileWriter("{}/graph_{}".format(
- FLAGS.logdir, self.name), self.sess.graph)
- self.check = tf.add_check_numerics_ops()
-
- def posterior_mean_and_sample(self, candidates):
- """Draw samples for test predictions.
-
- Given a Tensor of 'candidates' inputs, returns samples from the posterior
- and the posterior mean prediction for those inputs.
-
- Args:
- candidates: A (num-examples x num-dims) Tensor containing the inputs for
- which to return predictions.
- Returns:
- y_mean: The posterior mean prediction given these inputs
- y_sample: A sample from the posterior of the outputs given these inputs
- """
- # Cross-covariance for test predictions
- w = tf.identity(self.weights_train)
- inds = tf.squeeze(
- tf.reshape(
- tf.tile(
- tf.reshape(tf.range(self.n_out), (self.n_out, 1)),
- (1, tf.shape(candidates)[0])), (-1, 1)))
-
- cross_cov = self.cov(tf.tile(candidates, [self.n_out, 1]), self.x_train)
- cross_task_cov = self.task_cov(tf.one_hot(inds, self.n_out), w)
- cross_cov *= cross_task_cov
-
- # Test mean prediction
- y_mean = tf.matmul(cross_cov, tf.matmul(self.input_inv, self.y_train))
-
- # Test sample predictions
- # Note this can be done much more efficiently using Kronecker products
- # if all tasks are fully observed (which we won't assume)
- test_cov = (
- self.cov(tf.tile(candidates, [self.n_out, 1]),
- tf.tile(candidates, [self.n_out, 1])) *
- self.task_cov(tf.one_hot(inds, self.n_out),
- tf.one_hot(inds, self.n_out)) -
- tf.matmul(cross_cov,
- tf.matmul(self.input_inv,
- tf.transpose(cross_cov))))
-
- # Get the matrix square root through an SVD for drawing samples
- # This seems more numerically stable than the Cholesky
- s, _, v = tf.svd(test_cov, full_matrices=True)
- test_sqrt = tf.matmul(v, tf.matmul(tf.diag(s), tf.transpose(v)))
-
- y_sample = (
- tf.matmul(
- test_sqrt,
- tf.random_normal([tf.shape(test_sqrt)[0], 1], dtype=tf.float64)) +
- y_mean)
-
- y_sample = (
- tf.transpose(tf.reshape(y_sample,
- (self.n_out, -1))) * self.input_std +
- self.input_mean)
-
- return y_mean, y_sample
-
- def create_summaries(self):
- with self.graph.as_default():
- tf.summary.scalar("loss", self.loss)
- tf.summary.scalar("log_noise", self.noise)
- tf.summary.scalar("log_amp", self.amplitude)
- tf.summary.scalar("log_amp_lin", self.amplitude_linear)
- tf.summary.histogram("length_scales", self.length_scales)
- tf.summary.histogram("length_scales_lin", self.length_scales_lin)
- self.summary_op = tf.summary.merge_all()
-
- def train(self, data, num_steps):
- """Trains the GP for num_steps, using the data in 'data'.
-
- Args:
- data: ContextualDataset object that provides the data.
- num_steps: Number of minibatches to train the network for.
- """
-
- logging.info("Training %s for %d steps...", self.name, num_steps)
- for step in range(num_steps):
- numpts = min(data.num_points(None), self.max_num_points)
- if numpts >= self.max_num_points and self.keep_fixed_after_max_obs:
- x = data.contexts[:numpts, :]
- y = data.rewards[:numpts, :]
- weights = np.zeros((x.shape[0], self.n_out))
- for i, val in enumerate(data.actions[:numpts]):
- weights[i, val] = 1.0
- else:
- x, y, weights = data.get_batch_with_weights(numpts)
-
- ops = [
- self.global_step, self.summary_op, self.loss, self.noise,
- self.amplitude, self.amplitude_linear, self.length_scales,
- self.length_scales_lin, self.input_cov_op, self.input_op, self.var_op,
- self.input_w_op, self.out_op, self.train_op
- ]
-
- res = self.sess.run(ops,
- feed_dict={self.x: x,
- self.x_in: x,
- self.y: y,
- self.weights: weights,
- self.n: numpts,
- })
-
- if step % self._freq_summary == 0:
- if self._show_training:
- logging.info("step: %d, loss: %g noise: %f amp: %f amp_lin: %f",
- step, res[2], res[3], res[4], res[5])
- summary = res[1]
- global_step = res[0]
- self.summary_writer.add_summary(summary, global_step=global_step)
diff --git a/research/deep_contextual_bandits/bandits/algorithms/neural_bandit_model.py b/research/deep_contextual_bandits/bandits/algorithms/neural_bandit_model.py
deleted file mode 100644
index 99d7cd4dc8e2c35571f82bbb79ea1564a148ff5d..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/algorithms/neural_bandit_model.py
+++ /dev/null
@@ -1,220 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Define a family of neural network architectures for bandits.
-
-The network accepts different type of optimizers that could lead to different
-approximations of the posterior distribution or simply to point estimates.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-from absl import flags
-from bandits.core.bayesian_nn import BayesianNN
-
-FLAGS = flags.FLAGS
-
-
-class NeuralBanditModel(BayesianNN):
- """Implements a neural network for bandit problems."""
-
- def __init__(self, optimizer, hparams, name):
- """Saves hyper-params and builds the Tensorflow graph."""
-
- self.opt_name = optimizer
- self.name = name
- self.hparams = hparams
- self.verbose = getattr(self.hparams, "verbose", True)
- self.times_trained = 0
- self.build_model()
-
- def build_layer(self, x, num_units):
- """Builds a layer with input x; dropout and layer norm if specified."""
-
- init_s = self.hparams.init_scale
-
- layer_n = getattr(self.hparams, "layer_norm", False)
- dropout = getattr(self.hparams, "use_dropout", False)
-
- nn = tf.contrib.layers.fully_connected(
- x,
- num_units,
- activation_fn=self.hparams.activation,
- normalizer_fn=None if not layer_n else tf.contrib.layers.layer_norm,
- normalizer_params={},
- weights_initializer=tf.random_uniform_initializer(-init_s, init_s)
- )
-
- if dropout:
- nn = tf.nn.dropout(nn, self.hparams.keep_prob)
-
- return nn
-
- def forward_pass(self):
-
- init_s = self.hparams.init_scale
-
- scope_name = "prediction_{}".format(self.name)
- with tf.variable_scope(scope_name, reuse=tf.AUTO_REUSE):
- nn = self.x
- for num_units in self.hparams.layer_sizes:
- if num_units > 0:
- nn = self.build_layer(nn, num_units)
-
- y_pred = tf.layers.dense(
- nn,
- self.hparams.num_actions,
- kernel_initializer=tf.random_uniform_initializer(-init_s, init_s))
-
- return nn, y_pred
-
- def build_model(self):
- """Defines the actual NN model with fully connected layers.
-
- The loss is computed for partial feedback settings (bandits), so only
- the observed outcome is backpropagated (see weighted loss).
- Selects the optimizer and, finally, it also initializes the graph.
- """
-
- # create and store the graph corresponding to the BNN instance
- self.graph = tf.Graph()
-
- with self.graph.as_default():
-
- # create and store a new session for the graph
- self.sess = tf.Session()
-
- with tf.name_scope(self.name):
-
- self.global_step = tf.train.get_or_create_global_step()
-
- # context
- self.x = tf.placeholder(
- shape=[None, self.hparams.context_dim],
- dtype=tf.float32,
- name="{}_x".format(self.name))
-
- # reward vector
- self.y = tf.placeholder(
- shape=[None, self.hparams.num_actions],
- dtype=tf.float32,
- name="{}_y".format(self.name))
-
- # weights (1 for selected action, 0 otherwise)
- self.weights = tf.placeholder(
- shape=[None, self.hparams.num_actions],
- dtype=tf.float32,
- name="{}_w".format(self.name))
-
- # with tf.variable_scope("prediction_{}".format(self.name)):
- self.nn, self.y_pred = self.forward_pass()
- self.loss = tf.squared_difference(self.y_pred, self.y)
- self.weighted_loss = tf.multiply(self.weights, self.loss)
- self.cost = tf.reduce_sum(self.weighted_loss) / self.hparams.batch_size
-
- if self.hparams.activate_decay:
- self.lr = tf.train.inverse_time_decay(
- self.hparams.initial_lr, self.global_step,
- 1, self.hparams.lr_decay_rate)
- else:
- self.lr = tf.Variable(self.hparams.initial_lr, trainable=False)
-
- # create tensorboard metrics
- self.create_summaries()
- self.summary_writer = tf.summary.FileWriter(
- "{}/graph_{}".format(FLAGS.logdir, self.name), self.sess.graph)
-
- tvars = tf.trainable_variables()
- grads, _ = tf.clip_by_global_norm(
- tf.gradients(self.cost, tvars), self.hparams.max_grad_norm)
-
- self.optimizer = self.select_optimizer()
-
- self.train_op = self.optimizer.apply_gradients(
- zip(grads, tvars), global_step=self.global_step)
-
- self.init = tf.global_variables_initializer()
-
- self.initialize_graph()
-
- def initialize_graph(self):
- """Initializes all variables."""
-
- with self.graph.as_default():
- if self.verbose:
- print("Initializing model {}.".format(self.name))
- self.sess.run(self.init)
-
- def assign_lr(self):
- """Resets the learning rate in dynamic schedules for subsequent trainings.
-
- In bandits settings, we do expand our dataset over time. Then, we need to
- re-train the network with the new data. The algorithms that do not keep
- the step constant, can reset it at the start of each *training* process.
- """
-
- decay_steps = 1
- if self.hparams.activate_decay:
- current_gs = self.sess.run(self.global_step)
- with self.graph.as_default():
- self.lr = tf.train.inverse_time_decay(self.hparams.initial_lr,
- self.global_step - current_gs,
- decay_steps,
- self.hparams.lr_decay_rate)
-
- def select_optimizer(self):
- """Selects optimizer. To be extended (SGLD, KFAC, etc)."""
- return tf.train.RMSPropOptimizer(self.lr)
-
- def create_summaries(self):
- """Defines summaries including mean loss, learning rate, and global step."""
-
- with self.graph.as_default():
- with tf.name_scope(self.name + "_summaries"):
- tf.summary.scalar("cost", self.cost)
- tf.summary.scalar("lr", self.lr)
- tf.summary.scalar("global_step", self.global_step)
- self.summary_op = tf.summary.merge_all()
-
- def train(self, data, num_steps):
- """Trains the network for num_steps, using the provided data.
-
- Args:
- data: ContextualDataset object that provides the data.
- num_steps: Number of minibatches to train the network for.
- """
-
- if self.verbose:
- print("Training {} for {} steps...".format(self.name, num_steps))
-
- with self.graph.as_default():
-
- for step in range(num_steps):
- x, y, w = data.get_batch_with_weights(self.hparams.batch_size)
- _, cost, summary, lr = self.sess.run(
- [self.train_op, self.cost, self.summary_op, self.lr],
- feed_dict={self.x: x, self.y: y, self.weights: w})
-
- if step % self.hparams.freq_summary == 0:
- if self.hparams.show_training:
- print("{} | step: {}, lr: {}, loss: {}".format(
- self.name, step, lr, cost))
- self.summary_writer.add_summary(summary, step)
-
- self.times_trained += 1
diff --git a/research/deep_contextual_bandits/bandits/algorithms/neural_linear_sampling.py b/research/deep_contextual_bandits/bandits/algorithms/neural_linear_sampling.py
deleted file mode 100644
index 43fc551614b49ad34538aa64090bcda5f823a60f..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/algorithms/neural_linear_sampling.py
+++ /dev/null
@@ -1,180 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Thompson Sampling with linear posterior over a learnt deep representation."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-from scipy.stats import invgamma
-
-from bandits.core.bandit_algorithm import BanditAlgorithm
-from bandits.core.contextual_dataset import ContextualDataset
-from bandits.algorithms.neural_bandit_model import NeuralBanditModel
-
-
-class NeuralLinearPosteriorSampling(BanditAlgorithm):
- """Full Bayesian linear regression on the last layer of a deep neural net."""
-
- def __init__(self, name, hparams, optimizer='RMS'):
-
- self.name = name
- self.hparams = hparams
- self.latent_dim = self.hparams.layer_sizes[-1]
-
- # Gaussian prior for each beta_i
- self._lambda_prior = self.hparams.lambda_prior
-
- self.mu = [
- np.zeros(self.latent_dim)
- for _ in range(self.hparams.num_actions)
- ]
-
- self.cov = [(1.0 / self.lambda_prior) * np.eye(self.latent_dim)
- for _ in range(self.hparams.num_actions)]
-
- self.precision = [
- self.lambda_prior * np.eye(self.latent_dim)
- for _ in range(self.hparams.num_actions)
- ]
-
- # Inverse Gamma prior for each sigma2_i
- self._a0 = self.hparams.a0
- self._b0 = self.hparams.b0
-
- self.a = [self._a0 for _ in range(self.hparams.num_actions)]
- self.b = [self._b0 for _ in range(self.hparams.num_actions)]
-
- # Regression and NN Update Frequency
- self.update_freq_lr = hparams.training_freq
- self.update_freq_nn = hparams.training_freq_network
-
- self.t = 0
- self.optimizer_n = optimizer
-
- self.num_epochs = hparams.training_epochs
- self.data_h = ContextualDataset(hparams.context_dim,
- hparams.num_actions,
- intercept=False)
- self.latent_h = ContextualDataset(self.latent_dim,
- hparams.num_actions,
- intercept=False)
- self.bnn = NeuralBanditModel(optimizer, hparams, '{}-bnn'.format(name))
-
- def action(self, context):
- """Samples beta's from posterior, and chooses best action accordingly."""
-
- # Round robin until each action has been selected "initial_pulls" times
- if self.t < self.hparams.num_actions * self.hparams.initial_pulls:
- return self.t % self.hparams.num_actions
-
- # Sample sigma2, and beta conditional on sigma2
- sigma2_s = [
- self.b[i] * invgamma.rvs(self.a[i])
- for i in range(self.hparams.num_actions)
- ]
-
- try:
- beta_s = [
- np.random.multivariate_normal(self.mu[i], sigma2_s[i] * self.cov[i])
- for i in range(self.hparams.num_actions)
- ]
- except np.linalg.LinAlgError as e:
- # Sampling could fail if covariance is not positive definite
- print('Exception when sampling for {}.'.format(self.name))
- print('Details: {} | {}.'.format(e.message, e.args))
- d = self.latent_dim
- beta_s = [
- np.random.multivariate_normal(np.zeros((d)), np.eye(d))
- for i in range(self.hparams.num_actions)
- ]
-
- # Compute last-layer representation for the current context
- with self.bnn.graph.as_default():
- c = context.reshape((1, self.hparams.context_dim))
- z_context = self.bnn.sess.run(self.bnn.nn, feed_dict={self.bnn.x: c})
-
- # Apply Thompson Sampling to last-layer representation
- vals = [
- np.dot(beta_s[i], z_context.T) for i in range(self.hparams.num_actions)
- ]
- return np.argmax(vals)
-
- def update(self, context, action, reward):
- """Updates the posterior using linear bayesian regression formula."""
-
- self.t += 1
- self.data_h.add(context, action, reward)
- c = context.reshape((1, self.hparams.context_dim))
- z_context = self.bnn.sess.run(self.bnn.nn, feed_dict={self.bnn.x: c})
- self.latent_h.add(z_context, action, reward)
-
- # Retrain the network on the original data (data_h)
- if self.t % self.update_freq_nn == 0:
-
- if self.hparams.reset_lr:
- self.bnn.assign_lr()
- self.bnn.train(self.data_h, self.num_epochs)
-
- # Update the latent representation of every datapoint collected so far
- new_z = self.bnn.sess.run(self.bnn.nn,
- feed_dict={self.bnn.x: self.data_h.contexts})
- self.latent_h.replace_data(contexts=new_z)
-
- # Update the Bayesian Linear Regression
- if self.t % self.update_freq_lr == 0:
-
- # Find all the actions to update
- actions_to_update = self.latent_h.actions[:-self.update_freq_lr]
-
- for action_v in np.unique(actions_to_update):
-
- # Update action posterior with formulas: \beta | z,y ~ N(mu_q, cov_q)
- z, y = self.latent_h.get_data(action_v)
-
- # The algorithm could be improved with sequential formulas (cheaper)
- s = np.dot(z.T, z)
-
- # Some terms are removed as we assume prior mu_0 = 0.
- precision_a = s + self.lambda_prior * np.eye(self.latent_dim)
- cov_a = np.linalg.inv(precision_a)
- mu_a = np.dot(cov_a, np.dot(z.T, y))
-
- # Inverse Gamma posterior update
- a_post = self.a0 + z.shape[0] / 2.0
- b_upd = 0.5 * np.dot(y.T, y)
- b_upd -= 0.5 * np.dot(mu_a.T, np.dot(precision_a, mu_a))
- b_post = self.b0 + b_upd
-
- # Store new posterior distributions
- self.mu[action_v] = mu_a
- self.cov[action_v] = cov_a
- self.precision[action_v] = precision_a
- self.a[action_v] = a_post
- self.b[action_v] = b_post
-
- @property
- def a0(self):
- return self._a0
-
- @property
- def b0(self):
- return self._b0
-
- @property
- def lambda_prior(self):
- return self._lambda_prior
diff --git a/research/deep_contextual_bandits/bandits/algorithms/parameter_noise_sampling.py b/research/deep_contextual_bandits/bandits/algorithms/parameter_noise_sampling.py
deleted file mode 100644
index 19944ad577372b6971f03f1117fc33d5a2a276b1..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/algorithms/parameter_noise_sampling.py
+++ /dev/null
@@ -1,187 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Contextual algorithm based on Thompson Sampling + direct noise injection."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-from scipy.special import logsumexp
-import tensorflow as tf
-
-from absl import flags
-
-from bandits.core.bandit_algorithm import BanditAlgorithm
-from bandits.core.contextual_dataset import ContextualDataset
-from bandits.algorithms.neural_bandit_model import NeuralBanditModel
-
-FLAGS = flags.FLAGS
-
-
-class ParameterNoiseSampling(BanditAlgorithm):
- """Parameter Noise Sampling algorithm based on adding noise to net params.
-
- Described in https://arxiv.org/abs/1706.01905
- """
-
- def __init__(self, name, hparams):
- """Creates the algorithm, and sets up the adaptive Gaussian noise."""
-
- self.name = name
- self.hparams = hparams
- self.verbose = getattr(self.hparams, 'verbose', True)
- self.noise_std = getattr(self.hparams, 'noise_std', 0.005)
- self.eps = getattr(self.hparams, 'eps', 0.05)
- self.d_samples = getattr(self.hparams, 'd_samples', 300)
- self.optimizer = getattr(self.hparams, 'optimizer', 'RMS')
-
- # keep track of noise heuristic statistics
- self.std_h = [self.noise_std]
- self.eps_h = [self.eps]
- self.kl_h = []
- self.t = 0
-
- self.freq_update = hparams.training_freq
- self.num_epochs = hparams.training_epochs
-
- self.data_h = ContextualDataset(hparams.context_dim, hparams.num_actions,
- hparams.buffer_s)
- self.bnn = NeuralBanditModel(self.optimizer, hparams, '{}-bnn'.format(name))
-
- with self.bnn.graph.as_default():
-
- # noise-injection std placeholder
- self.bnn.noise_std_ph = tf.placeholder(tf.float32, shape=())
-
- # create noise corruption op; adds noise to all weights
- tvars = tf.trainable_variables()
- self.bnn.noisy_grads = [
- tf.random_normal(v.get_shape(), 0, self.bnn.noise_std_ph)
- for v in tvars
- ]
-
- # add noise to all params, then compute prediction, then subtract.
- with tf.control_dependencies(self.bnn.noisy_grads):
- self.bnn.noise_add_ops = [
- tvars[i].assign_add(n) for i, n in enumerate(self.bnn.noisy_grads)
- ]
- with tf.control_dependencies(self.bnn.noise_add_ops):
- # we force the prediction for 'y' to be recomputed after adding noise
- self.bnn.noisy_nn, self.bnn.noisy_pred_val = self.bnn.forward_pass()
-
- self.bnn.noisy_pred = tf.identity(self.bnn.noisy_pred_val)
- with tf.control_dependencies([tf.identity(self.bnn.noisy_pred)]):
- self.bnn.noise_sub_ops = [
- tvars[i].assign_add(-n)
- for i, n in enumerate(self.bnn.noisy_grads)
- ]
-
- def action(self, context):
- """Selects action based on Thompson Sampling *after* adding noise."""
-
- if self.t < self.hparams.num_actions * self.hparams.initial_pulls:
- # round robin until each action has been taken "initial_pulls" times
- return self.t % self.hparams.num_actions
-
- with self.bnn.graph.as_default():
- # run noise prediction op to choose action, and subtract noise op after.
- c = context.reshape((1, self.hparams.context_dim))
- output, _ = self.bnn.sess.run(
- [self.bnn.noisy_pred, self.bnn.noise_sub_ops],
- feed_dict={self.bnn.x: c,
- self.bnn.noise_std_ph: self.noise_std})
- return np.argmax(output)
-
- def update(self, context, action, reward):
- """Updates the data buffer, and re-trains the BNN and noise level."""
-
- self.t += 1
- self.data_h.add(context, action, reward)
-
- if self.t % self.freq_update == 0:
- self.bnn.train(self.data_h, self.num_epochs)
- self.update_noise()
-
- def update_noise(self):
- """Increase noise if distance btw original and corrupted distrib small."""
-
- kl = self.compute_distance()
- delta = -np.log1p(- self.eps + self.eps / self.hparams.num_actions)
-
- if kl < delta:
- self.noise_std *= 1.01
- else:
- self.noise_std /= 1.01
-
- self.eps *= 0.99
-
- if self.verbose:
- print('Update eps={} | kl={} | std={} | delta={} | increase={}.'.format(
- self.eps, kl, self.noise_std, delta, kl < delta))
-
- # store noise-injection statistics for inspection: std, KL, eps.
- self.std_h.append(self.noise_std)
- self.kl_h.append(kl)
- self.eps_h.append(self.eps)
-
- def compute_distance(self):
- """Computes empirical KL for original and corrupted output distributions."""
-
- random_inputs, _ = self.data_h.get_batch(self.d_samples)
- y_model = self.bnn.sess.run(
- self.bnn.y_pred,
- feed_dict={
- self.bnn.x: random_inputs,
- self.bnn.noise_std_ph: self.noise_std
- })
- y_noisy, _ = self.bnn.sess.run(
- [self.bnn.noisy_pred, self.bnn.noise_sub_ops],
- feed_dict={
- self.bnn.x: random_inputs,
- self.bnn.noise_std_ph: self.noise_std
- })
-
- if self.verbose:
- # display how often original & perturbed models propose different actions
- s = np.sum([np.argmax(y_model[i, :]) == np.argmax(y_noisy[i, :])
- for i in range(y_model.shape[0])])
- print('{} | % of agreement btw original / corrupted actions: {}.'.format(
- self.name, s / self.d_samples))
-
- kl = self.compute_kl_with_logits(y_model, y_noisy)
- return kl
-
- def compute_kl_with_logits(self, logits1, logits2):
- """Computes KL from logits samples from two distributions."""
-
- def exp_times_diff(a, b):
- return np.multiply(np.exp(a), a - b)
-
- logsumexp1 = logsumexp(logits1, axis=1)
- logsumexp2 = logsumexp(logits2, axis=1)
- logsumexp_diff = logsumexp2 - logsumexp1
-
- exp_diff = exp_times_diff(logits1, logits2)
- exp_diff = np.sum(exp_diff, axis=1)
-
- inv_exp_sum = np.sum(np.exp(logits1), axis=1)
- term1 = np.divide(exp_diff, inv_exp_sum)
-
- kl = term1 + logsumexp_diff
- kl = np.maximum(kl, 0.0)
- kl = np.nan_to_num(kl)
- return np.mean(kl)
diff --git a/research/deep_contextual_bandits/bandits/algorithms/posterior_bnn_sampling.py b/research/deep_contextual_bandits/bandits/algorithms/posterior_bnn_sampling.py
deleted file mode 100644
index 0f0c5d365a3a3e48006fe6b4e7e47ab73ea756cf..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/algorithms/posterior_bnn_sampling.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Contextual bandit algorithm based on Thompson Sampling and a Bayesian NN."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-
-from bandits.core.bandit_algorithm import BanditAlgorithm
-from bandits.algorithms.bb_alpha_divergence_model import BBAlphaDivergence
-from bandits.algorithms.bf_variational_neural_bandit_model import BfVariationalNeuralBanditModel
-from bandits.core.contextual_dataset import ContextualDataset
-from bandits.algorithms.multitask_gp import MultitaskGP
-from bandits.algorithms.neural_bandit_model import NeuralBanditModel
-from bandits.algorithms.variational_neural_bandit_model import VariationalNeuralBanditModel
-
-
-class PosteriorBNNSampling(BanditAlgorithm):
- """Posterior Sampling algorithm based on a Bayesian neural network."""
-
- def __init__(self, name, hparams, bnn_model='RMSProp'):
- """Creates a PosteriorBNNSampling object based on a specific optimizer.
-
- The algorithm has two basic tools: an Approx BNN and a Contextual Dataset.
- The Bayesian Network keeps the posterior based on the optimizer iterations.
-
- Args:
- name: Name of the algorithm.
- hparams: Hyper-parameters of the algorithm.
- bnn_model: Type of BNN. By default RMSProp (point estimate).
- """
-
- self.name = name
- self.hparams = hparams
- self.optimizer_n = hparams.optimizer
-
- self.training_freq = hparams.training_freq
- self.training_epochs = hparams.training_epochs
- self.t = 0
- self.data_h = ContextualDataset(hparams.context_dim, hparams.num_actions,
- hparams.buffer_s)
-
- # to be extended with more BNNs (BB alpha-div, GPs, SGFS, constSGD...)
- bnn_name = '{}-bnn'.format(name)
- if bnn_model == 'Variational':
- self.bnn = VariationalNeuralBanditModel(hparams, bnn_name)
- elif bnn_model == 'AlphaDiv':
- self.bnn = BBAlphaDivergence(hparams, bnn_name)
- elif bnn_model == 'Variational_BF':
- self.bnn = BfVariationalNeuralBanditModel(hparams, bnn_name)
- elif bnn_model == 'GP':
- self.bnn = MultitaskGP(hparams)
- else:
- self.bnn = NeuralBanditModel(self.optimizer_n, hparams, bnn_name)
-
- def action(self, context):
- """Selects action for context based on Thompson Sampling using the BNN."""
-
- if self.t < self.hparams.num_actions * self.hparams.initial_pulls:
- # round robin until each action has been taken "initial_pulls" times
- return self.t % self.hparams.num_actions
-
- with self.bnn.graph.as_default():
- c = context.reshape((1, self.hparams.context_dim))
- output = self.bnn.sess.run(self.bnn.y_pred, feed_dict={self.bnn.x: c})
- return np.argmax(output)
-
- def update(self, context, action, reward):
- """Updates data buffer, and re-trains the BNN every training_freq steps."""
-
- self.t += 1
- self.data_h.add(context, action, reward)
-
- if self.t % self.training_freq == 0:
- if self.hparams.reset_lr:
- self.bnn.assign_lr()
- self.bnn.train(self.data_h, self.training_epochs)
diff --git a/research/deep_contextual_bandits/bandits/algorithms/uniform_sampling.py b/research/deep_contextual_bandits/bandits/algorithms/uniform_sampling.py
deleted file mode 100644
index 15c073fbe89da4e9aef595c8772ceaa3667e1952..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/algorithms/uniform_sampling.py
+++ /dev/null
@@ -1,43 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Contextual bandit algorithm that selects an action uniformly at random."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-
-from bandits.core.bandit_algorithm import BanditAlgorithm
-
-
-class UniformSampling(BanditAlgorithm):
- """Defines a baseline; returns one action uniformly at random."""
-
- def __init__(self, name, hparams):
- """Creates a UniformSampling object.
-
- Args:
- name: Name of the algorithm.
- hparams: Hyper-parameters, including the number of arms (num_actions).
- """
-
- self.name = name
- self.hparams = hparams
-
- def action(self, context):
- """Selects an action uniformly at random."""
- return np.random.choice(range(self.hparams.num_actions))
diff --git a/research/deep_contextual_bandits/bandits/algorithms/variational_neural_bandit_model.py b/research/deep_contextual_bandits/bandits/algorithms/variational_neural_bandit_model.py
deleted file mode 100644
index 7700c08ba9f7861aac522ba6da9f7371b5e203af..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/algorithms/variational_neural_bandit_model.py
+++ /dev/null
@@ -1,346 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Bayesian NN using factorized VI (Bayes By Backprop. Blundell et al. 2014).
-
-See https://arxiv.org/abs/1505.05424 for details.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import tensorflow as tf
-
-from absl import flags
-from bandits.core.bayesian_nn import BayesianNN
-
-FLAGS = flags.FLAGS
-
-
-def log_gaussian(x, mu, sigma, reduce_sum=True):
- """Returns log Gaussian pdf."""
- res = (-0.5 * np.log(2 * np.pi) - tf.log(sigma) - tf.square(x - mu) /
- (2 * tf.square(sigma)))
- if reduce_sum:
- return tf.reduce_sum(res)
- else:
- return res
-
-
-def analytic_kl(mu_1, sigma_1, mu_2, sigma_2):
- """KL for two Gaussian distributions with diagonal covariance matrix."""
- sigma_1_sq = tf.square(sigma_1)
- sigma_2_sq = tf.square(sigma_2)
-
- t1 = tf.square(mu_1 - mu_2) / (2. * sigma_2_sq)
- t2 = (sigma_1_sq/sigma_2_sq - 1. - tf.log(sigma_1_sq) + tf.log(sigma_2_sq))/2.
- return tf.reduce_sum(t1 + t2)
-
-
-class VariationalNeuralBanditModel(BayesianNN):
- """Implements an approximate Bayesian NN using Variational Inference."""
-
- def __init__(self, hparams, name="BBBNN"):
-
- self.name = name
- self.hparams = hparams
-
- self.n_in = self.hparams.context_dim
- self.n_out = self.hparams.num_actions
- self.layers = self.hparams.layer_sizes
- self.init_scale = self.hparams.init_scale
- self.f_num_points = None
- if "f_num_points" in hparams:
- self.f_num_points = self.hparams.f_num_points
-
- self.cleared_times_trained = self.hparams.cleared_times_trained
- self.initial_training_steps = self.hparams.initial_training_steps
- self.training_schedule = np.linspace(self.initial_training_steps,
- self.hparams.training_epochs,
- self.cleared_times_trained)
- self.verbose = getattr(self.hparams, "verbose", True)
-
- self.weights_m = {}
- self.weights_std = {}
- self.biases_m = {}
- self.biases_std = {}
-
- self.times_trained = 0
-
- if self.hparams.use_sigma_exp_transform:
- self.sigma_transform = tf.exp
- self.inverse_sigma_transform = np.log
- else:
- self.sigma_transform = tf.nn.softplus
- self.inverse_sigma_transform = lambda y: y + np.log(1. - np.exp(-y))
-
- # Whether to use the local reparameterization trick to compute the loss.
- # See details in https://arxiv.org/abs/1506.02557
- self.use_local_reparameterization = True
-
- self.build_graph()
-
- def build_mu_variable(self, shape):
- """Returns a mean variable initialized as N(0, 0.05)."""
- return tf.Variable(tf.random_normal(shape, 0.0, 0.05))
-
- def build_sigma_variable(self, shape, init=-5.):
- """Returns a sigma variable initialized as N(init, 0.05)."""
- # Initialize sigma to be very small initially to encourage MAP opt first
- return tf.Variable(tf.random_normal(shape, init, 0.05))
-
- def build_layer(self, input_x, input_x_local, shape,
- layer_id, activation_fn=tf.nn.relu):
- """Builds a variational layer, and computes KL term.
-
- Args:
- input_x: Input to the variational layer.
- input_x_local: Input when the local reparameterization trick was applied.
- shape: [number_inputs, number_outputs] for the layer.
- layer_id: Number of layer in the architecture.
- activation_fn: Activation function to apply.
-
- Returns:
- output_h: Output of the variational layer.
- output_h_local: Output when local reparameterization trick was applied.
- neg_kl: Negative KL term for the layer.
- """
-
- w_mu = self.build_mu_variable(shape)
- w_sigma = self.sigma_transform(self.build_sigma_variable(shape))
- w_noise = tf.random_normal(shape)
- w = w_mu + w_sigma * w_noise
-
- b_mu = self.build_mu_variable([1, shape[1]])
- b_sigma = self.sigma_transform(self.build_sigma_variable([1, shape[1]]))
- b = b_mu
-
- # Store means and stds
- self.weights_m[layer_id] = w_mu
- self.weights_std[layer_id] = w_sigma
- self.biases_m[layer_id] = b_mu
- self.biases_std[layer_id] = b_sigma
-
- # Create outputs
- output_h = activation_fn(tf.matmul(input_x, w) + b)
-
- if self.use_local_reparameterization:
- # Use analytic KL divergence wrt the prior
- neg_kl = -analytic_kl(w_mu, w_sigma,
- 0., tf.to_float(np.sqrt(2./shape[0])))
- else:
- # Create empirical KL loss terms
- log_p = log_gaussian(w, 0., tf.to_float(np.sqrt(2./shape[0])))
- log_q = log_gaussian(w, tf.stop_gradient(w_mu), tf.stop_gradient(w_sigma))
- neg_kl = log_p - log_q
-
- # Apply local reparameterization trick: sample activations pre nonlinearity
- m_h = tf.matmul(input_x_local, w_mu) + b
- v_h = tf.matmul(tf.square(input_x_local), tf.square(w_sigma))
- output_h_local = m_h + tf.sqrt(v_h + 1e-6) * tf.random_normal(tf.shape(v_h))
- output_h_local = activation_fn(output_h_local)
-
- return output_h, output_h_local, neg_kl
-
- def build_action_noise(self):
- """Defines a model for additive noise per action, and its KL term."""
-
- # Define mean and std variables (log-normal dist) for each action.
- noise_sigma_mu = (self.build_mu_variable([1, self.n_out])
- + self.inverse_sigma_transform(self.hparams.noise_sigma))
- noise_sigma_sigma = self.sigma_transform(
- self.build_sigma_variable([1, self.n_out]))
-
- pre_noise_sigma = (noise_sigma_mu
- + tf.random_normal([1, self.n_out]) * noise_sigma_sigma)
- self.noise_sigma = self.sigma_transform(pre_noise_sigma)
-
- # Compute KL for additive noise sigma terms.
- if getattr(self.hparams, "infer_noise_sigma", False):
- neg_kl_term = log_gaussian(
- pre_noise_sigma,
- self.inverse_sigma_transform(self.hparams.noise_sigma),
- self.hparams.prior_sigma
- )
- neg_kl_term -= log_gaussian(pre_noise_sigma,
- noise_sigma_mu,
- noise_sigma_sigma)
- else:
- neg_kl_term = 0.
-
- return neg_kl_term
-
- def build_model(self, activation_fn=tf.nn.relu):
- """Defines the actual NN model with fully connected layers.
-
- The loss is computed for partial feedback settings (bandits), so only
- the observed outcome is backpropagated (see weighted loss).
- Selects the optimizer and, finally, it also initializes the graph.
-
- Args:
- activation_fn: the activation function used in the nn layers.
- """
-
- if self.verbose:
- print("Initializing model {}.".format(self.name))
- neg_kl_term, l_number = 0, 0
- use_local_reparameterization = self.use_local_reparameterization
-
- # Compute model additive noise for each action with log-normal distribution
- neg_kl_term += self.build_action_noise()
-
- # Build network.
- input_x = self.x
- input_local = self.x
- n_in = self.n_in
-
- for l_number, n_nodes in enumerate(self.layers):
- if n_nodes > 0:
- h, h_local, neg_kl = self.build_layer(input_x, input_local,
- [n_in, n_nodes], l_number)
-
- neg_kl_term += neg_kl
- input_x, input_local = h, h_local
- n_in = n_nodes
-
- # Create last linear layer
- h, h_local, neg_kl = self.build_layer(input_x, input_local,
- [n_in, self.n_out],
- l_number + 1,
- activation_fn=lambda x: x)
- neg_kl_term += neg_kl
-
- self.y_pred = h
- self.y_pred_local = h_local
-
- # Compute log likelihood (with learned or fixed noise level)
- if getattr(self.hparams, "infer_noise_sigma", False):
- log_likelihood = log_gaussian(
- self.y, self.y_pred_local, self.noise_sigma, reduce_sum=False)
- else:
- y_hat = self.y_pred_local if use_local_reparameterization else self.y_pred
- log_likelihood = log_gaussian(
- self.y, y_hat, self.hparams.noise_sigma, reduce_sum=False)
-
- # Only take into account observed outcomes (bandits setting)
- batch_size = tf.to_float(tf.shape(self.x)[0])
- weighted_log_likelihood = tf.reduce_sum(
- log_likelihood * self.weights) / batch_size
-
- # The objective is 1/n * (\sum_i log_like_i - KL); neg_kl_term estimates -KL
- elbo = weighted_log_likelihood + (neg_kl_term / self.n)
-
- self.loss = -elbo
- self.global_step = tf.train.get_or_create_global_step()
- self.train_op = tf.train.AdamOptimizer(self.hparams.initial_lr).minimize(
- self.loss, global_step=self.global_step)
-
- # Create tensorboard metrics
- self.create_summaries()
- self.summary_writer = tf.summary.FileWriter(
- "{}/graph_{}".format(FLAGS.logdir, self.name), self.sess.graph)
-
- def build_graph(self):
- """Defines graph, session, placeholders, and model.
-
- Placeholders are: n (size of the dataset), x and y (context and observed
- reward for each action), and weights (one-hot encoding of selected action
- for each context, i.e., only possibly non-zero element in each y).
- """
-
- self.graph = tf.Graph()
- with self.graph.as_default():
-
- self.sess = tf.Session()
-
- self.n = tf.placeholder(shape=[], dtype=tf.float32)
-
- self.x = tf.placeholder(shape=[None, self.n_in], dtype=tf.float32)
- self.y = tf.placeholder(shape=[None, self.n_out], dtype=tf.float32)
- self.weights = tf.placeholder(shape=[None, self.n_out], dtype=tf.float32)
-
- self.build_model()
- self.sess.run(tf.global_variables_initializer())
-
- def create_summaries(self):
- """Defines summaries including mean loss, and global step."""
-
- with self.graph.as_default():
- with tf.name_scope(self.name + "_summaries"):
- tf.summary.scalar("loss", self.loss)
- tf.summary.scalar("global_step", self.global_step)
- self.summary_op = tf.summary.merge_all()
-
- def assign_lr(self):
- """Resets the learning rate in dynamic schedules for subsequent trainings.
-
- In bandits settings, we do expand our dataset over time. Then, we need to
- re-train the network with the new data. The algorithms that do not keep
- the step constant, can reset it at the start of each *training* process.
- """
-
- decay_steps = 1
- if self.hparams.activate_decay:
- current_gs = self.sess.run(self.global_step)
- with self.graph.as_default():
- self.lr = tf.train.inverse_time_decay(self.hparams.initial_lr,
- self.global_step - current_gs,
- decay_steps,
- self.hparams.lr_decay_rate)
-
- def train(self, data, num_steps):
- """Trains the BNN for num_steps, using the data in 'data'.
-
- Args:
- data: ContextualDataset object that provides the data.
- num_steps: Number of minibatches to train the network for.
-
- Returns:
- losses: Loss history during training.
- """
-
- if self.times_trained < self.cleared_times_trained:
- num_steps = int(self.training_schedule[self.times_trained])
- self.times_trained += 1
-
- losses = []
-
- with self.graph.as_default():
-
- if self.verbose:
- print("Training {} for {} steps...".format(self.name, num_steps))
-
- for step in range(num_steps):
- x, y, weights = data.get_batch_with_weights(self.hparams.batch_size)
- _, summary, global_step, loss = self.sess.run(
- [self.train_op, self.summary_op, self.global_step, self.loss],
- feed_dict={
- self.x: x,
- self.y: y,
- self.weights: weights,
- self.n: data.num_points(self.f_num_points),
- })
-
- losses.append(loss)
-
- if step % self.hparams.freq_summary == 0:
- if self.hparams.show_training:
- print("{} | step: {}, loss: {}".format(
- self.name, global_step, loss))
- self.summary_writer.add_summary(summary, global_step)
-
- return losses
diff --git a/research/deep_contextual_bandits/bandits/core/bandit_algorithm.py b/research/deep_contextual_bandits/bandits/core/bandit_algorithm.py
deleted file mode 100644
index cae4e1676a865d538fa41936feb9118283b92a2c..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/core/bandit_algorithm.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Define the abstract class for contextual bandit algorithms."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-class BanditAlgorithm(object):
- """A bandit algorithm must be able to do two basic operations.
-
- 1. Choose an action given a context.
- 2. Update its internal model given a triple (context, played action, reward).
- """
-
- def action(self, context):
- pass
-
- def update(self, context, action, reward):
- pass
diff --git a/research/deep_contextual_bandits/bandits/core/bayesian_nn.py b/research/deep_contextual_bandits/bandits/core/bayesian_nn.py
deleted file mode 100644
index 310961591317f8c9ff958a5178e81e0422385baf..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/core/bayesian_nn.py
+++ /dev/null
@@ -1,36 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Define the abstract class for Bayesian Neural Networks."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-class BayesianNN(object):
- """A Bayesian neural network keeps a distribution over neural nets."""
-
- def __init__(self, optimizer):
- pass
-
- def build_model(self):
- pass
-
- def train(self, data):
- pass
-
- def sample(self, steps):
- pass
diff --git a/research/deep_contextual_bandits/bandits/core/contextual_bandit.py b/research/deep_contextual_bandits/bandits/core/contextual_bandit.py
deleted file mode 100644
index 98467378953b9f3e38057be8a0068fdbc7b59a84..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/core/contextual_bandit.py
+++ /dev/null
@@ -1,125 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Define a contextual bandit from which we can sample and compute rewards.
-
-We can feed the data, sample a context, its reward for a specific action, and
-also the optimal action for a given context.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-
-
-def run_contextual_bandit(context_dim, num_actions, dataset, algos):
- """Run a contextual bandit problem on a set of algorithms.
-
- Args:
- context_dim: Dimension of the context.
- num_actions: Number of available actions.
- dataset: Matrix where every row is a context + num_actions rewards.
- algos: List of algorithms to use in the contextual bandit instance.
-
- Returns:
- h_actions: Matrix with actions: size (num_context, num_algorithms).
- h_rewards: Matrix with rewards: size (num_context, num_algorithms).
- """
-
- num_contexts = dataset.shape[0]
-
- # Create contextual bandit
- cmab = ContextualBandit(context_dim, num_actions)
- cmab.feed_data(dataset)
-
- h_actions = np.empty((0, len(algos)), float)
- h_rewards = np.empty((0, len(algos)), float)
-
- # Run the contextual bandit process
- for i in range(num_contexts):
- context = cmab.context(i)
- actions = [a.action(context) for a in algos]
- rewards = [cmab.reward(i, action) for action in actions]
-
- for j, a in enumerate(algos):
- a.update(context, actions[j], rewards[j])
-
- h_actions = np.vstack((h_actions, np.array(actions)))
- h_rewards = np.vstack((h_rewards, np.array(rewards)))
-
- return h_actions, h_rewards
-
-
-class ContextualBandit(object):
- """Implements a Contextual Bandit with d-dimensional contexts and k arms."""
-
- def __init__(self, context_dim, num_actions):
- """Creates a contextual bandit object.
-
- Args:
- context_dim: Dimension of the contexts.
- num_actions: Number of arms for the multi-armed bandit.
- """
-
- self._context_dim = context_dim
- self._num_actions = num_actions
-
- def feed_data(self, data):
- """Feeds the data (contexts + rewards) to the bandit object.
-
- Args:
- data: Numpy array with shape [n, d+k], where n is the number of contexts,
- d is the dimension of each context, and k the number of arms (rewards).
-
- Raises:
- ValueError: when data dimensions do not correspond to the object values.
- """
-
- if data.shape[1] != self.context_dim + self.num_actions:
- raise ValueError('Data dimensions do not match.')
-
- self._number_contexts = data.shape[0]
- self.data = data
- self.order = range(self.number_contexts)
-
- def reset(self):
- """Randomly shuffle the order of the contexts to deliver."""
- self.order = np.random.permutation(self.number_contexts)
-
- def context(self, number):
- """Returns the number-th context."""
- return self.data[self.order[number]][:self.context_dim]
-
- def reward(self, number, action):
- """Returns the reward for the number-th context and action."""
- return self.data[self.order[number]][self.context_dim + action]
-
- def optimal(self, number):
- """Returns the optimal action (in hindsight) for the number-th context."""
- return np.argmax(self.data[self.order[number]][self.context_dim:])
-
- @property
- def context_dim(self):
- return self._context_dim
-
- @property
- def num_actions(self):
- return self._num_actions
-
- @property
- def number_contexts(self):
- return self._number_contexts
diff --git a/research/deep_contextual_bandits/bandits/core/contextual_dataset.py b/research/deep_contextual_bandits/bandits/core/contextual_dataset.py
deleted file mode 100644
index 9fae7629c7c2ee39ab6b98ddac73876b5fca421a..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/core/contextual_dataset.py
+++ /dev/null
@@ -1,166 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Define a data buffer for contextual bandit algorithms."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-
-
-class ContextualDataset(object):
- """The buffer is able to append new data, and sample random minibatches."""
-
- def __init__(self, context_dim, num_actions, buffer_s=-1, intercept=False):
- """Creates a ContextualDataset object.
-
- The data is stored in attributes: contexts and rewards.
- The sequence of taken actions are stored in attribute actions.
-
- Args:
- context_dim: Dimension of the contexts.
- num_actions: Number of arms for the multi-armed bandit.
- buffer_s: Size of buffer for training. Only last buffer_s will be
- returned as minibatch. If buffer_s = -1, all data will be used.
- intercept: If True, it adds a constant (1.0) dimension to each context X,
- at the end.
- """
-
- self._context_dim = context_dim
- self._num_actions = num_actions
- self._contexts = None
- self._rewards = None
- self.actions = []
- self.buffer_s = buffer_s
- self.intercept = intercept
-
- def add(self, context, action, reward):
- """Adds a new triplet (context, action, reward) to the dataset.
-
- The reward for the actions that weren't played is assumed to be zero.
-
- Args:
- context: A d-dimensional vector with the context.
- action: Integer between 0 and k-1 representing the chosen arm.
- reward: Real number representing the reward for the (context, action).
- """
-
- if self.intercept:
- c = np.array(context[:])
- c = np.append(c, 1.0).reshape((1, self.context_dim + 1))
- else:
- c = np.array(context[:]).reshape((1, self.context_dim))
-
- if self.contexts is None:
- self.contexts = c
- else:
- self.contexts = np.vstack((self.contexts, c))
-
- r = np.zeros((1, self.num_actions))
- r[0, action] = reward
- if self.rewards is None:
- self.rewards = r
- else:
- self.rewards = np.vstack((self.rewards, r))
-
- self.actions.append(action)
-
- def replace_data(self, contexts=None, actions=None, rewards=None):
- if contexts is not None:
- self.contexts = contexts
- if actions is not None:
- self.actions = actions
- if rewards is not None:
- self.rewards = rewards
-
- def get_batch(self, batch_size):
- """Returns a random minibatch of (contexts, rewards) with batch_size."""
- n, _ = self.contexts.shape
- if self.buffer_s == -1:
- # use all the data
- ind = np.random.choice(range(n), batch_size)
- else:
- # use only buffer (last buffer_s observations)
- ind = np.random.choice(range(max(0, n - self.buffer_s), n), batch_size)
- return self.contexts[ind, :], self.rewards[ind, :]
-
- def get_data(self, action):
- """Returns all (context, reward) where the action was played."""
- n, _ = self.contexts.shape
- ind = np.array([i for i in range(n) if self.actions[i] == action])
- return self.contexts[ind, :], self.rewards[ind, action]
-
- def get_data_with_weights(self):
- """Returns all observations with one-hot weights for actions."""
- weights = np.zeros((self.contexts.shape[0], self.num_actions))
- a_ind = np.array([(i, val) for i, val in enumerate(self.actions)])
- weights[a_ind[:, 0], a_ind[:, 1]] = 1.0
- return self.contexts, self.rewards, weights
-
- def get_batch_with_weights(self, batch_size):
- """Returns a random mini-batch with one-hot weights for actions."""
- n, _ = self.contexts.shape
- if self.buffer_s == -1:
- # use all the data
- ind = np.random.choice(range(n), batch_size)
- else:
- # use only buffer (last buffer_s obs)
- ind = np.random.choice(range(max(0, n - self.buffer_s), n), batch_size)
-
- weights = np.zeros((batch_size, self.num_actions))
- sampled_actions = np.array(self.actions)[ind]
- a_ind = np.array([(i, val) for i, val in enumerate(sampled_actions)])
- weights[a_ind[:, 0], a_ind[:, 1]] = 1.0
- return self.contexts[ind, :], self.rewards[ind, :], weights
-
- def num_points(self, f=None):
- """Returns number of points in the buffer (after applying function f)."""
- if f is not None:
- return f(self.contexts.shape[0])
- return self.contexts.shape[0]
-
- @property
- def context_dim(self):
- return self._context_dim
-
- @property
- def num_actions(self):
- return self._num_actions
-
- @property
- def contexts(self):
- return self._contexts
-
- @contexts.setter
- def contexts(self, value):
- self._contexts = value
-
- @property
- def actions(self):
- return self._actions
-
- @actions.setter
- def actions(self, value):
- self._actions = value
-
- @property
- def rewards(self):
- return self._rewards
-
- @rewards.setter
- def rewards(self, value):
- self._rewards = value
diff --git a/research/deep_contextual_bandits/bandits/data/data_sampler.py b/research/deep_contextual_bandits/bandits/data/data_sampler.py
deleted file mode 100644
index 55d1bae383637485182a9524ba8a3cb37b76bd0d..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/data/data_sampler.py
+++ /dev/null
@@ -1,374 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Functions to create bandit problems from datasets."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import pandas as pd
-import tensorflow as tf
-
-
-def one_hot(df, cols):
- """Returns one-hot encoding of DataFrame df including columns in cols."""
- for col in cols:
- dummies = pd.get_dummies(df[col], prefix=col, drop_first=False)
- df = pd.concat([df, dummies], axis=1)
- df = df.drop(col, axis=1)
- return df
-
-
-def sample_mushroom_data(file_name,
- num_contexts,
- r_noeat=0,
- r_eat_safe=5,
- r_eat_poison_bad=-35,
- r_eat_poison_good=5,
- prob_poison_bad=0.5):
- """Samples bandit game from Mushroom UCI Dataset.
-
- Args:
- file_name: Route of file containing the original Mushroom UCI dataset.
- num_contexts: Number of points to sample, i.e. (context, action rewards).
- r_noeat: Reward for not eating a mushroom.
- r_eat_safe: Reward for eating a non-poisonous mushroom.
- r_eat_poison_bad: Reward for eating a poisonous mushroom if harmed.
- r_eat_poison_good: Reward for eating a poisonous mushroom if not harmed.
- prob_poison_bad: Probability of being harmed by eating a poisonous mushroom.
-
- Returns:
- dataset: Sampled matrix with n rows: (context, eat_reward, no_eat_reward).
- opt_vals: Vector of expected optimal (reward, action) for each context.
-
- We assume r_eat_safe > r_noeat, and r_eat_poison_good > r_eat_poison_bad.
- """
-
- # first two cols of df encode whether mushroom is edible or poisonous
- df = pd.read_csv(file_name, header=None)
- df = one_hot(df, df.columns)
- ind = np.random.choice(range(df.shape[0]), num_contexts, replace=True)
-
- contexts = df.iloc[ind, 2:]
- no_eat_reward = r_noeat * np.ones((num_contexts, 1))
- random_poison = np.random.choice(
- [r_eat_poison_bad, r_eat_poison_good],
- p=[prob_poison_bad, 1 - prob_poison_bad],
- size=num_contexts)
- eat_reward = r_eat_safe * df.iloc[ind, 0]
- eat_reward += np.multiply(random_poison, df.iloc[ind, 1])
- eat_reward = eat_reward.values.reshape((num_contexts, 1))
-
- # compute optimal expected reward and optimal actions
- exp_eat_poison_reward = r_eat_poison_bad * prob_poison_bad
- exp_eat_poison_reward += r_eat_poison_good * (1 - prob_poison_bad)
- opt_exp_reward = r_eat_safe * df.iloc[ind, 0] + max(
- r_noeat, exp_eat_poison_reward) * df.iloc[ind, 1]
-
- if r_noeat > exp_eat_poison_reward:
- # actions: no eat = 0 ; eat = 1
- opt_actions = df.iloc[ind, 0] # indicator of edible
- else:
- # should always eat (higher expected reward)
- opt_actions = np.ones((num_contexts, 1))
-
- opt_vals = (opt_exp_reward.values, opt_actions.values)
-
- return np.hstack((contexts, no_eat_reward, eat_reward)), opt_vals
-
-
-def sample_stock_data(file_name, context_dim, num_actions, num_contexts,
- sigma, shuffle_rows=True):
- """Samples linear bandit game from stock prices dataset.
-
- Args:
- file_name: Route of file containing the stock prices dataset.
- context_dim: Context dimension (i.e. vector with the price of each stock).
- num_actions: Number of actions (different linear portfolio strategies).
- num_contexts: Number of contexts to sample.
- sigma: Vector with additive noise levels for each action.
- shuffle_rows: If True, rows from original dataset are shuffled.
-
- Returns:
- dataset: Sampled matrix with rows: (context, reward_1, ..., reward_k).
- opt_vals: Vector of expected optimal (reward, action) for each context.
- """
-
- with tf.gfile.Open(file_name, 'r') as f:
- contexts = np.loadtxt(f, skiprows=1)
-
- if shuffle_rows:
- np.random.shuffle(contexts)
- contexts = contexts[:num_contexts, :]
-
- betas = np.random.uniform(-1, 1, (context_dim, num_actions))
- betas /= np.linalg.norm(betas, axis=0)
-
- mean_rewards = np.dot(contexts, betas)
- noise = np.random.normal(scale=sigma, size=mean_rewards.shape)
- rewards = mean_rewards + noise
-
- opt_actions = np.argmax(mean_rewards, axis=1)
- opt_rewards = [mean_rewards[i, a] for i, a in enumerate(opt_actions)]
- return np.hstack((contexts, rewards)), (np.array(opt_rewards), opt_actions)
-
-
-def sample_jester_data(file_name, context_dim, num_actions, num_contexts,
- shuffle_rows=True, shuffle_cols=False):
- """Samples bandit game from (user, joke) dense subset of Jester dataset.
-
- Args:
- file_name: Route of file containing the modified Jester dataset.
- context_dim: Context dimension (i.e. vector with some ratings from a user).
- num_actions: Number of actions (number of joke ratings to predict).
- num_contexts: Number of contexts to sample.
- shuffle_rows: If True, rows from original dataset are shuffled.
- shuffle_cols: Whether or not context/action jokes are randomly shuffled.
-
- Returns:
- dataset: Sampled matrix with rows: (context, rating_1, ..., rating_k).
- opt_vals: Vector of deterministic optimal (reward, action) for each context.
- """
-
- with tf.gfile.Open(file_name, 'rb') as f:
- dataset = np.load(f)
-
- if shuffle_cols:
- dataset = dataset[:, np.random.permutation(dataset.shape[1])]
- if shuffle_rows:
- np.random.shuffle(dataset)
- dataset = dataset[:num_contexts, :]
-
- assert context_dim + num_actions == dataset.shape[1], 'Wrong data dimensions.'
-
- opt_actions = np.argmax(dataset[:, context_dim:], axis=1)
- opt_rewards = np.array([dataset[i, context_dim + a]
- for i, a in enumerate(opt_actions)])
-
- return dataset, (opt_rewards, opt_actions)
-
-
-def sample_statlog_data(file_name, num_contexts, shuffle_rows=True,
- remove_underrepresented=False):
- """Returns bandit problem dataset based on the UCI statlog data.
-
- Args:
- file_name: Route of file containing the Statlog dataset.
- num_contexts: Number of contexts to sample.
- shuffle_rows: If True, rows from original dataset are shuffled.
- remove_underrepresented: If True, removes arms with very few rewards.
-
- Returns:
- dataset: Sampled matrix with rows: (context, action rewards).
- opt_vals: Vector of deterministic optimal (reward, action) for each context.
-
- https://archive.ics.uci.edu/ml/datasets/Statlog+(Shuttle)
- """
-
- with tf.gfile.Open(file_name, 'r') as f:
- data = np.loadtxt(f)
-
- num_actions = 7 # some of the actions are very rarely optimal.
-
- # Shuffle data
- if shuffle_rows:
- np.random.shuffle(data)
- data = data[:num_contexts, :]
-
- # Last column is label, rest are features
- contexts = data[:, :-1]
- labels = data[:, -1].astype(int) - 1 # convert to 0 based index
-
- if remove_underrepresented:
- contexts, labels = remove_underrepresented_classes(contexts, labels)
-
- return classification_to_bandit_problem(contexts, labels, num_actions)
-
-
-def sample_adult_data(file_name, num_contexts, shuffle_rows=True,
- remove_underrepresented=False):
- """Returns bandit problem dataset based on the UCI adult data.
-
- Args:
- file_name: Route of file containing the Adult dataset.
- num_contexts: Number of contexts to sample.
- shuffle_rows: If True, rows from original dataset are shuffled.
- remove_underrepresented: If True, removes arms with very few rewards.
-
- Returns:
- dataset: Sampled matrix with rows: (context, action rewards).
- opt_vals: Vector of deterministic optimal (reward, action) for each context.
-
- Preprocessing:
- * drop rows with missing values
- * convert categorical variables to 1 hot encoding
-
- https://archive.ics.uci.edu/ml/datasets/census+income
- """
- with tf.gfile.Open(file_name, 'r') as f:
- df = pd.read_csv(f, header=None,
- na_values=[' ?']).dropna()
-
- num_actions = 14
-
- if shuffle_rows:
- df = df.sample(frac=1)
- df = df.iloc[:num_contexts, :]
-
- labels = df[6].astype('category').cat.codes.as_matrix()
- df = df.drop([6], axis=1)
-
- # Convert categorical variables to 1 hot encoding
- cols_to_transform = [1, 3, 5, 7, 8, 9, 13, 14]
- df = pd.get_dummies(df, columns=cols_to_transform)
-
- if remove_underrepresented:
- df, labels = remove_underrepresented_classes(df, labels)
- contexts = df.as_matrix()
-
- return classification_to_bandit_problem(contexts, labels, num_actions)
-
-
-def sample_census_data(file_name, num_contexts, shuffle_rows=True,
- remove_underrepresented=False):
- """Returns bandit problem dataset based on the UCI census data.
-
- Args:
- file_name: Route of file containing the Census dataset.
- num_contexts: Number of contexts to sample.
- shuffle_rows: If True, rows from original dataset are shuffled.
- remove_underrepresented: If True, removes arms with very few rewards.
-
- Returns:
- dataset: Sampled matrix with rows: (context, action rewards).
- opt_vals: Vector of deterministic optimal (reward, action) for each context.
-
- Preprocessing:
- * drop rows with missing labels
- * convert categorical variables to 1 hot encoding
-
- Note: this is the processed (not the 'raw') dataset. It contains a subset
- of the raw features and they've all been discretized.
-
- https://archive.ics.uci.edu/ml/datasets/US+Census+Data+%281990%29
- """
- # Note: this dataset is quite large. It will be slow to load and preprocess.
- with tf.gfile.Open(file_name, 'r') as f:
- df = (pd.read_csv(f, header=0, na_values=['?'])
- .dropna())
-
- num_actions = 9
-
- if shuffle_rows:
- df = df.sample(frac=1)
- df = df.iloc[:num_contexts, :]
-
- # Assuming what the paper calls response variable is the label?
- labels = df['dOccup'].astype('category').cat.codes.as_matrix()
- # In addition to label, also drop the (unique?) key.
- df = df.drop(['dOccup', 'caseid'], axis=1)
-
- # All columns are categorical. Convert to 1 hot encoding.
- df = pd.get_dummies(df, columns=df.columns)
-
- if remove_underrepresented:
- df, labels = remove_underrepresented_classes(df, labels)
- contexts = df.as_matrix()
-
- return classification_to_bandit_problem(contexts, labels, num_actions)
-
-
-def sample_covertype_data(file_name, num_contexts, shuffle_rows=True,
- remove_underrepresented=False):
- """Returns bandit problem dataset based on the UCI Cover_Type data.
-
- Args:
- file_name: Route of file containing the Covertype dataset.
- num_contexts: Number of contexts to sample.
- shuffle_rows: If True, rows from original dataset are shuffled.
- remove_underrepresented: If True, removes arms with very few rewards.
-
- Returns:
- dataset: Sampled matrix with rows: (context, action rewards).
- opt_vals: Vector of deterministic optimal (reward, action) for each context.
-
- Preprocessing:
- * drop rows with missing labels
- * convert categorical variables to 1 hot encoding
-
- https://archive.ics.uci.edu/ml/datasets/Covertype
- """
- with tf.gfile.Open(file_name, 'r') as f:
- df = (pd.read_csv(f, header=0, na_values=['?'])
- .dropna())
-
- num_actions = 7
-
- if shuffle_rows:
- df = df.sample(frac=1)
- df = df.iloc[:num_contexts, :]
-
- # Assuming what the paper calls response variable is the label?
- # Last column is label.
- labels = df[df.columns[-1]].astype('category').cat.codes.as_matrix()
- df = df.drop([df.columns[-1]], axis=1)
-
- # All columns are either quantitative or already converted to 1 hot.
- if remove_underrepresented:
- df, labels = remove_underrepresented_classes(df, labels)
- contexts = df.as_matrix()
-
- return classification_to_bandit_problem(contexts, labels, num_actions)
-
-
-def classification_to_bandit_problem(contexts, labels, num_actions=None):
- """Normalize contexts and encode deterministic rewards."""
-
- if num_actions is None:
- num_actions = np.max(labels) + 1
- num_contexts = contexts.shape[0]
-
- # Due to random subsampling in small problems, some features may be constant
- sstd = safe_std(np.std(contexts, axis=0, keepdims=True)[0, :])
-
- # Normalize features
- contexts = ((contexts - np.mean(contexts, axis=0, keepdims=True)) / sstd)
-
- # One hot encode labels as rewards
- rewards = np.zeros((num_contexts, num_actions))
- rewards[np.arange(num_contexts), labels] = 1.0
-
- return contexts, rewards, (np.ones(num_contexts), labels)
-
-
-def safe_std(values):
- """Remove zero std values for ones."""
- return np.array([val if val != 0.0 else 1.0 for val in values])
-
-
-def remove_underrepresented_classes(features, labels, thresh=0.0005):
- """Removes classes when number of datapoints fraction is below a threshold."""
-
- # Threshold doesn't seem to agree with https://arxiv.org/pdf/1706.04687.pdf
- # Example: for Covertype, they report 4 classes after filtering, we get 7?
- total_count = labels.shape[0]
- unique, counts = np.unique(labels, return_counts=True)
- ratios = counts.astype('float') / total_count
- vals_and_ratios = dict(zip(unique, ratios))
- print('Unique classes and their ratio of total: %s' % vals_and_ratios)
- keep = [vals_and_ratios[v] >= thresh for v in labels]
- return features[keep], labels[np.array(keep)]
diff --git a/research/deep_contextual_bandits/bandits/data/synthetic_data_sampler.py b/research/deep_contextual_bandits/bandits/data/synthetic_data_sampler.py
deleted file mode 100644
index c7de48aba4de109392aa8efad06071886cf67964..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/bandits/data/synthetic_data_sampler.py
+++ /dev/null
@@ -1,179 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Several functions to sample contextual data."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-
-
-def sample_contextual_data(num_contexts, dim_context, num_actions, sigma):
- """Samples independent Gaussian data.
-
- There is nothing to learn here as the rewards do not depend on the context.
-
- Args:
- num_contexts: Number of contexts to sample.
- dim_context: Dimension of the contexts.
- num_actions: Number of arms for the multi-armed bandit.
- sigma: Standard deviation of the independent Gaussian samples.
-
- Returns:
- data: A [num_contexts, dim_context + num_actions] numpy array with the data.
- """
- size_data = [num_contexts, dim_context + num_actions]
- return np.random.normal(scale=sigma, size=size_data)
-
-
-def sample_linear_data(num_contexts, dim_context, num_actions, sigma=0.0):
- """Samples data from linearly parameterized arms.
-
- The reward for context X and arm j is given by X^T beta_j, for some latent
- set of parameters {beta_j : j = 1, ..., k}. The beta's are sampled uniformly
- at random, the contexts are Gaussian, and sigma-noise is added to the rewards.
-
- Args:
- num_contexts: Number of contexts to sample.
- dim_context: Dimension of the contexts.
- num_actions: Number of arms for the multi-armed bandit.
- sigma: Standard deviation of the additive noise. Set to zero for no noise.
-
- Returns:
- data: A [n, d+k] numpy array with the data.
- betas: Latent parameters that determine expected reward for each arm.
- opt: (optimal_rewards, optimal_actions) for all contexts.
- """
-
- betas = np.random.uniform(-1, 1, (dim_context, num_actions))
- betas /= np.linalg.norm(betas, axis=0)
- contexts = np.random.normal(size=[num_contexts, dim_context])
- rewards = np.dot(contexts, betas)
- opt_actions = np.argmax(rewards, axis=1)
- rewards += np.random.normal(scale=sigma, size=rewards.shape)
- opt_rewards = np.array([rewards[i, act] for i, act in enumerate(opt_actions)])
- return np.hstack((contexts, rewards)), betas, (opt_rewards, opt_actions)
-
-
-def sample_sparse_linear_data(num_contexts, dim_context, num_actions,
- sparse_dim, sigma=0.0):
- """Samples data from sparse linearly parameterized arms.
-
- The reward for context X and arm j is given by X^T beta_j, for some latent
- set of parameters {beta_j : j = 1, ..., k}. The beta's are sampled uniformly
- at random, the contexts are Gaussian, and sigma-noise is added to the rewards.
- Only s components out of d are non-zero for each arm's beta.
-
- Args:
- num_contexts: Number of contexts to sample.
- dim_context: Dimension of the contexts.
- num_actions: Number of arms for the multi-armed bandit.
- sparse_dim: Dimension of the latent subspace (sparsity pattern dimension).
- sigma: Standard deviation of the additive noise. Set to zero for no noise.
-
- Returns:
- data: A [num_contexts, dim_context+num_actions] numpy array with the data.
- betas: Latent parameters that determine expected reward for each arm.
- opt: (optimal_rewards, optimal_actions) for all contexts.
- """
-
- flatten = lambda l: [item for sublist in l for item in sublist]
- sparse_pattern = flatten(
- [[(j, i) for j in np.random.choice(range(dim_context),
- sparse_dim,
- replace=False)]
- for i in range(num_actions)])
- betas = np.random.uniform(-1, 1, (dim_context, num_actions))
- mask = np.zeros((dim_context, num_actions))
- for elt in sparse_pattern:
- mask[elt] = 1
- betas = np.multiply(betas, mask)
- betas /= np.linalg.norm(betas, axis=0)
- contexts = np.random.normal(size=[num_contexts, dim_context])
- rewards = np.dot(contexts, betas)
- opt_actions = np.argmax(rewards, axis=1)
- rewards += np.random.normal(scale=sigma, size=rewards.shape)
- opt_rewards = np.array([rewards[i, act] for i, act in enumerate(opt_actions)])
- return np.hstack((contexts, rewards)), betas, (opt_rewards, opt_actions)
-
-
-def sample_wheel_bandit_data(num_contexts, delta, mean_v, std_v,
- mu_large, std_large):
- """Samples from Wheel bandit game (see https://arxiv.org/abs/1802.09127).
-
- Args:
- num_contexts: Number of points to sample, i.e. (context, action rewards).
- delta: Exploration parameter: high reward in one region if norm above delta.
- mean_v: Mean reward for each action if context norm is below delta.
- std_v: Gaussian reward std for each action if context norm is below delta.
- mu_large: Mean reward for optimal action if context norm is above delta.
- std_large: Reward std for optimal action if context norm is above delta.
-
- Returns:
- dataset: Sampled matrix with n rows: (context, action rewards).
- opt_vals: Vector of expected optimal (reward, action) for each context.
- """
-
- context_dim = 2
- num_actions = 5
-
- data = []
- rewards = []
- opt_actions = []
- opt_rewards = []
-
- # sample uniform contexts in unit ball
- while len(data) < num_contexts:
- raw_data = np.random.uniform(-1, 1, (int(num_contexts / 3), context_dim))
-
- for i in range(raw_data.shape[0]):
- if np.linalg.norm(raw_data[i, :]) <= 1:
- data.append(raw_data[i, :])
-
- contexts = np.stack(data)[:num_contexts, :]
-
- # sample rewards
- for i in range(num_contexts):
- r = [np.random.normal(mean_v[j], std_v[j]) for j in range(num_actions)]
- if np.linalg.norm(contexts[i, :]) >= delta:
- # large reward in the right region for the context
- r_big = np.random.normal(mu_large, std_large)
- if contexts[i, 0] > 0:
- if contexts[i, 1] > 0:
- r[0] = r_big
- opt_actions.append(0)
- else:
- r[1] = r_big
- opt_actions.append(1)
- else:
- if contexts[i, 1] > 0:
- r[2] = r_big
- opt_actions.append(2)
- else:
- r[3] = r_big
- opt_actions.append(3)
- else:
- opt_actions.append(np.argmax(mean_v))
-
- opt_rewards.append(r[opt_actions[-1]])
- rewards.append(r)
-
- rewards = np.stack(rewards)
- opt_rewards = np.array(opt_rewards)
- opt_actions = np.array(opt_actions)
-
- return np.hstack((contexts, rewards)), (opt_rewards, opt_actions)
diff --git a/research/deep_contextual_bandits/example_main.py b/research/deep_contextual_bandits/example_main.py
deleted file mode 100644
index c71a5aa26f94adbf5989d002fd5c768582c14e14..0000000000000000000000000000000000000000
--- a/research/deep_contextual_bandits/example_main.py
+++ /dev/null
@@ -1,454 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Simple example of contextual bandits simulation.
-
-Code corresponding to:
-Deep Bayesian Bandits Showdown: An Empirical Comparison of Bayesian Deep Networks
-for Thompson Sampling, by Carlos Riquelme, George Tucker, and Jasper Snoek.
-https://arxiv.org/abs/1802.09127
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import time
-from absl import app
-from absl import flags
-import numpy as np
-import os
-import tensorflow as tf
-
-from bandits.algorithms.bootstrapped_bnn_sampling import BootstrappedBNNSampling
-from bandits.core.contextual_bandit import run_contextual_bandit
-from bandits.data.data_sampler import sample_adult_data
-from bandits.data.data_sampler import sample_census_data
-from bandits.data.data_sampler import sample_covertype_data
-from bandits.data.data_sampler import sample_jester_data
-from bandits.data.data_sampler import sample_mushroom_data
-from bandits.data.data_sampler import sample_statlog_data
-from bandits.data.data_sampler import sample_stock_data
-from bandits.algorithms.fixed_policy_sampling import FixedPolicySampling
-from bandits.algorithms.linear_full_posterior_sampling import LinearFullPosteriorSampling
-from bandits.algorithms.neural_linear_sampling import NeuralLinearPosteriorSampling
-from bandits.algorithms.parameter_noise_sampling import ParameterNoiseSampling
-from bandits.algorithms.posterior_bnn_sampling import PosteriorBNNSampling
-from bandits.data.synthetic_data_sampler import sample_linear_data
-from bandits.data.synthetic_data_sampler import sample_sparse_linear_data
-from bandits.data.synthetic_data_sampler import sample_wheel_bandit_data
-from bandits.algorithms.uniform_sampling import UniformSampling
-
-# Set up your file routes to the data files.
-base_route = os.getcwd()
-data_route = 'contextual_bandits/datasets'
-
-FLAGS = flags.FLAGS
-FLAGS.set_default('alsologtostderr', True)
-flags.DEFINE_string('logdir', '/tmp/bandits/', 'Base directory to save output')
-flags.DEFINE_string(
- 'mushroom_data',
- os.path.join(base_route, data_route, 'mushroom.data'),
- 'Directory where Mushroom data is stored.')
-flags.DEFINE_string(
- 'financial_data',
- os.path.join(base_route, data_route, 'raw_stock_contexts'),
- 'Directory where Financial data is stored.')
-flags.DEFINE_string(
- 'jester_data',
- os.path.join(base_route, data_route, 'jester_data_40jokes_19181users.npy'),
- 'Directory where Jester data is stored.')
-flags.DEFINE_string(
- 'statlog_data',
- os.path.join(base_route, data_route, 'shuttle.trn'),
- 'Directory where Statlog data is stored.')
-flags.DEFINE_string(
- 'adult_data',
- os.path.join(base_route, data_route, 'adult.full'),
- 'Directory where Adult data is stored.')
-flags.DEFINE_string(
- 'covertype_data',
- os.path.join(base_route, data_route, 'covtype.data'),
- 'Directory where Covertype data is stored.')
-flags.DEFINE_string(
- 'census_data',
- os.path.join(base_route, data_route, 'USCensus1990.data.txt'),
- 'Directory where Census data is stored.')
-
-
-def sample_data(data_type, num_contexts=None):
- """Sample data from given 'data_type'.
-
- Args:
- data_type: Dataset from which to sample.
- num_contexts: Number of contexts to sample.
-
- Returns:
- dataset: Sampled matrix with rows: (context, reward_1, ..., reward_num_act).
- opt_rewards: Vector of expected optimal reward for each context.
- opt_actions: Vector of optimal action for each context.
- num_actions: Number of available actions.
- context_dim: Dimension of each context.
- """
-
- if data_type == 'linear':
- # Create linear dataset
- num_actions = 8
- context_dim = 10
- noise_stds = [0.01 * (i + 1) for i in range(num_actions)]
- dataset, _, opt_linear = sample_linear_data(num_contexts, context_dim,
- num_actions, sigma=noise_stds)
- opt_rewards, opt_actions = opt_linear
- elif data_type == 'sparse_linear':
- # Create sparse linear dataset
- num_actions = 7
- context_dim = 10
- noise_stds = [0.01 * (i + 1) for i in range(num_actions)]
- num_nnz_dims = int(context_dim / 3.0)
- dataset, _, opt_sparse_linear = sample_sparse_linear_data(
- num_contexts, context_dim, num_actions, num_nnz_dims, sigma=noise_stds)
- opt_rewards, opt_actions = opt_sparse_linear
- elif data_type == 'mushroom':
- # Create mushroom dataset
- num_actions = 2
- context_dim = 117
- file_name = FLAGS.mushroom_data
- dataset, opt_mushroom = sample_mushroom_data(file_name, num_contexts)
- opt_rewards, opt_actions = opt_mushroom
- elif data_type == 'financial':
- num_actions = 8
- context_dim = 21
- num_contexts = min(3713, num_contexts)
- noise_stds = [0.01 * (i + 1) for i in range(num_actions)]
- file_name = FLAGS.financial_data
- dataset, opt_financial = sample_stock_data(file_name, context_dim,
- num_actions, num_contexts,
- noise_stds, shuffle_rows=True)
- opt_rewards, opt_actions = opt_financial
- elif data_type == 'jester':
- num_actions = 8
- context_dim = 32
- num_contexts = min(19181, num_contexts)
- file_name = FLAGS.jester_data
- dataset, opt_jester = sample_jester_data(file_name, context_dim,
- num_actions, num_contexts,
- shuffle_rows=True,
- shuffle_cols=True)
- opt_rewards, opt_actions = opt_jester
- elif data_type == 'statlog':
- file_name = FLAGS.statlog_data
- num_actions = 7
- num_contexts = min(43500, num_contexts)
- sampled_vals = sample_statlog_data(file_name, num_contexts,
- shuffle_rows=True)
- contexts, rewards, (opt_rewards, opt_actions) = sampled_vals
- dataset = np.hstack((contexts, rewards))
- context_dim = contexts.shape[1]
- elif data_type == 'adult':
- file_name = FLAGS.adult_data
- num_actions = 14
- num_contexts = min(45222, num_contexts)
- sampled_vals = sample_adult_data(file_name, num_contexts,
- shuffle_rows=True)
- contexts, rewards, (opt_rewards, opt_actions) = sampled_vals
- dataset = np.hstack((contexts, rewards))
- context_dim = contexts.shape[1]
- elif data_type == 'covertype':
- file_name = FLAGS.covertype_data
- num_actions = 7
- num_contexts = min(150000, num_contexts)
- sampled_vals = sample_covertype_data(file_name, num_contexts,
- shuffle_rows=True)
- contexts, rewards, (opt_rewards, opt_actions) = sampled_vals
- dataset = np.hstack((contexts, rewards))
- context_dim = contexts.shape[1]
- elif data_type == 'census':
- file_name = FLAGS.census_data
- num_actions = 9
- num_contexts = min(150000, num_contexts)
- sampled_vals = sample_census_data(file_name, num_contexts,
- shuffle_rows=True)
- contexts, rewards, (opt_rewards, opt_actions) = sampled_vals
- dataset = np.hstack((contexts, rewards))
- context_dim = contexts.shape[1]
- elif data_type == 'wheel':
- delta = 0.95
- num_actions = 5
- context_dim = 2
- mean_v = [1.0, 1.0, 1.0, 1.0, 1.2]
- std_v = [0.05, 0.05, 0.05, 0.05, 0.05]
- mu_large = 50
- std_large = 0.01
- dataset, opt_wheel = sample_wheel_bandit_data(num_contexts, delta,
- mean_v, std_v,
- mu_large, std_large)
- opt_rewards, opt_actions = opt_wheel
-
- return dataset, opt_rewards, opt_actions, num_actions, context_dim
-
-
-def display_results(algos, opt_rewards, opt_actions, h_rewards, t_init, name):
- """Displays summary statistics of the performance of each algorithm."""
-
- print('---------------------------------------------------')
- print('---------------------------------------------------')
- print('{} bandit completed after {} seconds.'.format(
- name, time.time() - t_init))
- print('---------------------------------------------------')
-
- performance_pairs = []
- for j, a in enumerate(algos):
- performance_pairs.append((a.name, np.sum(h_rewards[:, j])))
- performance_pairs = sorted(performance_pairs,
- key=lambda elt: elt[1],
- reverse=True)
- for i, (name, reward) in enumerate(performance_pairs):
- print('{:3}) {:20}| \t \t total reward = {:10}.'.format(i, name, reward))
-
- print('---------------------------------------------------')
- print('Optimal total reward = {}.'.format(np.sum(opt_rewards)))
- print('Frequency of optimal actions (action, frequency):')
- print([[elt, list(opt_actions).count(elt)] for elt in set(opt_actions)])
- print('---------------------------------------------------')
- print('---------------------------------------------------')
-
-
-def main(_):
-
- # Problem parameters
- num_contexts = 2000
-
- # Data type in {linear, sparse_linear, mushroom, financial, jester,
- # statlog, adult, covertype, census, wheel}
- data_type = 'mushroom'
-
- # Create dataset
- sampled_vals = sample_data(data_type, num_contexts)
- dataset, opt_rewards, opt_actions, num_actions, context_dim = sampled_vals
-
- # Define hyperparameters and algorithms
- hparams = tf.contrib.training.HParams(num_actions=num_actions)
-
- hparams_linear = tf.contrib.training.HParams(num_actions=num_actions,
- context_dim=context_dim,
- a0=6,
- b0=6,
- lambda_prior=0.25,
- initial_pulls=2)
-
- hparams_rms = tf.contrib.training.HParams(num_actions=num_actions,
- context_dim=context_dim,
- init_scale=0.3,
- activation=tf.nn.relu,
- layer_sizes=[50],
- batch_size=512,
- activate_decay=True,
- initial_lr=0.1,
- max_grad_norm=5.0,
- show_training=False,
- freq_summary=1000,
- buffer_s=-1,
- initial_pulls=2,
- optimizer='RMS',
- reset_lr=True,
- lr_decay_rate=0.5,
- training_freq=50,
- training_epochs=100,
- p=0.95,
- q=3)
-
- hparams_dropout = tf.contrib.training.HParams(num_actions=num_actions,
- context_dim=context_dim,
- init_scale=0.3,
- activation=tf.nn.relu,
- layer_sizes=[50],
- batch_size=512,
- activate_decay=True,
- initial_lr=0.1,
- max_grad_norm=5.0,
- show_training=False,
- freq_summary=1000,
- buffer_s=-1,
- initial_pulls=2,
- optimizer='RMS',
- reset_lr=True,
- lr_decay_rate=0.5,
- training_freq=50,
- training_epochs=100,
- use_dropout=True,
- keep_prob=0.80)
-
- hparams_bbb = tf.contrib.training.HParams(num_actions=num_actions,
- context_dim=context_dim,
- init_scale=0.3,
- activation=tf.nn.relu,
- layer_sizes=[50],
- batch_size=512,
- activate_decay=True,
- initial_lr=0.1,
- max_grad_norm=5.0,
- show_training=False,
- freq_summary=1000,
- buffer_s=-1,
- initial_pulls=2,
- optimizer='RMS',
- use_sigma_exp_transform=True,
- cleared_times_trained=10,
- initial_training_steps=100,
- noise_sigma=0.1,
- reset_lr=False,
- training_freq=50,
- training_epochs=100)
-
- hparams_nlinear = tf.contrib.training.HParams(num_actions=num_actions,
- context_dim=context_dim,
- init_scale=0.3,
- activation=tf.nn.relu,
- layer_sizes=[50],
- batch_size=512,
- activate_decay=True,
- initial_lr=0.1,
- max_grad_norm=5.0,
- show_training=False,
- freq_summary=1000,
- buffer_s=-1,
- initial_pulls=2,
- reset_lr=True,
- lr_decay_rate=0.5,
- training_freq=1,
- training_freq_network=50,
- training_epochs=100,
- a0=6,
- b0=6,
- lambda_prior=0.25)
-
- hparams_nlinear2 = tf.contrib.training.HParams(num_actions=num_actions,
- context_dim=context_dim,
- init_scale=0.3,
- activation=tf.nn.relu,
- layer_sizes=[50],
- batch_size=512,
- activate_decay=True,
- initial_lr=0.1,
- max_grad_norm=5.0,
- show_training=False,
- freq_summary=1000,
- buffer_s=-1,
- initial_pulls=2,
- reset_lr=True,
- lr_decay_rate=0.5,
- training_freq=10,
- training_freq_network=50,
- training_epochs=100,
- a0=6,
- b0=6,
- lambda_prior=0.25)
-
- hparams_pnoise = tf.contrib.training.HParams(num_actions=num_actions,
- context_dim=context_dim,
- init_scale=0.3,
- activation=tf.nn.relu,
- layer_sizes=[50],
- batch_size=512,
- activate_decay=True,
- initial_lr=0.1,
- max_grad_norm=5.0,
- show_training=False,
- freq_summary=1000,
- buffer_s=-1,
- initial_pulls=2,
- optimizer='RMS',
- reset_lr=True,
- lr_decay_rate=0.5,
- training_freq=50,
- training_epochs=100,
- noise_std=0.05,
- eps=0.1,
- d_samples=300,
- )
-
- hparams_alpha_div = tf.contrib.training.HParams(num_actions=num_actions,
- context_dim=context_dim,
- init_scale=0.3,
- activation=tf.nn.relu,
- layer_sizes=[50],
- batch_size=512,
- activate_decay=True,
- initial_lr=0.1,
- max_grad_norm=5.0,
- show_training=False,
- freq_summary=1000,
- buffer_s=-1,
- initial_pulls=2,
- optimizer='RMS',
- use_sigma_exp_transform=True,
- cleared_times_trained=10,
- initial_training_steps=100,
- noise_sigma=0.1,
- reset_lr=False,
- training_freq=50,
- training_epochs=100,
- alpha=1.0,
- k=20,
- prior_variance=0.1)
-
- hparams_gp = tf.contrib.training.HParams(num_actions=num_actions,
- num_outputs=num_actions,
- context_dim=context_dim,
- reset_lr=False,
- learn_embeddings=True,
- max_num_points=1000,
- show_training=False,
- freq_summary=1000,
- batch_size=512,
- keep_fixed_after_max_obs=True,
- training_freq=50,
- initial_pulls=2,
- training_epochs=100,
- lr=0.01,
- buffer_s=-1,
- initial_lr=0.001,
- lr_decay_rate=0.0,
- optimizer='RMS',
- task_latent_dim=5,
- activate_decay=False)
-
- algos = [
- UniformSampling('Uniform Sampling', hparams),
- UniformSampling('Uniform Sampling 2', hparams),
- FixedPolicySampling('fixed1', [0.75, 0.25], hparams),
- FixedPolicySampling('fixed2', [0.25, 0.75], hparams),
- PosteriorBNNSampling('RMS', hparams_rms, 'RMSProp'),
- PosteriorBNNSampling('Dropout', hparams_dropout, 'RMSProp'),
- PosteriorBNNSampling('BBB', hparams_bbb, 'Variational'),
- NeuralLinearPosteriorSampling('NeuralLinear', hparams_nlinear),
- NeuralLinearPosteriorSampling('NeuralLinear2', hparams_nlinear2),
- LinearFullPosteriorSampling('LinFullPost', hparams_linear),
- BootstrappedBNNSampling('BootRMS', hparams_rms),
- ParameterNoiseSampling('ParamNoise', hparams_pnoise),
- PosteriorBNNSampling('BBAlphaDiv', hparams_alpha_div, 'AlphaDiv'),
- PosteriorBNNSampling('MultitaskGP', hparams_gp, 'GP'),
- ]
-
- # Run contextual bandit problem
- t_init = time.time()
- results = run_contextual_bandit(context_dim, num_actions, dataset, algos)
- _, h_rewards = results
-
- # Display results
- display_results(algos, opt_rewards, opt_actions, h_rewards, t_init, data_type)
-
-if __name__ == '__main__':
- app.run(main)
diff --git a/research/domain_adaptation/README.md b/research/domain_adaptation/README.md
deleted file mode 100644
index e8a2b83794f11ed3711e6bc26254a90cb5469440..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/README.md
+++ /dev/null
@@ -1,124 +0,0 @@
-
-
-
-
-## Introduction
-This is the code used for two domain adaptation papers.
-
-The `domain_separation` directory contains code for the "Domain Separation
-Networks" paper by Bousmalis K., Trigeorgis G., et al. which was presented at
-NIPS 2016. The paper can be found here: https://arxiv.org/abs/1608.06019.
-
-The `pixel_domain_adaptation` directory contains the code used for the
-"Unsupervised Pixel-Level Domain Adaptation with Generative Adversarial
-Networks" paper by Bousmalis K., et al. (presented at CVPR 2017). The paper can
-be found here: https://arxiv.org/abs/1612.05424. PixelDA aims to perform domain
-adaptation by transfering the visual style of the target domain (which has few
-or no labels) to a source domain (which has many labels). This is accomplished
-using a Generative Adversarial Network (GAN).
-
-### Other implementations
-* [Simplified-DSN](https://github.com/AmirHussein96/Simplified-DSN):
- An unofficial implementation of the [Domain Separation Networks paper](https://arxiv.org/abs/1608.06019).
-
-## Contact
-The domain separation code was open-sourced
-by [Konstantinos Bousmalis](https://github.com/bousmalis)
-(konstantinos@google.com), while the pixel level domain adaptation code was
-open-sourced by [David Dohan](https://github.com/dmrd) (ddohan@google.com).
-
-## Installation
-You will need to have the following installed on your machine before trying out the DSN code.
-
-* TensorFlow 1.x: https://www.tensorflow.org/install/
-* Bazel: https://bazel.build/
-
-## Initial setup
-In order to run the MNIST to MNIST-M experiments, you will need to set the
-data directory:
-
-```
-$ export DSN_DATA_DIR=/your/dir
-```
-
-Add models and models/slim to your `$PYTHONPATH` (assumes $PWD is /models):
-
-```
-$ export PYTHONPATH=$PYTHONPATH:$PWD:$PWD/slim
-```
-
-## Getting the datasets
-
-You can fetch the MNIST data by running
-
-```
- $ bazel run slim:download_and_convert_data -- --dataset_dir $DSN_DATA_DIR --dataset_name=mnist
-```
-
-The MNIST-M dataset is available online [here](http://bit.ly/2nrlUAJ). Once it is downloaded and extracted into your data directory, create TFRecord files by running:
-```
-$ bazel run domain_adaptation/datasets:download_and_convert_mnist_m -- --dataset_dir $DSN_DATA_DIR
-```
-
-# Running PixelDA from MNIST to MNIST-M
-You can run PixelDA as follows (using Tensorboard to examine the results):
-
-```
-$ bazel run domain_adaptation/pixel_domain_adaptation:pixelda_train -- --dataset_dir $DSN_DATA_DIR --source_dataset mnist --target_dataset mnist_m
-```
-
-And evaluation as:
-```
-$ bazel run domain_adaptation/pixel_domain_adaptation:pixelda_eval -- --dataset_dir $DSN_DATA_DIR --source_dataset mnist --target_dataset mnist_m --target_split_name test
-```
-
-The MNIST-M results in the paper were run with the following hparams flag:
-```
---hparams arch=resnet,domain_loss_weight=0.135603587834,num_training_examples=16000000,style_transfer_loss_weight=0.0113173311334,task_loss_in_g_weight=0.0100959947002,task_tower=mnist,task_tower_in_g_step=true
-```
-
-### A note on terminology/language of the code:
-
-The components of the network can be grouped into two parts
-which correspond to elements which are jointly optimized: The generator
-component and the discriminator component.
-
-The generator component takes either an image or noise vector and produces an
-output image.
-
-The discriminator component takes the generated images and the target images
-and attempts to discriminate between them.
-
-## Running DSN code for adapting MNIST to MNIST-M
-
-Then you need to build the binaries with Bazel:
-
-```
-$ bazel build -c opt domain_adaptation/domain_separation/...
-```
-
-You can then train with the following command:
-
-```
-$ ./bazel-bin/domain_adaptation/domain_separation/dsn_train \
- --similarity_loss=dann_loss \
- --basic_tower=dann_mnist \
- --source_dataset=mnist \
- --target_dataset=mnist_m \
- --learning_rate=0.0117249 \
- --gamma_weight=0.251175 \
- --weight_decay=1e-6 \
- --layers_to_regularize=fc3 \
- --nouse_separation \
- --master="" \
- --dataset_dir=${DSN_DATA_DIR} \
- -v --use_logging
-```
-
-Evaluation can be invoked with the following command:
-
-```
-$ ./bazel-bin/domain_adaptation/domain_separation/dsn_eval \
- -v --dataset mnist_m --split test --num_examples=9001 \
- --dataset_dir=${DSN_DATA_DIR}
-```
diff --git a/research/domain_adaptation/WORKSPACE b/research/domain_adaptation/WORKSPACE
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/domain_adaptation/__init__.py b/research/domain_adaptation/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/domain_adaptation/datasets/BUILD b/research/domain_adaptation/datasets/BUILD
deleted file mode 100644
index 067a79374fbcedaa6fcd90293e5365aaad4c18c6..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/datasets/BUILD
+++ /dev/null
@@ -1,45 +0,0 @@
-# Domain Adaptation Scenarios Datasets
-
-package(
- default_visibility = [
- ":internal",
- ],
-)
-
-licenses(["notice"]) # Apache 2.0
-
-exports_files(["LICENSE"])
-
-package_group(
- name = "internal",
- packages = [
- "//domain_adaptation/...",
- ],
-)
-
-py_library(
- name = "dataset_factory",
- srcs = ["dataset_factory.py"],
- deps = [
- ":mnist_m",
- "//slim:mnist",
- ],
-)
-
-py_binary(
- name = "download_and_convert_mnist_m",
- srcs = ["download_and_convert_mnist_m.py"],
- deps = [
-
- "//slim:dataset_utils",
- ],
-)
-
-py_binary(
- name = "mnist_m",
- srcs = ["mnist_m.py"],
- deps = [
-
- "//slim:dataset_utils",
- ],
-)
diff --git a/research/domain_adaptation/datasets/__init__.py b/research/domain_adaptation/datasets/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/domain_adaptation/datasets/dataset_factory.py b/research/domain_adaptation/datasets/dataset_factory.py
deleted file mode 100644
index 4ca1b41c412a78d25053fc786c8f81072fe90adb..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/datasets/dataset_factory.py
+++ /dev/null
@@ -1,107 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""A factory-pattern class which returns image/label pairs."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-# Dependency imports
-import tensorflow as tf
-
-from slim.datasets import mnist
-from domain_adaptation.datasets import mnist_m
-
-slim = tf.contrib.slim
-
-
-def get_dataset(dataset_name,
- split_name,
- dataset_dir,
- file_pattern=None,
- reader=None):
- """Given a dataset name and a split_name returns a Dataset.
-
- Args:
- dataset_name: String, the name of the dataset.
- split_name: A train/test split name.
- dataset_dir: The directory where the dataset files are stored.
- file_pattern: The file pattern to use for matching the dataset source files.
- reader: The subclass of tf.ReaderBase. If left as `None`, then the default
- reader defined by each dataset is used.
-
- Returns:
- A tf-slim `Dataset` class.
-
- Raises:
- ValueError: if `dataset_name` isn't recognized.
- """
- dataset_name_to_module = {'mnist': mnist, 'mnist_m': mnist_m}
- if dataset_name not in dataset_name_to_module:
- raise ValueError('Name of dataset unknown %s.' % dataset_name)
-
- return dataset_name_to_module[dataset_name].get_split(split_name, dataset_dir,
- file_pattern, reader)
-
-
-def provide_batch(dataset_name, split_name, dataset_dir, num_readers,
- batch_size, num_preprocessing_threads):
- """Provides a batch of images and corresponding labels.
-
- Args:
- dataset_name: String, the name of the dataset.
- split_name: A train/test split name.
- dataset_dir: The directory where the dataset files are stored.
- num_readers: The number of readers used by DatasetDataProvider.
- batch_size: The size of the batch requested.
- num_preprocessing_threads: The number of preprocessing threads for
- tf.train.batch.
- file_pattern: The file pattern to use for matching the dataset source files.
- reader: The subclass of tf.ReaderBase. If left as `None`, then the default
- reader defined by each dataset is used.
-
- Returns:
- A batch of
- images: tensor of [batch_size, height, width, channels].
- labels: dictionary of labels.
- """
- dataset = get_dataset(dataset_name, split_name, dataset_dir)
- provider = slim.dataset_data_provider.DatasetDataProvider(
- dataset,
- num_readers=num_readers,
- common_queue_capacity=20 * batch_size,
- common_queue_min=10 * batch_size)
- [image, label] = provider.get(['image', 'label'])
-
- # Convert images to float32
- image = tf.image.convert_image_dtype(image, tf.float32)
- image -= 0.5
- image *= 2
-
- # Load the data.
- labels = {}
- images, labels['classes'] = tf.train.batch(
- [image, label],
- batch_size=batch_size,
- num_threads=num_preprocessing_threads,
- capacity=5 * batch_size)
- labels['classes'] = slim.one_hot_encoding(labels['classes'],
- dataset.num_classes)
-
- # Convert mnist to RGB and 32x32 so that it can match mnist_m.
- if dataset_name == 'mnist':
- images = tf.image.grayscale_to_rgb(images)
- images = tf.image.resize_images(images, [32, 32])
- return images, labels
diff --git a/research/domain_adaptation/datasets/download_and_convert_mnist_m.py b/research/domain_adaptation/datasets/download_and_convert_mnist_m.py
deleted file mode 100644
index 3b5004d3d8aaf54656389e517c50f38299714bc7..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/datasets/download_and_convert_mnist_m.py
+++ /dev/null
@@ -1,237 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-r"""Downloads and converts MNIST-M data to TFRecords of TF-Example protos.
-
-This module downloads the MNIST-M data, uncompresses it, reads the files
-that make up the MNIST-M data and creates two TFRecord datasets: one for train
-and one for test. Each TFRecord dataset is comprised of a set of TF-Example
-protocol buffers, each of which contain a single image and label.
-
-The script should take about a minute to run.
-
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import random
-import sys
-
-# Dependency imports
-import numpy as np
-from six.moves import urllib
-import tensorflow as tf
-
-from slim.datasets import dataset_utils
-
-tf.app.flags.DEFINE_string(
- 'dataset_dir', None,
- 'The directory where the output TFRecords and temporary files are saved.')
-
-FLAGS = tf.app.flags.FLAGS
-
-_IMAGE_SIZE = 32
-_NUM_CHANNELS = 3
-
-# The number of images in the training set.
-_NUM_TRAIN_SAMPLES = 59001
-
-# The number of images to be kept from the training set for the validation set.
-_NUM_VALIDATION = 1000
-
-# The number of images in the test set.
-_NUM_TEST_SAMPLES = 9001
-
-# Seed for repeatability.
-_RANDOM_SEED = 0
-
-# The names of the classes.
-_CLASS_NAMES = [
- 'zero',
- 'one',
- 'two',
- 'three',
- 'four',
- 'five',
- 'size',
- 'seven',
- 'eight',
- 'nine',
-]
-
-
-class ImageReader(object):
- """Helper class that provides TensorFlow image coding utilities."""
-
- def __init__(self):
- # Initializes function that decodes RGB PNG data.
- self._decode_png_data = tf.placeholder(dtype=tf.string)
- self._decode_png = tf.image.decode_png(self._decode_png_data, channels=3)
-
- def read_image_dims(self, sess, image_data):
- image = self.decode_png(sess, image_data)
- return image.shape[0], image.shape[1]
-
- def decode_png(self, sess, image_data):
- image = sess.run(
- self._decode_png, feed_dict={self._decode_png_data: image_data})
- assert len(image.shape) == 3
- assert image.shape[2] == 3
- return image
-
-
-def _convert_dataset(split_name, filenames, filename_to_class_id, dataset_dir):
- """Converts the given filenames to a TFRecord dataset.
-
- Args:
- split_name: The name of the dataset, either 'train' or 'valid'.
- filenames: A list of absolute paths to png images.
- filename_to_class_id: A dictionary from filenames (strings) to class ids
- (integers).
- dataset_dir: The directory where the converted datasets are stored.
- """
- print('Converting the {} split.'.format(split_name))
- # Train and validation splits are both in the train directory.
- if split_name in ['train', 'valid']:
- png_directory = os.path.join(dataset_dir, 'mnist_m', 'mnist_m_train')
- elif split_name == 'test':
- png_directory = os.path.join(dataset_dir, 'mnist_m', 'mnist_m_test')
-
- with tf.Graph().as_default():
- image_reader = ImageReader()
-
- with tf.Session('') as sess:
- output_filename = _get_output_filename(dataset_dir, split_name)
-
- with tf.python_io.TFRecordWriter(output_filename) as tfrecord_writer:
- for filename in filenames:
- # Read the filename:
- image_data = tf.gfile.FastGFile(
- os.path.join(png_directory, filename), 'r').read()
- height, width = image_reader.read_image_dims(sess, image_data)
-
- class_id = filename_to_class_id[filename]
- example = dataset_utils.image_to_tfexample(image_data, 'png', height,
- width, class_id)
- tfrecord_writer.write(example.SerializeToString())
-
- sys.stdout.write('\n')
- sys.stdout.flush()
-
-
-def _extract_labels(label_filename):
- """Extract the labels into a dict of filenames to int labels.
-
- Args:
- labels_filename: The filename of the MNIST-M labels.
-
- Returns:
- A dictionary of filenames to int labels.
- """
- print('Extracting labels from: ', label_filename)
- label_file = tf.gfile.FastGFile(label_filename, 'r').readlines()
- label_lines = [line.rstrip('\n').split() for line in label_file]
- labels = {}
- for line in label_lines:
- assert len(line) == 2
- labels[line[0]] = int(line[1])
- return labels
-
-
-def _get_output_filename(dataset_dir, split_name):
- """Creates the output filename.
-
- Args:
- dataset_dir: The directory where the temporary files are stored.
- split_name: The name of the train/test split.
-
- Returns:
- An absolute file path.
- """
- return '%s/mnist_m_%s.tfrecord' % (dataset_dir, split_name)
-
-
-def _get_filenames(dataset_dir):
- """Returns a list of filenames and inferred class names.
-
- Args:
- dataset_dir: A directory containing a set PNG encoded MNIST-M images.
-
- Returns:
- A list of image file paths, relative to `dataset_dir`.
- """
- photo_filenames = []
- for filename in os.listdir(dataset_dir):
- photo_filenames.append(filename)
- return photo_filenames
-
-
-def run(dataset_dir):
- """Runs the download and conversion operation.
-
- Args:
- dataset_dir: The dataset directory where the dataset is stored.
- """
- if not tf.gfile.Exists(dataset_dir):
- tf.gfile.MakeDirs(dataset_dir)
-
- train_filename = _get_output_filename(dataset_dir, 'train')
- testing_filename = _get_output_filename(dataset_dir, 'test')
-
- if tf.gfile.Exists(train_filename) and tf.gfile.Exists(testing_filename):
- print('Dataset files already exist. Exiting without re-creating them.')
- return
-
- # TODO(konstantinos): Add download and cleanup functionality
-
- train_validation_filenames = _get_filenames(
- os.path.join(dataset_dir, 'mnist_m', 'mnist_m_train'))
- test_filenames = _get_filenames(
- os.path.join(dataset_dir, 'mnist_m', 'mnist_m_test'))
-
- # Divide into train and validation:
- random.seed(_RANDOM_SEED)
- random.shuffle(train_validation_filenames)
- train_filenames = train_validation_filenames[_NUM_VALIDATION:]
- validation_filenames = train_validation_filenames[:_NUM_VALIDATION]
-
- train_validation_filenames_to_class_ids = _extract_labels(
- os.path.join(dataset_dir, 'mnist_m', 'mnist_m_train_labels.txt'))
- test_filenames_to_class_ids = _extract_labels(
- os.path.join(dataset_dir, 'mnist_m', 'mnist_m_test_labels.txt'))
-
- # Convert the train, validation, and test sets.
- _convert_dataset('train', train_filenames,
- train_validation_filenames_to_class_ids, dataset_dir)
- _convert_dataset('valid', validation_filenames,
- train_validation_filenames_to_class_ids, dataset_dir)
- _convert_dataset('test', test_filenames, test_filenames_to_class_ids,
- dataset_dir)
-
- # Finally, write the labels file:
- labels_to_class_names = dict(zip(range(len(_CLASS_NAMES)), _CLASS_NAMES))
- dataset_utils.write_label_file(labels_to_class_names, dataset_dir)
-
- print('\nFinished converting the MNIST-M dataset!')
-
-
-def main(_):
- assert FLAGS.dataset_dir
- run(FLAGS.dataset_dir)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/domain_adaptation/datasets/mnist_m.py b/research/domain_adaptation/datasets/mnist_m.py
deleted file mode 100644
index fab6c443cf3d2e9783d19bf52c81b7aa62d56a38..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/datasets/mnist_m.py
+++ /dev/null
@@ -1,98 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Provides data for the MNIST-M dataset.
-
-The dataset scripts used to create the dataset can be found at:
-tensorflow_models/domain_adaptation_/datasets/download_and_convert_mnist_m_dataset.py
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-# Dependency imports
-import tensorflow as tf
-
-from slim.datasets import dataset_utils
-
-slim = tf.contrib.slim
-
-_FILE_PATTERN = 'mnist_m_%s.tfrecord'
-
-_SPLITS_TO_SIZES = {'train': 58001, 'valid': 1000, 'test': 9001}
-
-_NUM_CLASSES = 10
-
-_ITEMS_TO_DESCRIPTIONS = {
- 'image': 'A [32 x 32 x 1] RGB image.',
- 'label': 'A single integer between 0 and 9',
-}
-
-
-def get_split(split_name, dataset_dir, file_pattern=None, reader=None):
- """Gets a dataset tuple with instructions for reading MNIST.
-
- Args:
- split_name: A train/test split name.
- dataset_dir: The base directory of the dataset sources.
-
- Returns:
- A `Dataset` namedtuple.
-
- Raises:
- ValueError: if `split_name` is not a valid train/test split.
- """
- if split_name not in _SPLITS_TO_SIZES:
- raise ValueError('split name %s was not recognized.' % split_name)
-
- if not file_pattern:
- file_pattern = _FILE_PATTERN
- file_pattern = os.path.join(dataset_dir, file_pattern % split_name)
-
- # Allowing None in the signature so that dataset_factory can use the default.
- if reader is None:
- reader = tf.TFRecordReader
-
- keys_to_features = {
- 'image/encoded':
- tf.FixedLenFeature((), tf.string, default_value=''),
- 'image/format':
- tf.FixedLenFeature((), tf.string, default_value='png'),
- 'image/class/label':
- tf.FixedLenFeature(
- [1], tf.int64, default_value=tf.zeros([1], dtype=tf.int64)),
- }
-
- items_to_handlers = {
- 'image': slim.tfexample_decoder.Image(shape=[32, 32, 3], channels=3),
- 'label': slim.tfexample_decoder.Tensor('image/class/label', shape=[]),
- }
-
- decoder = slim.tfexample_decoder.TFExampleDecoder(
- keys_to_features, items_to_handlers)
-
- labels_to_names = None
- if dataset_utils.has_labels(dataset_dir):
- labels_to_names = dataset_utils.read_label_file(dataset_dir)
-
- return slim.dataset.Dataset(
- data_sources=file_pattern,
- reader=reader,
- decoder=decoder,
- num_samples=_SPLITS_TO_SIZES[split_name],
- num_classes=_NUM_CLASSES,
- items_to_descriptions=_ITEMS_TO_DESCRIPTIONS,
- labels_to_names=labels_to_names)
diff --git a/research/domain_adaptation/domain_separation/BUILD b/research/domain_adaptation/domain_separation/BUILD
deleted file mode 100644
index 14dceda27e49d74eaaaeae21676183b78c72b9c2..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/domain_separation/BUILD
+++ /dev/null
@@ -1,157 +0,0 @@
-# Domain Separation Networks
-
-package(
- default_visibility = [
- ":internal",
- ],
-)
-
-licenses(["notice"]) # Apache 2.0
-
-exports_files(["LICENSE"])
-
-package_group(
- name = "internal",
- packages = [
- "//domain_adaptation/...",
- ],
-)
-
-py_library(
- name = "models",
- srcs = [
- "models.py",
- ],
- deps = [
- ":utils",
- ],
-)
-
-py_library(
- name = "losses",
- srcs = [
- "losses.py",
- ],
- deps = [
- ":grl_op_grads_py",
- ":grl_op_shapes_py",
- ":grl_ops",
- ":utils",
- ],
-)
-
-py_test(
- name = "losses_test",
- srcs = [
- "losses_test.py",
- ],
- deps = [
- ":losses",
- ":utils",
- ],
-)
-
-py_library(
- name = "dsn",
- srcs = [
- "dsn.py",
- ],
- deps = [
- ":grl_op_grads_py",
- ":grl_op_shapes_py",
- ":grl_ops",
- ":losses",
- ":models",
- ":utils",
- ],
-)
-
-py_test(
- name = "dsn_test",
- srcs = [
- "dsn_test.py",
- ],
- deps = [
- ":dsn",
- ],
-)
-
-py_binary(
- name = "dsn_train",
- srcs = [
- "dsn_train.py",
- ],
- deps = [
- ":dsn",
- ":models",
- "//domain_adaptation/datasets:dataset_factory",
- ],
-)
-
-py_binary(
- name = "dsn_eval",
- srcs = [
- "dsn_eval.py",
- ],
- deps = [
- ":dsn",
- ":models",
- "//domain_adaptation/datasets:dataset_factory",
- ],
-)
-
-py_test(
- name = "models_test",
- srcs = [
- "models_test.py",
- ],
- deps = [
- ":models",
- "//domain_adaptation/datasets:dataset_factory",
- ],
-)
-
-py_library(
- name = "utils",
- srcs = [
- "utils.py",
- ],
- deps = [
- ],
-)
-
-py_library(
- name = "grl_op_grads_py",
- srcs = [
- "grl_op_grads.py",
- ],
- deps = [
- ":grl_ops",
- ],
-)
-
-py_library(
- name = "grl_op_shapes_py",
- srcs = [
- "grl_op_shapes.py",
- ],
- deps = [
- ],
-)
-
-py_library(
- name = "grl_ops",
- srcs = ["grl_ops.py"],
- data = ["_grl_ops.so"],
-)
-
-py_test(
- name = "grl_ops_test",
- size = "small",
- srcs = ["grl_ops_test.py"],
- deps = [
- ":grl_op_grads_py",
- ":grl_op_shapes_py",
- ":grl_ops",
- ],
-)
diff --git a/research/domain_adaptation/domain_separation/__init__.py b/research/domain_adaptation/domain_separation/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/domain_adaptation/domain_separation/_grl_ops.so b/research/domain_adaptation/domain_separation/_grl_ops.so
deleted file mode 100755
index 4c35473760a76dcb743d58f45eddccecb5f5161e..0000000000000000000000000000000000000000
Binary files a/research/domain_adaptation/domain_separation/_grl_ops.so and /dev/null differ
diff --git a/research/domain_adaptation/domain_separation/dsn.py b/research/domain_adaptation/domain_separation/dsn.py
deleted file mode 100644
index 3018e8a791840ae465bad493913235cc04c31cff..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/domain_separation/dsn.py
+++ /dev/null
@@ -1,355 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Functions to create a DSN model and add the different losses to it.
-
-Specifically, in this file we define the:
- - Shared Encoding Similarity Loss Module, with:
- - The MMD Similarity method
- - The Correlation Similarity method
- - The Gradient Reversal (Domain-Adversarial) method
- - Difference Loss Module
- - Reconstruction Loss Module
- - Task Loss Module
-"""
-from functools import partial
-
-import tensorflow as tf
-
-import losses
-import models
-import utils
-
-slim = tf.contrib.slim
-
-
-################################################################################
-# HELPER FUNCTIONS
-################################################################################
-def dsn_loss_coefficient(params):
- """The global_step-dependent weight that specifies when to kick in DSN losses.
-
- Args:
- params: A dictionary of parameters. Expecting 'domain_separation_startpoint'
-
- Returns:
- A weight to that effectively enables or disables the DSN-related losses,
- i.e. similarity, difference, and reconstruction losses.
- """
- return tf.where(
- tf.less(slim.get_or_create_global_step(),
- params['domain_separation_startpoint']), 1e-10, 1.0)
-
-
-################################################################################
-# MODEL CREATION
-################################################################################
-def create_model(source_images, source_labels, domain_selection_mask,
- target_images, target_labels, similarity_loss, params,
- basic_tower_name):
- """Creates a DSN model.
-
- Args:
- source_images: images from the source domain, a tensor of size
- [batch_size, height, width, channels]
- source_labels: a dictionary with the name, tensor pairs. 'classes' is one-
- hot for the number of classes.
- domain_selection_mask: a boolean tensor of size [batch_size, ] which denotes
- the labeled images that belong to the source domain.
- target_images: images from the target domain, a tensor of size
- [batch_size, height width, channels].
- target_labels: a dictionary with the name, tensor pairs.
- similarity_loss: The type of method to use for encouraging
- the codes from the shared encoder to be similar.
- params: A dictionary of parameters. Expecting 'weight_decay',
- 'layers_to_regularize', 'use_separation', 'domain_separation_startpoint',
- 'alpha_weight', 'beta_weight', 'gamma_weight', 'recon_loss_name',
- 'decoder_name', 'encoder_name'
- basic_tower_name: the name of the tower to use for the shared encoder.
-
- Raises:
- ValueError: if the arch is not one of the available architectures.
- """
- network = getattr(models, basic_tower_name)
- num_classes = source_labels['classes'].get_shape().as_list()[1]
-
- # Make sure we are using the appropriate number of classes.
- network = partial(network, num_classes=num_classes)
-
- # Add the classification/pose estimation loss to the source domain.
- source_endpoints = add_task_loss(source_images, source_labels, network,
- params)
-
- if similarity_loss == 'none':
- # No domain adaptation, we can stop here.
- return
-
- with tf.variable_scope('towers', reuse=True):
- target_logits, target_endpoints = network(
- target_images, weight_decay=params['weight_decay'], prefix='target')
-
- # Plot target accuracy of the train set.
- target_accuracy = utils.accuracy(
- tf.argmax(target_logits, 1), tf.argmax(target_labels['classes'], 1))
-
- if 'quaternions' in target_labels:
- target_quaternion_loss = losses.log_quaternion_loss(
- target_labels['quaternions'], target_endpoints['quaternion_pred'],
- params)
- tf.summary.scalar('eval/Target quaternions', target_quaternion_loss)
-
- tf.summary.scalar('eval/Target accuracy', target_accuracy)
-
- source_shared = source_endpoints[params['layers_to_regularize']]
- target_shared = target_endpoints[params['layers_to_regularize']]
-
- # When using the semisupervised model we include labeled target data in the
- # source classifier. We do not want to include these target domain when
- # we use the similarity loss.
- indices = tf.range(0, source_shared.get_shape().as_list()[0])
- indices = tf.boolean_mask(indices, domain_selection_mask)
- add_similarity_loss(similarity_loss,
- tf.gather(source_shared, indices),
- tf.gather(target_shared, indices), params)
-
- if params['use_separation']:
- add_autoencoders(
- source_images,
- source_shared,
- target_images,
- target_shared,
- params=params,)
-
-
-def add_similarity_loss(method_name,
- source_samples,
- target_samples,
- params,
- scope=None):
- """Adds a loss encouraging the shared encoding from each domain to be similar.
-
- Args:
- method_name: the name of the encoding similarity method to use. Valid
- options include `dann_loss', `mmd_loss' or `correlation_loss'.
- source_samples: a tensor of shape [num_samples, num_features].
- target_samples: a tensor of shape [num_samples, num_features].
- params: a dictionary of parameters. Expecting 'gamma_weight'.
- scope: optional name scope for summary tags.
- Raises:
- ValueError: if `method_name` is not recognized.
- """
- weight = dsn_loss_coefficient(params) * params['gamma_weight']
- method = getattr(losses, method_name)
- method(source_samples, target_samples, weight, scope)
-
-
-def add_reconstruction_loss(recon_loss_name, images, recons, weight, domain):
- """Adds a reconstruction loss.
-
- Args:
- recon_loss_name: The name of the reconstruction loss.
- images: A `Tensor` of size [batch_size, height, width, 3].
- recons: A `Tensor` whose size matches `images`.
- weight: A scalar coefficient for the loss.
- domain: The name of the domain being reconstructed.
-
- Raises:
- ValueError: If `recon_loss_name` is not recognized.
- """
- if recon_loss_name == 'sum_of_pairwise_squares':
- loss_fn = tf.contrib.losses.mean_pairwise_squared_error
- elif recon_loss_name == 'sum_of_squares':
- loss_fn = tf.contrib.losses.mean_squared_error
- else:
- raise ValueError('recon_loss_name value [%s] not recognized.' %
- recon_loss_name)
-
- loss = loss_fn(recons, images, weight)
- assert_op = tf.Assert(tf.is_finite(loss), [loss])
- with tf.control_dependencies([assert_op]):
- tf.summary.scalar('losses/%s Recon Loss' % domain, loss)
-
-
-def add_autoencoders(source_data, source_shared, target_data, target_shared,
- params):
- """Adds the encoders/decoders for our domain separation model w/ incoherence.
-
- Args:
- source_data: images from the source domain, a tensor of size
- [batch_size, height, width, channels]
- source_shared: a tensor with first dimension batch_size
- target_data: images from the target domain, a tensor of size
- [batch_size, height, width, channels]
- target_shared: a tensor with first dimension batch_size
- params: A dictionary of parameters. Expecting 'layers_to_regularize',
- 'beta_weight', 'alpha_weight', 'recon_loss_name', 'decoder_name',
- 'encoder_name', 'weight_decay'
- """
-
- def normalize_images(images):
- images -= tf.reduce_min(images)
- return images / tf.reduce_max(images)
-
- def concat_operation(shared_repr, private_repr):
- return shared_repr + private_repr
-
- mu = dsn_loss_coefficient(params)
-
- # The layer to concatenate the networks at.
- concat_layer = params['layers_to_regularize']
-
- # The coefficient for modulating the private/shared difference loss.
- difference_loss_weight = params['beta_weight'] * mu
-
- # The reconstruction weight.
- recon_loss_weight = params['alpha_weight'] * mu
-
- # The reconstruction loss to use.
- recon_loss_name = params['recon_loss_name']
-
- # The decoder/encoder to use.
- decoder_name = params['decoder_name']
- encoder_name = params['encoder_name']
-
- _, height, width, _ = source_data.get_shape().as_list()
- code_size = source_shared.get_shape().as_list()[-1]
- weight_decay = params['weight_decay']
-
- encoder_fn = getattr(models, encoder_name)
- # Target Auto-encoding.
- with tf.variable_scope('source_encoder'):
- source_endpoints = encoder_fn(
- source_data, code_size, weight_decay=weight_decay)
-
- with tf.variable_scope('target_encoder'):
- target_endpoints = encoder_fn(
- target_data, code_size, weight_decay=weight_decay)
-
- decoder_fn = getattr(models, decoder_name)
-
- decoder = partial(
- decoder_fn,
- height=height,
- width=width,
- channels=source_data.get_shape().as_list()[-1],
- weight_decay=weight_decay)
-
- # Source Auto-encoding.
- source_private = source_endpoints[concat_layer]
- target_private = target_endpoints[concat_layer]
- with tf.variable_scope('decoder'):
- source_recons = decoder(concat_operation(source_shared, source_private))
-
- with tf.variable_scope('decoder', reuse=True):
- source_private_recons = decoder(
- concat_operation(tf.zeros_like(source_private), source_private))
- source_shared_recons = decoder(
- concat_operation(source_shared, tf.zeros_like(source_shared)))
-
- with tf.variable_scope('decoder', reuse=True):
- target_recons = decoder(concat_operation(target_shared, target_private))
- target_shared_recons = decoder(
- concat_operation(target_shared, tf.zeros_like(target_shared)))
- target_private_recons = decoder(
- concat_operation(tf.zeros_like(target_private), target_private))
-
- losses.difference_loss(
- source_private,
- source_shared,
- weight=difference_loss_weight,
- name='Source')
- losses.difference_loss(
- target_private,
- target_shared,
- weight=difference_loss_weight,
- name='Target')
-
- add_reconstruction_loss(recon_loss_name, source_data, source_recons,
- recon_loss_weight, 'source')
- add_reconstruction_loss(recon_loss_name, target_data, target_recons,
- recon_loss_weight, 'target')
-
- # Add summaries
- source_reconstructions = tf.concat(
- axis=2,
- values=map(normalize_images, [
- source_data, source_recons, source_shared_recons,
- source_private_recons
- ]))
- target_reconstructions = tf.concat(
- axis=2,
- values=map(normalize_images, [
- target_data, target_recons, target_shared_recons,
- target_private_recons
- ]))
- tf.summary.image(
- 'Source Images:Recons:RGB',
- source_reconstructions[:, :, :, :3],
- max_outputs=10)
- tf.summary.image(
- 'Target Images:Recons:RGB',
- target_reconstructions[:, :, :, :3],
- max_outputs=10)
-
- if source_reconstructions.get_shape().as_list()[3] == 4:
- tf.summary.image(
- 'Source Images:Recons:Depth',
- source_reconstructions[:, :, :, 3:4],
- max_outputs=10)
- tf.summary.image(
- 'Target Images:Recons:Depth',
- target_reconstructions[:, :, :, 3:4],
- max_outputs=10)
-
-
-def add_task_loss(source_images, source_labels, basic_tower, params):
- """Adds a classification and/or pose estimation loss to the model.
-
- Args:
- source_images: images from the source domain, a tensor of size
- [batch_size, height, width, channels]
- source_labels: labels from the source domain, a tensor of size [batch_size].
- or a tuple of (quaternions, class_labels)
- basic_tower: a function that creates the single tower of the model.
- params: A dictionary of parameters. Expecting 'weight_decay', 'pose_weight'.
- Returns:
- The source endpoints.
-
- Raises:
- RuntimeError: if basic tower does not support pose estimation.
- """
- with tf.variable_scope('towers'):
- source_logits, source_endpoints = basic_tower(
- source_images, weight_decay=params['weight_decay'], prefix='Source')
-
- if 'quaternions' in source_labels: # We have pose estimation as well
- if 'quaternion_pred' not in source_endpoints:
- raise RuntimeError('Please use a model for estimation e.g. pose_mini')
-
- loss = losses.log_quaternion_loss(source_labels['quaternions'],
- source_endpoints['quaternion_pred'],
- params)
-
- assert_op = tf.Assert(tf.is_finite(loss), [loss])
- with tf.control_dependencies([assert_op]):
- quaternion_loss = loss
- tf.summary.histogram('log_quaternion_loss_hist', quaternion_loss)
- slim.losses.add_loss(quaternion_loss * params['pose_weight'])
- tf.summary.scalar('losses/quaternion_loss', quaternion_loss)
-
- classification_loss = tf.losses.softmax_cross_entropy(
- source_labels['classes'], source_logits)
-
- tf.summary.scalar('losses/classification_loss', classification_loss)
- return source_endpoints
diff --git a/research/domain_adaptation/domain_separation/dsn_eval.py b/research/domain_adaptation/domain_separation/dsn_eval.py
deleted file mode 100644
index b6cccdfcc17e8f18e8381530b5c8f41501bda29b..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/domain_separation/dsn_eval.py
+++ /dev/null
@@ -1,161 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-# pylint: disable=line-too-long
-"""Evaluation for Domain Separation Networks (DSNs)."""
-# pylint: enable=line-too-long
-import math
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-from domain_adaptation.datasets import dataset_factory
-from domain_adaptation.domain_separation import losses
-from domain_adaptation.domain_separation import models
-
-slim = tf.contrib.slim
-
-FLAGS = tf.app.flags.FLAGS
-
-tf.app.flags.DEFINE_integer('batch_size', 32,
- 'The number of images in each batch.')
-
-tf.app.flags.DEFINE_string('master', '',
- 'BNS name of the TensorFlow master to use.')
-
-tf.app.flags.DEFINE_string('checkpoint_dir', '/tmp/da/',
- 'Directory where the model was written to.')
-
-tf.app.flags.DEFINE_string(
- 'eval_dir', '/tmp/da/',
- 'Directory where we should write the tf summaries to.')
-
-tf.app.flags.DEFINE_string('dataset_dir', None,
- 'The directory where the dataset files are stored.')
-
-tf.app.flags.DEFINE_string('dataset', 'mnist_m',
- 'Which dataset to test on: "mnist", "mnist_m".')
-
-tf.app.flags.DEFINE_string('split', 'valid',
- 'Which portion to test on: "valid", "test".')
-
-tf.app.flags.DEFINE_integer('num_examples', 1000, 'Number of test examples.')
-
-tf.app.flags.DEFINE_string('basic_tower', 'dann_mnist',
- 'The basic tower building block.')
-
-tf.app.flags.DEFINE_bool('enable_precision_recall', False,
- 'If True, precision and recall for each class will '
- 'be added to the metrics.')
-
-tf.app.flags.DEFINE_bool('use_logging', False, 'Debugging messages.')
-
-
-def quaternion_metric(predictions, labels):
- params = {'batch_size': FLAGS.batch_size, 'use_logging': False}
- logcost = losses.log_quaternion_loss_batch(predictions, labels, params)
- return slim.metrics.streaming_mean(logcost)
-
-
-def angle_diff(true_q, pred_q):
- angles = 2 * (
- 180.0 /
- np.pi) * np.arccos(np.abs(np.sum(np.multiply(pred_q, true_q), axis=1)))
- return angles
-
-
-def provide_batch_fn():
- """ The provide_batch function to use. """
- return dataset_factory.provide_batch
-
-
-def main(_):
- g = tf.Graph()
- with g.as_default():
- # Load the data.
- images, labels = provide_batch_fn()(
- FLAGS.dataset, FLAGS.split, FLAGS.dataset_dir, 4, FLAGS.batch_size, 4)
-
- num_classes = labels['classes'].get_shape().as_list()[1]
-
- tf.summary.image('eval_images', images, max_outputs=3)
-
- # Define the model:
- with tf.variable_scope('towers'):
- basic_tower = getattr(models, FLAGS.basic_tower)
- predictions, endpoints = basic_tower(
- images,
- num_classes=num_classes,
- is_training=False,
- batch_norm_params=None)
- metric_names_to_values = {}
-
- # Define the metrics:
- if 'quaternions' in labels: # Also have to evaluate pose estimation!
- quaternion_loss = quaternion_metric(labels['quaternions'],
- endpoints['quaternion_pred'])
-
- angle_errors, = tf.py_func(
- angle_diff, [labels['quaternions'], endpoints['quaternion_pred']],
- [tf.float32])
-
- metric_names_to_values[
- 'Angular mean error'] = slim.metrics.streaming_mean(angle_errors)
- metric_names_to_values['Quaternion Loss'] = quaternion_loss
-
- accuracy = tf.contrib.metrics.streaming_accuracy(
- tf.argmax(predictions, 1), tf.argmax(labels['classes'], 1))
-
- predictions = tf.argmax(predictions, 1)
- labels = tf.argmax(labels['classes'], 1)
- metric_names_to_values['Accuracy'] = accuracy
-
- if FLAGS.enable_precision_recall:
- for i in xrange(num_classes):
- index_map = tf.one_hot(i, depth=num_classes)
- name = 'PR/Precision_{}'.format(i)
- metric_names_to_values[name] = slim.metrics.streaming_precision(
- tf.gather(index_map, predictions), tf.gather(index_map, labels))
- name = 'PR/Recall_{}'.format(i)
- metric_names_to_values[name] = slim.metrics.streaming_recall(
- tf.gather(index_map, predictions), tf.gather(index_map, labels))
-
- names_to_values, names_to_updates = slim.metrics.aggregate_metric_map(
- metric_names_to_values)
-
- # Create the summary ops such that they also print out to std output:
- summary_ops = []
- for metric_name, metric_value in names_to_values.iteritems():
- op = tf.summary.scalar(metric_name, metric_value)
- op = tf.Print(op, [metric_value], metric_name)
- summary_ops.append(op)
-
- # This ensures that we make a single pass over all of the data.
- num_batches = math.ceil(FLAGS.num_examples / float(FLAGS.batch_size))
-
- # Setup the global step.
- slim.get_or_create_global_step()
- slim.evaluation.evaluation_loop(
- FLAGS.master,
- checkpoint_dir=FLAGS.checkpoint_dir,
- logdir=FLAGS.eval_dir,
- num_evals=num_batches,
- eval_op=names_to_updates.values(),
- summary_op=tf.summary.merge(summary_ops))
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/domain_adaptation/domain_separation/dsn_test.py b/research/domain_adaptation/domain_separation/dsn_test.py
deleted file mode 100644
index 3d687398a9b9356455f739417bc96ddb2ca5ad40..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/domain_separation/dsn_test.py
+++ /dev/null
@@ -1,157 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tests for DSN model assembly functions."""
-
-import numpy as np
-import tensorflow as tf
-
-import dsn
-
-
-class HelperFunctionsTest(tf.test.TestCase):
-
- def testBasicDomainSeparationStartPoint(self):
- with self.test_session() as sess:
- # Test for when global_step < domain_separation_startpoint
- step = tf.contrib.slim.get_or_create_global_step()
- sess.run(tf.global_variables_initializer()) # global_step = 0
- params = {'domain_separation_startpoint': 2}
- weight = dsn.dsn_loss_coefficient(params)
- weight_np = sess.run(weight)
- self.assertAlmostEqual(weight_np, 1e-10)
-
- step_op = tf.assign_add(step, 1)
- step_np = sess.run(step_op) # global_step = 1
- weight = dsn.dsn_loss_coefficient(params)
- weight_np = sess.run(weight)
- self.assertAlmostEqual(weight_np, 1e-10)
-
- # Test for when global_step >= domain_separation_startpoint
- step_np = sess.run(step_op) # global_step = 2
- tf.logging.info(step_np)
- weight = dsn.dsn_loss_coefficient(params)
- weight_np = sess.run(weight)
- self.assertAlmostEqual(weight_np, 1.0)
-
-
-class DsnModelAssemblyTest(tf.test.TestCase):
-
- def _testBuildDefaultModel(self):
- images = tf.to_float(np.random.rand(32, 28, 28, 1))
- labels = {}
- labels['classes'] = tf.one_hot(
- tf.to_int32(np.random.randint(0, 9, (32))), 10)
-
- params = {
- 'use_separation': True,
- 'layers_to_regularize': 'fc3',
- 'weight_decay': 0.0,
- 'ps_tasks': 1,
- 'domain_separation_startpoint': 1,
- 'alpha_weight': 1,
- 'beta_weight': 1,
- 'gamma_weight': 1,
- 'recon_loss_name': 'sum_of_squares',
- 'decoder_name': 'small_decoder',
- 'encoder_name': 'default_encoder',
- }
- return images, labels, params
-
- def testBuildModelDann(self):
- images, labels, params = self._testBuildDefaultModel()
-
- with self.test_session():
- dsn.create_model(images, labels,
- tf.cast(tf.ones([32,]), tf.bool), images, labels,
- 'dann_loss', params, 'dann_mnist')
- loss_tensors = tf.contrib.losses.get_losses()
- self.assertEqual(len(loss_tensors), 6)
-
- def testBuildModelDannSumOfPairwiseSquares(self):
- images, labels, params = self._testBuildDefaultModel()
-
- with self.test_session():
- dsn.create_model(images, labels,
- tf.cast(tf.ones([32,]), tf.bool), images, labels,
- 'dann_loss', params, 'dann_mnist')
- loss_tensors = tf.contrib.losses.get_losses()
- self.assertEqual(len(loss_tensors), 6)
-
- def testBuildModelDannMultiPSTasks(self):
- images, labels, params = self._testBuildDefaultModel()
- params['ps_tasks'] = 10
- with self.test_session():
- dsn.create_model(images, labels,
- tf.cast(tf.ones([32,]), tf.bool), images, labels,
- 'dann_loss', params, 'dann_mnist')
- loss_tensors = tf.contrib.losses.get_losses()
- self.assertEqual(len(loss_tensors), 6)
-
- def testBuildModelMmd(self):
- images, labels, params = self._testBuildDefaultModel()
-
- with self.test_session():
- dsn.create_model(images, labels,
- tf.cast(tf.ones([32,]), tf.bool), images, labels,
- 'mmd_loss', params, 'dann_mnist')
- loss_tensors = tf.contrib.losses.get_losses()
- self.assertEqual(len(loss_tensors), 6)
-
- def testBuildModelCorr(self):
- images, labels, params = self._testBuildDefaultModel()
-
- with self.test_session():
- dsn.create_model(images, labels,
- tf.cast(tf.ones([32,]), tf.bool), images, labels,
- 'correlation_loss', params, 'dann_mnist')
- loss_tensors = tf.contrib.losses.get_losses()
- self.assertEqual(len(loss_tensors), 6)
-
- def testBuildModelNoDomainAdaptation(self):
- images, labels, params = self._testBuildDefaultModel()
- params['use_separation'] = False
- with self.test_session():
- dsn.create_model(images, labels,
- tf.cast(tf.ones([32,]), tf.bool), images, labels, 'none',
- params, 'dann_mnist')
- loss_tensors = tf.contrib.losses.get_losses()
- self.assertEqual(len(loss_tensors), 1)
- self.assertEqual(len(tf.contrib.losses.get_regularization_losses()), 0)
-
- def testBuildModelNoAdaptationWeightDecay(self):
- images, labels, params = self._testBuildDefaultModel()
- params['use_separation'] = False
- params['weight_decay'] = 1e-5
- with self.test_session():
- dsn.create_model(images, labels,
- tf.cast(tf.ones([32,]), tf.bool), images, labels, 'none',
- params, 'dann_mnist')
- loss_tensors = tf.contrib.losses.get_losses()
- self.assertEqual(len(loss_tensors), 1)
- self.assertTrue(len(tf.contrib.losses.get_regularization_losses()) >= 1)
-
- def testBuildModelNoSeparation(self):
- images, labels, params = self._testBuildDefaultModel()
- params['use_separation'] = False
- with self.test_session():
- dsn.create_model(images, labels,
- tf.cast(tf.ones([32,]), tf.bool), images, labels,
- 'dann_loss', params, 'dann_mnist')
- loss_tensors = tf.contrib.losses.get_losses()
- self.assertEqual(len(loss_tensors), 2)
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/domain_adaptation/domain_separation/dsn_train.py b/research/domain_adaptation/domain_separation/dsn_train.py
deleted file mode 100644
index 5e364ad3037b041125a3523370b3b040478f0d8e..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/domain_separation/dsn_train.py
+++ /dev/null
@@ -1,278 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Training for Domain Separation Networks (DSNs)."""
-from __future__ import division
-
-import tensorflow as tf
-
-from domain_adaptation.datasets import dataset_factory
-import dsn
-
-slim = tf.contrib.slim
-FLAGS = tf.app.flags.FLAGS
-
-tf.app.flags.DEFINE_integer('batch_size', 32,
- 'The number of images in each batch.')
-
-tf.app.flags.DEFINE_string('source_dataset', 'pose_synthetic',
- 'Source dataset to train on.')
-
-tf.app.flags.DEFINE_string('target_dataset', 'pose_real',
- 'Target dataset to train on.')
-
-tf.app.flags.DEFINE_string('target_labeled_dataset', 'none',
- 'Target dataset to train on.')
-
-tf.app.flags.DEFINE_string('dataset_dir', None,
- 'The directory where the dataset files are stored.')
-
-tf.app.flags.DEFINE_string('master', '',
- 'BNS name of the TensorFlow master to use.')
-
-tf.app.flags.DEFINE_string('train_log_dir', '/tmp/da/',
- 'Directory where to write event logs.')
-
-tf.app.flags.DEFINE_string(
- 'layers_to_regularize', 'fc3',
- 'Comma-separated list of layer names to use MMD regularization on.')
-
-tf.app.flags.DEFINE_float('learning_rate', .01, 'The learning rate')
-
-tf.app.flags.DEFINE_float('alpha_weight', 1e-6,
- 'The coefficient for scaling the reconstruction '
- 'loss.')
-
-tf.app.flags.DEFINE_float(
- 'beta_weight', 1e-6,
- 'The coefficient for scaling the private/shared difference loss.')
-
-tf.app.flags.DEFINE_float(
- 'gamma_weight', 1e-6,
- 'The coefficient for scaling the shared encoding similarity loss.')
-
-tf.app.flags.DEFINE_float('pose_weight', 0.125,
- 'The coefficient for scaling the pose loss.')
-
-tf.app.flags.DEFINE_float(
- 'weight_decay', 1e-6,
- 'The coefficient for the L2 regularization applied for all weights.')
-
-tf.app.flags.DEFINE_integer(
- 'save_summaries_secs', 60,
- 'The frequency with which summaries are saved, in seconds.')
-
-tf.app.flags.DEFINE_integer(
- 'save_interval_secs', 60,
- 'The frequency with which the model is saved, in seconds.')
-
-tf.app.flags.DEFINE_integer(
- 'max_number_of_steps', None,
- 'The maximum number of gradient steps. Use None to train indefinitely.')
-
-tf.app.flags.DEFINE_integer(
- 'domain_separation_startpoint', 1,
- 'The global step to add the domain separation losses.')
-
-tf.app.flags.DEFINE_integer(
- 'bipartite_assignment_top_k', 3,
- 'The number of top-k matches to use in bipartite matching adaptation.')
-
-tf.app.flags.DEFINE_float('decay_rate', 0.95, 'Learning rate decay factor.')
-
-tf.app.flags.DEFINE_integer('decay_steps', 20000, 'Learning rate decay steps.')
-
-tf.app.flags.DEFINE_float('momentum', 0.9, 'The momentum value.')
-
-tf.app.flags.DEFINE_bool('use_separation', False,
- 'Use our domain separation model.')
-
-tf.app.flags.DEFINE_bool('use_logging', False, 'Debugging messages.')
-
-tf.app.flags.DEFINE_integer(
- 'ps_tasks', 0,
- 'The number of parameter servers. If the value is 0, then the parameters '
- 'are handled locally by the worker.')
-
-tf.app.flags.DEFINE_integer(
- 'num_readers', 4,
- 'The number of parallel readers that read data from the dataset.')
-
-tf.app.flags.DEFINE_integer('num_preprocessing_threads', 4,
- 'The number of threads used to create the batches.')
-
-tf.app.flags.DEFINE_integer(
- 'task', 0,
- 'The Task ID. This value is used when training with multiple workers to '
- 'identify each worker.')
-
-tf.app.flags.DEFINE_string('decoder_name', 'small_decoder',
- 'The decoder to use.')
-tf.app.flags.DEFINE_string('encoder_name', 'default_encoder',
- 'The encoder to use.')
-
-################################################################################
-# Flags that control the architecture and losses
-################################################################################
-tf.app.flags.DEFINE_string(
- 'similarity_loss', 'grl',
- 'The method to use for encouraging the common encoder codes to be '
- 'similar, one of "grl", "mmd", "corr".')
-
-tf.app.flags.DEFINE_string('recon_loss_name', 'sum_of_pairwise_squares',
- 'The name of the reconstruction loss.')
-
-tf.app.flags.DEFINE_string('basic_tower', 'pose_mini',
- 'The basic tower building block.')
-
-def provide_batch_fn():
- """ The provide_batch function to use. """
- return dataset_factory.provide_batch
-
-def main(_):
- model_params = {
- 'use_separation': FLAGS.use_separation,
- 'domain_separation_startpoint': FLAGS.domain_separation_startpoint,
- 'layers_to_regularize': FLAGS.layers_to_regularize,
- 'alpha_weight': FLAGS.alpha_weight,
- 'beta_weight': FLAGS.beta_weight,
- 'gamma_weight': FLAGS.gamma_weight,
- 'pose_weight': FLAGS.pose_weight,
- 'recon_loss_name': FLAGS.recon_loss_name,
- 'decoder_name': FLAGS.decoder_name,
- 'encoder_name': FLAGS.encoder_name,
- 'weight_decay': FLAGS.weight_decay,
- 'batch_size': FLAGS.batch_size,
- 'use_logging': FLAGS.use_logging,
- 'ps_tasks': FLAGS.ps_tasks,
- 'task': FLAGS.task,
- }
- g = tf.Graph()
- with g.as_default():
- with tf.device(tf.train.replica_device_setter(FLAGS.ps_tasks)):
- # Load the data.
- source_images, source_labels = provide_batch_fn()(
- FLAGS.source_dataset, 'train', FLAGS.dataset_dir, FLAGS.num_readers,
- FLAGS.batch_size, FLAGS.num_preprocessing_threads)
- target_images, target_labels = provide_batch_fn()(
- FLAGS.target_dataset, 'train', FLAGS.dataset_dir, FLAGS.num_readers,
- FLAGS.batch_size, FLAGS.num_preprocessing_threads)
-
- # In the unsupervised case all the samples in the labeled
- # domain are from the source domain.
- domain_selection_mask = tf.fill((source_images.get_shape().as_list()[0],),
- True)
-
- # When using the semisupervised model we include labeled target data in
- # the source labelled data.
- if FLAGS.target_labeled_dataset != 'none':
- # 1000 is the maximum number of labelled target samples that exists in
- # the datasets.
- target_semi_images, target_semi_labels = provide_batch_fn()(
- FLAGS.target_labeled_dataset, 'train', FLAGS.batch_size)
-
- # Calculate the proportion of source domain samples in the semi-
- # supervised setting, so that the proportion is set accordingly in the
- # batches.
- proportion = float(source_labels['num_train_samples']) / (
- source_labels['num_train_samples'] +
- target_semi_labels['num_train_samples'])
-
- rnd_tensor = tf.random_uniform(
- (target_semi_images.get_shape().as_list()[0],))
-
- domain_selection_mask = rnd_tensor < proportion
- source_images = tf.where(domain_selection_mask, source_images,
- target_semi_images)
- source_class_labels = tf.where(domain_selection_mask,
- source_labels['classes'],
- target_semi_labels['classes'])
-
- if 'quaternions' in source_labels:
- source_pose_labels = tf.where(domain_selection_mask,
- source_labels['quaternions'],
- target_semi_labels['quaternions'])
- (source_images, source_class_labels, source_pose_labels,
- domain_selection_mask) = tf.train.shuffle_batch(
- [
- source_images, source_class_labels, source_pose_labels,
- domain_selection_mask
- ],
- FLAGS.batch_size,
- 50000,
- 5000,
- num_threads=1,
- enqueue_many=True)
-
- else:
- (source_images, source_class_labels,
- domain_selection_mask) = tf.train.shuffle_batch(
- [source_images, source_class_labels, domain_selection_mask],
- FLAGS.batch_size,
- 50000,
- 5000,
- num_threads=1,
- enqueue_many=True)
- source_labels = {}
- source_labels['classes'] = source_class_labels
- if 'quaternions' in source_labels:
- source_labels['quaternions'] = source_pose_labels
-
- slim.get_or_create_global_step()
- tf.summary.image('source_images', source_images, max_outputs=3)
- tf.summary.image('target_images', target_images, max_outputs=3)
-
- dsn.create_model(
- source_images,
- source_labels,
- domain_selection_mask,
- target_images,
- target_labels,
- FLAGS.similarity_loss,
- model_params,
- basic_tower_name=FLAGS.basic_tower)
-
- # Configure the optimization scheme:
- learning_rate = tf.train.exponential_decay(
- FLAGS.learning_rate,
- slim.get_or_create_global_step(),
- FLAGS.decay_steps,
- FLAGS.decay_rate,
- staircase=True,
- name='learning_rate')
-
- tf.summary.scalar('learning_rate', learning_rate)
- tf.summary.scalar('total_loss', tf.losses.get_total_loss())
-
- opt = tf.train.MomentumOptimizer(learning_rate, FLAGS.momentum)
- tf.logging.set_verbosity(tf.logging.INFO)
- # Run training.
- loss_tensor = slim.learning.create_train_op(
- slim.losses.get_total_loss(),
- opt,
- summarize_gradients=True,
- colocate_gradients_with_ops=True)
- slim.learning.train(
- train_op=loss_tensor,
- logdir=FLAGS.train_log_dir,
- master=FLAGS.master,
- is_chief=FLAGS.task == 0,
- number_of_steps=FLAGS.max_number_of_steps,
- save_summaries_secs=FLAGS.save_summaries_secs,
- save_interval_secs=FLAGS.save_interval_secs)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/domain_adaptation/domain_separation/grl_op_grads.py b/research/domain_adaptation/domain_separation/grl_op_grads.py
deleted file mode 100644
index fcd85ba2b5e7912bffe646a73558af8184812ea6..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/domain_separation/grl_op_grads.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Gradients for operators defined in grl_ops.py."""
-import tensorflow as tf
-
-
-@tf.RegisterGradient("GradientReversal")
-def _GradientReversalGrad(_, grad):
- """The gradients for `gradient_reversal`.
-
- Args:
- _: The `gradient_reversal` `Operation` that we are differentiating,
- which we can use to find the inputs and outputs of the original op.
- grad: Gradient with respect to the output of the `gradient_reversal` op.
-
- Returns:
- Gradient with respect to the input of `gradient_reversal`, which is simply
- the negative of the input gradient.
-
- """
- return tf.negative(grad)
diff --git a/research/domain_adaptation/domain_separation/grl_op_kernels.cc b/research/domain_adaptation/domain_separation/grl_op_kernels.cc
deleted file mode 100644
index ba30128f11e9e88c702d3a80593d930519f346fe..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/domain_separation/grl_op_kernels.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Copyright 2016 The TensorFlow Authors All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-// This file contains the implementations of the ops registered in
-// grl_ops.cc.
-
-#include "tensorflow/core/framework/op_kernel.h"
-#include "tensorflow/core/framework/types.pb.h"
-
-namespace tensorflow {
-
-// The gradient reversal op is used in domain adversarial training. It behaves
-// as the identity op during forward propagation, and multiplies its input by -1
-// during backward propagation.
-class GradientReversalOp : public OpKernel {
- public:
- explicit GradientReversalOp(OpKernelConstruction* context)
- : OpKernel(context) {}
-
- // Gradient reversal op behaves as the identity op during forward
- // propagation. Compute() function copied from the IdentityOp::Compute()
- // function here: third_party/tensorflow/core/kernels/identity_op.h.
- void Compute(OpKernelContext* context) override {
- if (IsRefType(context->input_dtype(0))) {
- context->forward_ref_input_to_ref_output(0, 0);
- } else {
- context->set_output(0, context->input(0));
- }
- }
-};
-
-REGISTER_KERNEL_BUILDER(Name("GradientReversal").Device(DEVICE_CPU),
- GradientReversalOp);
-
-} // namespace tensorflow
diff --git a/research/domain_adaptation/domain_separation/grl_op_shapes.py b/research/domain_adaptation/domain_separation/grl_op_shapes.py
deleted file mode 100644
index 52773c680af265beca9125e48bf68152b8a34e56..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/domain_separation/grl_op_shapes.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Shape inference for operators defined in grl_ops.cc."""
diff --git a/research/domain_adaptation/domain_separation/grl_ops.cc b/research/domain_adaptation/domain_separation/grl_ops.cc
deleted file mode 100644
index d441c2b484215605db65a043be6cfa0ab90da2c3..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/domain_separation/grl_ops.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Copyright 2016 The TensorFlow Authors All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-// Contains custom ops.
-
-#include "tensorflow/core/framework/common_shape_fns.h"
-#include "tensorflow/core/framework/op.h"
-
-namespace tensorflow {
-
-// This custom op is used by adversarial training.
-REGISTER_OP("GradientReversal")
- .Input("input: float")
- .Output("output: float")
- .SetShapeFn(shape_inference::UnchangedShape)
- .Doc(R"doc(
-This op copies the input to the output during forward propagation, and
-negates the input during backward propagation.
-
-input: Tensor.
-output: Tensor, copied from input.
-)doc");
-
-} // namespace tensorflow
diff --git a/research/domain_adaptation/domain_separation/grl_ops.py b/research/domain_adaptation/domain_separation/grl_ops.py
deleted file mode 100644
index 50447247b10caf3e41f3c0fb1c6f943dd3d9de6e..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/domain_separation/grl_ops.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""GradientReversal op Python library."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os.path
-
-import tensorflow as tf
-
-tf.logging.info(tf.resource_loader.get_data_files_path())
-_grl_ops_module = tf.load_op_library(
- os.path.join(tf.resource_loader.get_data_files_path(),
- '_grl_ops.so'))
-gradient_reversal = _grl_ops_module.gradient_reversal
diff --git a/research/domain_adaptation/domain_separation/grl_ops_test.py b/research/domain_adaptation/domain_separation/grl_ops_test.py
deleted file mode 100644
index b431a6c02b60ade92a653d2ee8108c0586c70fbb..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/domain_separation/grl_ops_test.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests for grl_ops."""
-
-#from models.domain_adaptation.domain_separation import grl_op_grads # pylint: disable=unused-import
-#from models.domain_adaptation.domain_separation import grl_op_shapes # pylint: disable=unused-import
-import tensorflow as tf
-
-import grl_op_grads
-import grl_ops
-
-FLAGS = tf.app.flags.FLAGS
-
-
-class GRLOpsTest(tf.test.TestCase):
-
- def testGradientReversalOp(self):
- with tf.Graph().as_default():
- with self.test_session():
- # Test that in forward prop, gradient reversal op acts as the
- # identity operation.
- examples = tf.constant([5.0, 4.0, 3.0, 2.0, 1.0])
- output = grl_ops.gradient_reversal(examples)
- expected_output = examples
- self.assertAllEqual(output.eval(), expected_output.eval())
-
- # Test that shape inference works as expected.
- self.assertAllEqual(output.get_shape(), expected_output.get_shape())
-
- # Test that in backward prop, gradient reversal op multiplies
- # gradients by -1.
- examples = tf.constant([[1.0]])
- w = tf.get_variable(name='w', shape=[1, 1])
- b = tf.get_variable(name='b', shape=[1])
- init_op = tf.global_variables_initializer()
- init_op.run()
- features = tf.nn.xw_plus_b(examples, w, b)
- # Construct two outputs: features layer passes directly to output1, but
- # features layer passes through a gradient reversal layer before
- # reaching output2.
- output1 = features
- output2 = grl_ops.gradient_reversal(features)
- gold = tf.constant([1.0])
- loss1 = gold - output1
- loss2 = gold - output2
- opt = tf.train.GradientDescentOptimizer(learning_rate=0.01)
- grads_and_vars_1 = opt.compute_gradients(loss1,
- tf.trainable_variables())
- grads_and_vars_2 = opt.compute_gradients(loss2,
- tf.trainable_variables())
- self.assertAllEqual(len(grads_and_vars_1), len(grads_and_vars_2))
- for i in range(len(grads_and_vars_1)):
- g1 = grads_and_vars_1[i][0]
- g2 = grads_and_vars_2[i][0]
- # Verify that gradients of loss1 are the negative of gradients of
- # loss2.
- self.assertAllEqual(tf.negative(g1).eval(), g2.eval())
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/domain_adaptation/domain_separation/losses.py b/research/domain_adaptation/domain_separation/losses.py
deleted file mode 100644
index 0d882340de10e4dd64d44f9357e8bfc5b1dd4712..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/domain_separation/losses.py
+++ /dev/null
@@ -1,290 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Domain Adaptation Loss Functions.
-
-The following domain adaptation loss functions are defined:
-
-- Maximum Mean Discrepancy (MMD).
- Relevant paper:
- Gretton, Arthur, et al.,
- "A kernel two-sample test."
- The Journal of Machine Learning Research, 2012
-
-- Correlation Loss on a batch.
-"""
-from functools import partial
-import tensorflow as tf
-
-import grl_op_grads # pylint: disable=unused-import
-import grl_op_shapes # pylint: disable=unused-import
-import grl_ops
-import utils
-slim = tf.contrib.slim
-
-
-################################################################################
-# SIMILARITY LOSS
-################################################################################
-def maximum_mean_discrepancy(x, y, kernel=utils.gaussian_kernel_matrix):
- r"""Computes the Maximum Mean Discrepancy (MMD) of two samples: x and y.
-
- Maximum Mean Discrepancy (MMD) is a distance-measure between the samples of
- the distributions of x and y. Here we use the kernel two sample estimate
- using the empirical mean of the two distributions.
-
- MMD^2(P, Q) = || \E{\phi(x)} - \E{\phi(y)} ||^2
- = \E{ K(x, x) } + \E{ K(y, y) } - 2 \E{ K(x, y) },
-
- where K = <\phi(x), \phi(y)>,
- is the desired kernel function, in this case a radial basis kernel.
-
- Args:
- x: a tensor of shape [num_samples, num_features]
- y: a tensor of shape [num_samples, num_features]
- kernel: a function which computes the kernel in MMD. Defaults to the
- GaussianKernelMatrix.
-
- Returns:
- a scalar denoting the squared maximum mean discrepancy loss.
- """
- with tf.name_scope('MaximumMeanDiscrepancy'):
- # \E{ K(x, x) } + \E{ K(y, y) } - 2 \E{ K(x, y) }
- cost = tf.reduce_mean(kernel(x, x))
- cost += tf.reduce_mean(kernel(y, y))
- cost -= 2 * tf.reduce_mean(kernel(x, y))
-
- # We do not allow the loss to become negative.
- cost = tf.where(cost > 0, cost, 0, name='value')
- return cost
-
-
-def mmd_loss(source_samples, target_samples, weight, scope=None):
- """Adds a similarity loss term, the MMD between two representations.
-
- This Maximum Mean Discrepancy (MMD) loss is calculated with a number of
- different Gaussian kernels.
-
- Args:
- source_samples: a tensor of shape [num_samples, num_features].
- target_samples: a tensor of shape [num_samples, num_features].
- weight: the weight of the MMD loss.
- scope: optional name scope for summary tags.
-
- Returns:
- a scalar tensor representing the MMD loss value.
- """
- sigmas = [
- 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 1, 5, 10, 15, 20, 25, 30, 35, 100,
- 1e3, 1e4, 1e5, 1e6
- ]
- gaussian_kernel = partial(
- utils.gaussian_kernel_matrix, sigmas=tf.constant(sigmas))
-
- loss_value = maximum_mean_discrepancy(
- source_samples, target_samples, kernel=gaussian_kernel)
- loss_value = tf.maximum(1e-4, loss_value) * weight
- assert_op = tf.Assert(tf.is_finite(loss_value), [loss_value])
- with tf.control_dependencies([assert_op]):
- tag = 'MMD Loss'
- if scope:
- tag = scope + tag
- tf.summary.scalar(tag, loss_value)
- tf.losses.add_loss(loss_value)
-
- return loss_value
-
-
-def correlation_loss(source_samples, target_samples, weight, scope=None):
- """Adds a similarity loss term, the correlation between two representations.
-
- Args:
- source_samples: a tensor of shape [num_samples, num_features]
- target_samples: a tensor of shape [num_samples, num_features]
- weight: a scalar weight for the loss.
- scope: optional name scope for summary tags.
-
- Returns:
- a scalar tensor representing the correlation loss value.
- """
- with tf.name_scope('corr_loss'):
- source_samples -= tf.reduce_mean(source_samples, 0)
- target_samples -= tf.reduce_mean(target_samples, 0)
-
- source_samples = tf.nn.l2_normalize(source_samples, 1)
- target_samples = tf.nn.l2_normalize(target_samples, 1)
-
- source_cov = tf.matmul(tf.transpose(source_samples), source_samples)
- target_cov = tf.matmul(tf.transpose(target_samples), target_samples)
-
- corr_loss = tf.reduce_mean(tf.square(source_cov - target_cov)) * weight
-
- assert_op = tf.Assert(tf.is_finite(corr_loss), [corr_loss])
- with tf.control_dependencies([assert_op]):
- tag = 'Correlation Loss'
- if scope:
- tag = scope + tag
- tf.summary.scalar(tag, corr_loss)
- tf.losses.add_loss(corr_loss)
-
- return corr_loss
-
-
-def dann_loss(source_samples, target_samples, weight, scope=None):
- """Adds the domain adversarial (DANN) loss.
-
- Args:
- source_samples: a tensor of shape [num_samples, num_features].
- target_samples: a tensor of shape [num_samples, num_features].
- weight: the weight of the loss.
- scope: optional name scope for summary tags.
-
- Returns:
- a scalar tensor representing the correlation loss value.
- """
- with tf.variable_scope('dann'):
- batch_size = tf.shape(source_samples)[0]
- samples = tf.concat(axis=0, values=[source_samples, target_samples])
- samples = slim.flatten(samples)
-
- domain_selection_mask = tf.concat(
- axis=0, values=[tf.zeros((batch_size, 1)), tf.ones((batch_size, 1))])
-
- # Perform the gradient reversal and be careful with the shape.
- grl = grl_ops.gradient_reversal(samples)
- grl = tf.reshape(grl, (-1, samples.get_shape().as_list()[1]))
-
- grl = slim.fully_connected(grl, 100, scope='fc1')
- logits = slim.fully_connected(grl, 1, activation_fn=None, scope='fc2')
-
- domain_predictions = tf.sigmoid(logits)
-
- domain_loss = tf.losses.log_loss(
- domain_selection_mask, domain_predictions, weights=weight)
-
- domain_accuracy = utils.accuracy(
- tf.round(domain_predictions), domain_selection_mask)
-
- assert_op = tf.Assert(tf.is_finite(domain_loss), [domain_loss])
- with tf.control_dependencies([assert_op]):
- tag_loss = 'losses/domain_loss'
- tag_accuracy = 'losses/domain_accuracy'
- if scope:
- tag_loss = scope + tag_loss
- tag_accuracy = scope + tag_accuracy
-
- tf.summary.scalar(tag_loss, domain_loss)
- tf.summary.scalar(tag_accuracy, domain_accuracy)
-
- return domain_loss
-
-
-################################################################################
-# DIFFERENCE LOSS
-################################################################################
-def difference_loss(private_samples, shared_samples, weight=1.0, name=''):
- """Adds the difference loss between the private and shared representations.
-
- Args:
- private_samples: a tensor of shape [num_samples, num_features].
- shared_samples: a tensor of shape [num_samples, num_features].
- weight: the weight of the incoherence loss.
- name: the name of the tf summary.
- """
- private_samples -= tf.reduce_mean(private_samples, 0)
- shared_samples -= tf.reduce_mean(shared_samples, 0)
-
- private_samples = tf.nn.l2_normalize(private_samples, 1)
- shared_samples = tf.nn.l2_normalize(shared_samples, 1)
-
- correlation_matrix = tf.matmul(
- private_samples, shared_samples, transpose_a=True)
-
- cost = tf.reduce_mean(tf.square(correlation_matrix)) * weight
- cost = tf.where(cost > 0, cost, 0, name='value')
-
- tf.summary.scalar('losses/Difference Loss {}'.format(name),
- cost)
- assert_op = tf.Assert(tf.is_finite(cost), [cost])
- with tf.control_dependencies([assert_op]):
- tf.losses.add_loss(cost)
-
-
-################################################################################
-# TASK LOSS
-################################################################################
-def log_quaternion_loss_batch(predictions, labels, params):
- """A helper function to compute the error between quaternions.
-
- Args:
- predictions: A Tensor of size [batch_size, 4].
- labels: A Tensor of size [batch_size, 4].
- params: A dictionary of parameters. Expecting 'use_logging', 'batch_size'.
-
- Returns:
- A Tensor of size [batch_size], denoting the error between the quaternions.
- """
- use_logging = params['use_logging']
- assertions = []
- if use_logging:
- assertions.append(
- tf.Assert(
- tf.reduce_all(
- tf.less(
- tf.abs(tf.reduce_sum(tf.square(predictions), [1]) - 1),
- 1e-4)),
- ['The l2 norm of each prediction quaternion vector should be 1.']))
- assertions.append(
- tf.Assert(
- tf.reduce_all(
- tf.less(
- tf.abs(tf.reduce_sum(tf.square(labels), [1]) - 1), 1e-4)),
- ['The l2 norm of each label quaternion vector should be 1.']))
-
- with tf.control_dependencies(assertions):
- product = tf.multiply(predictions, labels)
- internal_dot_products = tf.reduce_sum(product, [1])
-
- if use_logging:
- internal_dot_products = tf.Print(
- internal_dot_products,
- [internal_dot_products, tf.shape(internal_dot_products)],
- 'internal_dot_products:')
-
- logcost = tf.log(1e-4 + 1 - tf.abs(internal_dot_products))
- return logcost
-
-
-def log_quaternion_loss(predictions, labels, params):
- """A helper function to compute the mean error between batches of quaternions.
-
- The caller is expected to add the loss to the graph.
-
- Args:
- predictions: A Tensor of size [batch_size, 4].
- labels: A Tensor of size [batch_size, 4].
- params: A dictionary of parameters. Expecting 'use_logging', 'batch_size'.
-
- Returns:
- A Tensor of size 1, denoting the mean error between batches of quaternions.
- """
- use_logging = params['use_logging']
- logcost = log_quaternion_loss_batch(predictions, labels, params)
- logcost = tf.reduce_sum(logcost, [0])
- batch_size = params['batch_size']
- logcost = tf.multiply(logcost, 1.0 / batch_size, name='log_quaternion_loss')
- if use_logging:
- logcost = tf.Print(
- logcost, [logcost], '[logcost]', name='log_quaternion_loss_print')
- return logcost
diff --git a/research/domain_adaptation/domain_separation/losses_test.py b/research/domain_adaptation/domain_separation/losses_test.py
deleted file mode 100644
index 46e50301be56f5977adcb3fb00587f076934b785..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/domain_separation/losses_test.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tests for DSN losses."""
-from functools import partial
-
-import numpy as np
-import tensorflow as tf
-
-import losses
-import utils
-
-
-def MaximumMeanDiscrepancySlow(x, y, sigmas):
- num_samples = x.get_shape().as_list()[0]
-
- def AverageGaussianKernel(x, y, sigmas):
- result = 0
- for sigma in sigmas:
- dist = tf.reduce_sum(tf.square(x - y))
- result += tf.exp((-1.0 / (2.0 * sigma)) * dist)
- return result / num_samples**2
-
- total = 0
-
- for i in range(num_samples):
- for j in range(num_samples):
- total += AverageGaussianKernel(x[i, :], x[j, :], sigmas)
- total += AverageGaussianKernel(y[i, :], y[j, :], sigmas)
- total += -2 * AverageGaussianKernel(x[i, :], y[j, :], sigmas)
-
- return total
-
-
-class LogQuaternionLossTest(tf.test.TestCase):
-
- def test_log_quaternion_loss_batch(self):
- with self.test_session():
- predictions = tf.random_uniform((10, 4), seed=1)
- predictions = tf.nn.l2_normalize(predictions, 1)
- labels = tf.random_uniform((10, 4), seed=1)
- labels = tf.nn.l2_normalize(labels, 1)
- params = {'batch_size': 10, 'use_logging': False}
- x = losses.log_quaternion_loss_batch(predictions, labels, params)
- self.assertTrue(((10,) == tf.shape(x).eval()).all())
-
-
-class MaximumMeanDiscrepancyTest(tf.test.TestCase):
-
- def test_mmd_name(self):
- with self.test_session():
- x = tf.random_uniform((2, 3), seed=1)
- kernel = partial(utils.gaussian_kernel_matrix, sigmas=tf.constant([1.]))
- loss = losses.maximum_mean_discrepancy(x, x, kernel)
-
- self.assertEquals(loss.op.name, 'MaximumMeanDiscrepancy/value')
-
- def test_mmd_is_zero_when_inputs_are_same(self):
- with self.test_session():
- x = tf.random_uniform((2, 3), seed=1)
- kernel = partial(utils.gaussian_kernel_matrix, sigmas=tf.constant([1.]))
- self.assertEquals(0, losses.maximum_mean_discrepancy(x, x, kernel).eval())
-
- def test_fast_mmd_is_similar_to_slow_mmd(self):
- with self.test_session():
- x = tf.constant(np.random.normal(size=(2, 3)), tf.float32)
- y = tf.constant(np.random.rand(2, 3), tf.float32)
-
- cost_old = MaximumMeanDiscrepancySlow(x, y, [1.]).eval()
- kernel = partial(utils.gaussian_kernel_matrix, sigmas=tf.constant([1.]))
- cost_new = losses.maximum_mean_discrepancy(x, y, kernel).eval()
-
- self.assertAlmostEqual(cost_old, cost_new, delta=1e-5)
-
- def test_multiple_sigmas(self):
- with self.test_session():
- x = tf.constant(np.random.normal(size=(2, 3)), tf.float32)
- y = tf.constant(np.random.rand(2, 3), tf.float32)
-
- sigmas = tf.constant([2., 5., 10, 20, 30])
- kernel = partial(utils.gaussian_kernel_matrix, sigmas=sigmas)
- cost_old = MaximumMeanDiscrepancySlow(x, y, [2., 5., 10, 20, 30]).eval()
- cost_new = losses.maximum_mean_discrepancy(x, y, kernel=kernel).eval()
-
- self.assertAlmostEqual(cost_old, cost_new, delta=1e-5)
-
- def test_mmd_is_zero_when_distributions_are_same(self):
-
- with self.test_session():
- x = tf.random_uniform((1000, 10), seed=1)
- y = tf.random_uniform((1000, 10), seed=3)
-
- kernel = partial(utils.gaussian_kernel_matrix, sigmas=tf.constant([100.]))
- loss = losses.maximum_mean_discrepancy(x, y, kernel=kernel).eval()
-
- self.assertAlmostEqual(0, loss, delta=1e-4)
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/domain_adaptation/domain_separation/models.py b/research/domain_adaptation/domain_separation/models.py
deleted file mode 100644
index 04ccaf82eb9b31a6ea78871204c7df70eca3fbfd..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/domain_separation/models.py
+++ /dev/null
@@ -1,443 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Contains different architectures for the different DSN parts.
-
-We define here the modules that can be used in the different parts of the DSN
-model.
-- shared encoder (dsn_cropped_linemod, dann_xxxx)
-- private encoder (default_encoder)
-- decoder (large_decoder, gtsrb_decoder, small_decoder)
-"""
-import tensorflow as tf
-
-#from models.domain_adaptation.domain_separation
-import utils
-
-slim = tf.contrib.slim
-
-
-def default_batch_norm_params(is_training=False):
- """Returns default batch normalization parameters for DSNs.
-
- Args:
- is_training: whether or not the model is training.
-
- Returns:
- a dictionary that maps batch norm parameter names (strings) to values.
- """
- return {
- # Decay for the moving averages.
- 'decay': 0.5,
- # epsilon to prevent 0s in variance.
- 'epsilon': 0.001,
- 'is_training': is_training
- }
-
-
-################################################################################
-# PRIVATE ENCODERS
-################################################################################
-def default_encoder(images, code_size, batch_norm_params=None,
- weight_decay=0.0):
- """Encodes the given images to codes of the given size.
-
- Args:
- images: a tensor of size [batch_size, height, width, 1].
- code_size: the number of hidden units in the code layer of the classifier.
- batch_norm_params: a dictionary that maps batch norm parameter names to
- values.
- weight_decay: the value for the weight decay coefficient.
-
- Returns:
- end_points: the code of the input.
- """
- end_points = {}
- with slim.arg_scope(
- [slim.conv2d, slim.fully_connected],
- weights_regularizer=slim.l2_regularizer(weight_decay),
- activation_fn=tf.nn.relu,
- normalizer_fn=slim.batch_norm,
- normalizer_params=batch_norm_params):
- with slim.arg_scope([slim.conv2d], kernel_size=[5, 5], padding='SAME'):
- net = slim.conv2d(images, 32, scope='conv1')
- net = slim.max_pool2d(net, [2, 2], 2, scope='pool1')
- net = slim.conv2d(net, 64, scope='conv2')
- net = slim.max_pool2d(net, [2, 2], 2, scope='pool2')
-
- net = slim.flatten(net)
- end_points['flatten'] = net
- net = slim.fully_connected(net, code_size, scope='fc1')
- end_points['fc3'] = net
- return end_points
-
-
-################################################################################
-# DECODERS
-################################################################################
-def large_decoder(codes,
- height,
- width,
- channels,
- batch_norm_params=None,
- weight_decay=0.0):
- """Decodes the codes to a fixed output size.
-
- Args:
- codes: a tensor of size [batch_size, code_size].
- height: the height of the output images.
- width: the width of the output images.
- channels: the number of the output channels.
- batch_norm_params: a dictionary that maps batch norm parameter names to
- values.
- weight_decay: the value for the weight decay coefficient.
-
- Returns:
- recons: the reconstruction tensor of shape [batch_size, height, width, 3].
- """
- with slim.arg_scope(
- [slim.conv2d, slim.fully_connected],
- weights_regularizer=slim.l2_regularizer(weight_decay),
- activation_fn=tf.nn.relu,
- normalizer_fn=slim.batch_norm,
- normalizer_params=batch_norm_params):
- net = slim.fully_connected(codes, 600, scope='fc1')
- batch_size = net.get_shape().as_list()[0]
- net = tf.reshape(net, [batch_size, 10, 10, 6])
-
- net = slim.conv2d(net, 32, [5, 5], scope='conv1_1')
-
- net = tf.image.resize_nearest_neighbor(net, (16, 16))
-
- net = slim.conv2d(net, 32, [5, 5], scope='conv2_1')
-
- net = tf.image.resize_nearest_neighbor(net, (32, 32))
-
- net = slim.conv2d(net, 32, [5, 5], scope='conv3_2')
-
- output_size = [height, width]
- net = tf.image.resize_nearest_neighbor(net, output_size)
-
- with slim.arg_scope([slim.conv2d], kernel_size=[3, 3]):
- net = slim.conv2d(net, channels, activation_fn=None, scope='conv4_1')
-
- return net
-
-
-def gtsrb_decoder(codes,
- height,
- width,
- channels,
- batch_norm_params=None,
- weight_decay=0.0):
- """Decodes the codes to a fixed output size. This decoder is specific to GTSRB
-
- Args:
- codes: a tensor of size [batch_size, 100].
- height: the height of the output images.
- width: the width of the output images.
- channels: the number of the output channels.
- batch_norm_params: a dictionary that maps batch norm parameter names to
- values.
- weight_decay: the value for the weight decay coefficient.
-
- Returns:
- recons: the reconstruction tensor of shape [batch_size, height, width, 3].
-
- Raises:
- ValueError: When the input code size is not 100.
- """
- batch_size, code_size = codes.get_shape().as_list()
- if code_size != 100:
- raise ValueError('The code size used as an input to the GTSRB decoder is '
- 'expected to be 100.')
-
- with slim.arg_scope(
- [slim.conv2d, slim.fully_connected],
- weights_regularizer=slim.l2_regularizer(weight_decay),
- activation_fn=tf.nn.relu,
- normalizer_fn=slim.batch_norm,
- normalizer_params=batch_norm_params):
- net = codes
- net = tf.reshape(net, [batch_size, 10, 10, 1])
- net = slim.conv2d(net, 32, [3, 3], scope='conv1_1')
-
- # First upsampling 20x20
- net = tf.image.resize_nearest_neighbor(net, [20, 20])
-
- net = slim.conv2d(net, 32, [3, 3], scope='conv2_1')
-
- output_size = [height, width]
- # Final upsampling 40 x 40
- net = tf.image.resize_nearest_neighbor(net, output_size)
-
- with slim.arg_scope([slim.conv2d], kernel_size=[3, 3]):
- net = slim.conv2d(net, 16, scope='conv3_1')
- net = slim.conv2d(net, channels, activation_fn=None, scope='conv3_2')
-
- return net
-
-
-def small_decoder(codes,
- height,
- width,
- channels,
- batch_norm_params=None,
- weight_decay=0.0):
- """Decodes the codes to a fixed output size.
-
- Args:
- codes: a tensor of size [batch_size, code_size].
- height: the height of the output images.
- width: the width of the output images.
- channels: the number of the output channels.
- batch_norm_params: a dictionary that maps batch norm parameter names to
- values.
- weight_decay: the value for the weight decay coefficient.
-
- Returns:
- recons: the reconstruction tensor of shape [batch_size, height, width, 3].
- """
- with slim.arg_scope(
- [slim.conv2d, slim.fully_connected],
- weights_regularizer=slim.l2_regularizer(weight_decay),
- activation_fn=tf.nn.relu,
- normalizer_fn=slim.batch_norm,
- normalizer_params=batch_norm_params):
- net = slim.fully_connected(codes, 300, scope='fc1')
- batch_size = net.get_shape().as_list()[0]
- net = tf.reshape(net, [batch_size, 10, 10, 3])
-
- net = slim.conv2d(net, 16, [3, 3], scope='conv1_1')
- net = slim.conv2d(net, 16, [3, 3], scope='conv1_2')
-
- output_size = [height, width]
- net = tf.image.resize_nearest_neighbor(net, output_size)
-
- with slim.arg_scope([slim.conv2d], kernel_size=[3, 3]):
- net = slim.conv2d(net, 16, scope='conv2_1')
- net = slim.conv2d(net, channels, activation_fn=None, scope='conv2_2')
-
- return net
-
-
-################################################################################
-# SHARED ENCODERS
-################################################################################
-def dann_mnist(images,
- weight_decay=0.0,
- prefix='model',
- num_classes=10,
- **kwargs):
- """Creates a convolution MNIST model.
-
- Note that this model implements the architecture for MNIST proposed in:
- Y. Ganin et al., Domain-Adversarial Training of Neural Networks (DANN),
- JMLR 2015
-
- Args:
- images: the MNIST digits, a tensor of size [batch_size, 28, 28, 1].
- weight_decay: the value for the weight decay coefficient.
- prefix: name of the model to use when prefixing tags.
- num_classes: the number of output classes to use.
- **kwargs: Placeholder for keyword arguments used by other shared encoders.
-
- Returns:
- the output logits, a tensor of size [batch_size, num_classes].
- a dictionary with key/values the layer names and tensors.
- """
- end_points = {}
-
- with slim.arg_scope(
- [slim.conv2d, slim.fully_connected],
- weights_regularizer=slim.l2_regularizer(weight_decay),
- activation_fn=tf.nn.relu,):
- with slim.arg_scope([slim.conv2d], padding='SAME'):
- end_points['conv1'] = slim.conv2d(images, 32, [5, 5], scope='conv1')
- end_points['pool1'] = slim.max_pool2d(
- end_points['conv1'], [2, 2], 2, scope='pool1')
- end_points['conv2'] = slim.conv2d(
- end_points['pool1'], 48, [5, 5], scope='conv2')
- end_points['pool2'] = slim.max_pool2d(
- end_points['conv2'], [2, 2], 2, scope='pool2')
- end_points['fc3'] = slim.fully_connected(
- slim.flatten(end_points['pool2']), 100, scope='fc3')
- end_points['fc4'] = slim.fully_connected(
- slim.flatten(end_points['fc3']), 100, scope='fc4')
-
- logits = slim.fully_connected(
- end_points['fc4'], num_classes, activation_fn=None, scope='fc5')
-
- return logits, end_points
-
-
-def dann_svhn(images,
- weight_decay=0.0,
- prefix='model',
- num_classes=10,
- **kwargs):
- """Creates the convolutional SVHN model.
-
- Note that this model implements the architecture for MNIST proposed in:
- Y. Ganin et al., Domain-Adversarial Training of Neural Networks (DANN),
- JMLR 2015
-
- Args:
- images: the SVHN digits, a tensor of size [batch_size, 32, 32, 3].
- weight_decay: the value for the weight decay coefficient.
- prefix: name of the model to use when prefixing tags.
- num_classes: the number of output classes to use.
- **kwargs: Placeholder for keyword arguments used by other shared encoders.
-
- Returns:
- the output logits, a tensor of size [batch_size, num_classes].
- a dictionary with key/values the layer names and tensors.
- """
-
- end_points = {}
-
- with slim.arg_scope(
- [slim.conv2d, slim.fully_connected],
- weights_regularizer=slim.l2_regularizer(weight_decay),
- activation_fn=tf.nn.relu,):
- with slim.arg_scope([slim.conv2d], padding='SAME'):
-
- end_points['conv1'] = slim.conv2d(images, 64, [5, 5], scope='conv1')
- end_points['pool1'] = slim.max_pool2d(
- end_points['conv1'], [3, 3], 2, scope='pool1')
- end_points['conv2'] = slim.conv2d(
- end_points['pool1'], 64, [5, 5], scope='conv2')
- end_points['pool2'] = slim.max_pool2d(
- end_points['conv2'], [3, 3], 2, scope='pool2')
- end_points['conv3'] = slim.conv2d(
- end_points['pool2'], 128, [5, 5], scope='conv3')
-
- end_points['fc3'] = slim.fully_connected(
- slim.flatten(end_points['conv3']), 3072, scope='fc3')
- end_points['fc4'] = slim.fully_connected(
- slim.flatten(end_points['fc3']), 2048, scope='fc4')
-
- logits = slim.fully_connected(
- end_points['fc4'], num_classes, activation_fn=None, scope='fc5')
-
- return logits, end_points
-
-
-def dann_gtsrb(images,
- weight_decay=0.0,
- prefix='model',
- num_classes=43,
- **kwargs):
- """Creates the convolutional GTSRB model.
-
- Note that this model implements the architecture for MNIST proposed in:
- Y. Ganin et al., Domain-Adversarial Training of Neural Networks (DANN),
- JMLR 2015
-
- Args:
- images: the GTSRB images, a tensor of size [batch_size, 40, 40, 3].
- weight_decay: the value for the weight decay coefficient.
- prefix: name of the model to use when prefixing tags.
- num_classes: the number of output classes to use.
- **kwargs: Placeholder for keyword arguments used by other shared encoders.
-
- Returns:
- the output logits, a tensor of size [batch_size, num_classes].
- a dictionary with key/values the layer names and tensors.
- """
-
- end_points = {}
-
- with slim.arg_scope(
- [slim.conv2d, slim.fully_connected],
- weights_regularizer=slim.l2_regularizer(weight_decay),
- activation_fn=tf.nn.relu,):
- with slim.arg_scope([slim.conv2d], padding='SAME'):
-
- end_points['conv1'] = slim.conv2d(images, 96, [5, 5], scope='conv1')
- end_points['pool1'] = slim.max_pool2d(
- end_points['conv1'], [2, 2], 2, scope='pool1')
- end_points['conv2'] = slim.conv2d(
- end_points['pool1'], 144, [3, 3], scope='conv2')
- end_points['pool2'] = slim.max_pool2d(
- end_points['conv2'], [2, 2], 2, scope='pool2')
- end_points['conv3'] = slim.conv2d(
- end_points['pool2'], 256, [5, 5], scope='conv3')
- end_points['pool3'] = slim.max_pool2d(
- end_points['conv3'], [2, 2], 2, scope='pool3')
-
- end_points['fc3'] = slim.fully_connected(
- slim.flatten(end_points['pool3']), 512, scope='fc3')
-
- logits = slim.fully_connected(
- end_points['fc3'], num_classes, activation_fn=None, scope='fc4')
-
- return logits, end_points
-
-
-def dsn_cropped_linemod(images,
- weight_decay=0.0,
- prefix='model',
- num_classes=11,
- batch_norm_params=None,
- is_training=False):
- """Creates the convolutional pose estimation model for Cropped Linemod.
-
- Args:
- images: the Cropped Linemod samples, a tensor of size
- [batch_size, 64, 64, 4].
- weight_decay: the value for the weight decay coefficient.
- prefix: name of the model to use when prefixing tags.
- num_classes: the number of output classes to use.
- batch_norm_params: a dictionary that maps batch norm parameter names to
- values.
- is_training: specifies whether or not we're currently training the model.
- This variable will determine the behaviour of the dropout layer.
-
- Returns:
- the output logits, a tensor of size [batch_size, num_classes].
- a dictionary with key/values the layer names and tensors.
- """
-
- end_points = {}
-
- tf.summary.image('{}/input_images'.format(prefix), images)
- with slim.arg_scope(
- [slim.conv2d, slim.fully_connected],
- weights_regularizer=slim.l2_regularizer(weight_decay),
- activation_fn=tf.nn.relu,
- normalizer_fn=slim.batch_norm if batch_norm_params else None,
- normalizer_params=batch_norm_params):
- with slim.arg_scope([slim.conv2d], padding='SAME'):
- end_points['conv1'] = slim.conv2d(images, 32, [5, 5], scope='conv1')
- end_points['pool1'] = slim.max_pool2d(
- end_points['conv1'], [2, 2], 2, scope='pool1')
- end_points['conv2'] = slim.conv2d(
- end_points['pool1'], 64, [5, 5], scope='conv2')
- end_points['pool2'] = slim.max_pool2d(
- end_points['conv2'], [2, 2], 2, scope='pool2')
- net = slim.flatten(end_points['pool2'])
- end_points['fc3'] = slim.fully_connected(net, 128, scope='fc3')
- net = slim.dropout(
- end_points['fc3'], 0.5, is_training=is_training, scope='dropout')
-
- with tf.variable_scope('quaternion_prediction'):
- predicted_quaternion = slim.fully_connected(
- net, 4, activation_fn=tf.nn.tanh)
- predicted_quaternion = tf.nn.l2_normalize(predicted_quaternion, 1)
- logits = slim.fully_connected(
- net, num_classes, activation_fn=None, scope='fc4')
- end_points['quaternion_pred'] = predicted_quaternion
-
- return logits, end_points
diff --git a/research/domain_adaptation/domain_separation/models_test.py b/research/domain_adaptation/domain_separation/models_test.py
deleted file mode 100644
index 69d1a27259022569cc5865e49dd6bba5675d834f..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/domain_separation/models_test.py
+++ /dev/null
@@ -1,167 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tests for DSN components."""
-
-import numpy as np
-import tensorflow as tf
-
-#from models.domain_adaptation.domain_separation
-import models
-
-
-class SharedEncodersTest(tf.test.TestCase):
-
- def _testSharedEncoder(self,
- input_shape=[5, 28, 28, 1],
- model=models.dann_mnist,
- is_training=True):
- images = tf.to_float(np.random.rand(*input_shape))
-
- with self.test_session() as sess:
- logits, _ = model(images)
- sess.run(tf.global_variables_initializer())
- logits_np = sess.run(logits)
- return logits_np
-
- def testBuildGRLMnistModel(self):
- logits = self._testSharedEncoder(model=getattr(models,
- 'dann_mnist'))
- self.assertEqual(logits.shape, (5, 10))
- self.assertTrue(np.any(logits))
-
- def testBuildGRLSvhnModel(self):
- logits = self._testSharedEncoder(model=getattr(models,
- 'dann_svhn'))
- self.assertEqual(logits.shape, (5, 10))
- self.assertTrue(np.any(logits))
-
- def testBuildGRLGtsrbModel(self):
- logits = self._testSharedEncoder([5, 40, 40, 3],
- getattr(models, 'dann_gtsrb'))
- self.assertEqual(logits.shape, (5, 43))
- self.assertTrue(np.any(logits))
-
- def testBuildPoseModel(self):
- logits = self._testSharedEncoder([5, 64, 64, 4],
- getattr(models, 'dsn_cropped_linemod'))
- self.assertEqual(logits.shape, (5, 11))
- self.assertTrue(np.any(logits))
-
- def testBuildPoseModelWithBatchNorm(self):
- images = tf.to_float(np.random.rand(10, 64, 64, 4))
-
- with self.test_session() as sess:
- logits, _ = getattr(models, 'dsn_cropped_linemod')(
- images, batch_norm_params=models.default_batch_norm_params(True))
- sess.run(tf.global_variables_initializer())
- logits_np = sess.run(logits)
- self.assertEqual(logits_np.shape, (10, 11))
- self.assertTrue(np.any(logits_np))
-
-
-class EncoderTest(tf.test.TestCase):
-
- def _testEncoder(self, batch_norm_params=None, channels=1):
- images = tf.to_float(np.random.rand(10, 28, 28, channels))
-
- with self.test_session() as sess:
- end_points = models.default_encoder(
- images, 128, batch_norm_params=batch_norm_params)
- sess.run(tf.global_variables_initializer())
- private_code = sess.run(end_points['fc3'])
- self.assertEqual(private_code.shape, (10, 128))
- self.assertTrue(np.any(private_code))
- self.assertTrue(np.all(np.isfinite(private_code)))
-
- def testEncoder(self):
- self._testEncoder()
-
- def testEncoderMultiChannel(self):
- self._testEncoder(None, 4)
-
- def testEncoderIsTrainingBatchNorm(self):
- self._testEncoder(models.default_batch_norm_params(True))
-
- def testEncoderBatchNorm(self):
- self._testEncoder(models.default_batch_norm_params(False))
-
-
-class DecoderTest(tf.test.TestCase):
-
- def _testDecoder(self,
- height=64,
- width=64,
- channels=4,
- batch_norm_params=None,
- decoder=models.small_decoder):
- codes = tf.to_float(np.random.rand(32, 100))
-
- with self.test_session() as sess:
- output = decoder(
- codes,
- height=height,
- width=width,
- channels=channels,
- batch_norm_params=batch_norm_params)
- sess.run(tf.global_variables_initializer())
- output_np = sess.run(output)
- self.assertEqual(output_np.shape, (32, height, width, channels))
- self.assertTrue(np.any(output_np))
- self.assertTrue(np.all(np.isfinite(output_np)))
-
- def testSmallDecoder(self):
- self._testDecoder(28, 28, 4, None, getattr(models, 'small_decoder'))
-
- def testSmallDecoderThreeChannels(self):
- self._testDecoder(28, 28, 3)
-
- def testSmallDecoderBatchNorm(self):
- self._testDecoder(28, 28, 4, models.default_batch_norm_params(False))
-
- def testSmallDecoderIsTrainingBatchNorm(self):
- self._testDecoder(28, 28, 4, models.default_batch_norm_params(True))
-
- def testLargeDecoder(self):
- self._testDecoder(32, 32, 4, None, getattr(models, 'large_decoder'))
-
- def testLargeDecoderThreeChannels(self):
- self._testDecoder(32, 32, 3, None, getattr(models, 'large_decoder'))
-
- def testLargeDecoderBatchNorm(self):
- self._testDecoder(32, 32, 4,
- models.default_batch_norm_params(False),
- getattr(models, 'large_decoder'))
-
- def testLargeDecoderIsTrainingBatchNorm(self):
- self._testDecoder(32, 32, 4,
- models.default_batch_norm_params(True),
- getattr(models, 'large_decoder'))
-
- def testGtsrbDecoder(self):
- self._testDecoder(40, 40, 3, None, getattr(models, 'large_decoder'))
-
- def testGtsrbDecoderBatchNorm(self):
- self._testDecoder(40, 40, 4,
- models.default_batch_norm_params(False),
- getattr(models, 'gtsrb_decoder'))
-
- def testGtsrbDecoderIsTrainingBatchNorm(self):
- self._testDecoder(40, 40, 4,
- models.default_batch_norm_params(True),
- getattr(models, 'gtsrb_decoder'))
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/domain_adaptation/domain_separation/utils.py b/research/domain_adaptation/domain_separation/utils.py
deleted file mode 100644
index e144ee86120bd58eb06b710fb35f3f58b5a05343..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/domain_separation/utils.py
+++ /dev/null
@@ -1,183 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Auxiliary functions for domain adaptation related losses.
-"""
-import math
-import tensorflow as tf
-
-
-def create_summaries(end_points, prefix='', max_images=3, use_op_name=False):
- """Creates a tf summary per endpoint.
-
- If the endpoint is a 4 dimensional tensor it displays it as an image
- otherwise if it is a two dimensional one it creates a histogram summary.
-
- Args:
- end_points: a dictionary of name, tf tensor pairs.
- prefix: an optional string to prefix the summary with.
- max_images: the maximum number of images to display per summary.
- use_op_name: Use the op name as opposed to the shorter end_points key.
- """
- for layer_name in end_points:
- if use_op_name:
- name = end_points[layer_name].op.name
- else:
- name = layer_name
- if len(end_points[layer_name].get_shape().as_list()) == 4:
- # if it's an actual image do not attempt to reshape it
- if end_points[layer_name].get_shape().as_list()[-1] == 1 or end_points[
- layer_name].get_shape().as_list()[-1] == 3:
- visualization_image = end_points[layer_name]
- else:
- visualization_image = reshape_feature_maps(end_points[layer_name])
- tf.summary.image(
- '{}/{}'.format(prefix, name),
- visualization_image,
- max_outputs=max_images)
- elif len(end_points[layer_name].get_shape().as_list()) == 3:
- images = tf.expand_dims(end_points[layer_name], 3)
- tf.summary.image(
- '{}/{}'.format(prefix, name),
- images,
- max_outputs=max_images)
- elif len(end_points[layer_name].get_shape().as_list()) == 2:
- tf.summary.histogram('{}/{}'.format(prefix, name), end_points[layer_name])
-
-
-def reshape_feature_maps(features_tensor):
- """Reshape activations for tf.summary.image visualization.
-
- Arguments:
- features_tensor: a tensor of activations with a square number of feature
- maps, eg 4, 9, 16, etc.
- Returns:
- A composite image with all the feature maps that can be passed as an
- argument to tf.summary.image.
- """
- assert len(features_tensor.get_shape().as_list()) == 4
- num_filters = features_tensor.get_shape().as_list()[-1]
- assert num_filters > 0
- num_filters_sqrt = math.sqrt(num_filters)
- assert num_filters_sqrt.is_integer(
- ), 'Number of filters should be a square number but got {}'.format(
- num_filters)
- num_filters_sqrt = int(num_filters_sqrt)
- conv_summary = tf.unstack(features_tensor, axis=3)
- conv_one_row = tf.concat(axis=2, values=conv_summary[0:num_filters_sqrt])
- ind = 1
- conv_final = conv_one_row
- for ind in range(1, num_filters_sqrt):
- conv_one_row = tf.concat(axis=2,
- values=conv_summary[
- ind * num_filters_sqrt + 0:ind * num_filters_sqrt + num_filters_sqrt])
- conv_final = tf.concat(
- axis=1, values=[tf.squeeze(conv_final), tf.squeeze(conv_one_row)])
- conv_final = tf.expand_dims(conv_final, -1)
- return conv_final
-
-
-def accuracy(predictions, labels):
- """Calculates the classificaton accuracy.
-
- Args:
- predictions: the predicted values, a tensor whose size matches 'labels'.
- labels: the ground truth values, a tensor of any size.
-
- Returns:
- a tensor whose value on evaluation returns the total accuracy.
- """
- return tf.reduce_mean(tf.cast(tf.equal(predictions, labels), tf.float32))
-
-
-def compute_upsample_values(input_tensor, upsample_height, upsample_width):
- """Compute values for an upsampling op (ops.BatchCropAndResize).
-
- Args:
- input_tensor: image tensor with shape [batch, height, width, in_channels]
- upsample_height: integer
- upsample_width: integer
-
- Returns:
- grid_centers: tensor with shape [batch, 1]
- crop_sizes: tensor with shape [batch, 1]
- output_height: integer
- output_width: integer
- """
- batch, input_height, input_width, _ = input_tensor.shape
-
- height_half = input_height / 2.
- width_half = input_width / 2.
- grid_centers = tf.constant(batch * [[height_half, width_half]])
- crop_sizes = tf.constant(batch * [[input_height, input_width]])
- output_height = input_height * upsample_height
- output_width = input_width * upsample_width
-
- return grid_centers, tf.to_float(crop_sizes), output_height, output_width
-
-
-def compute_pairwise_distances(x, y):
- """Computes the squared pairwise Euclidean distances between x and y.
-
- Args:
- x: a tensor of shape [num_x_samples, num_features]
- y: a tensor of shape [num_y_samples, num_features]
-
- Returns:
- a distance matrix of dimensions [num_x_samples, num_y_samples].
-
- Raises:
- ValueError: if the inputs do no matched the specified dimensions.
- """
-
- if not len(x.get_shape()) == len(y.get_shape()) == 2:
- raise ValueError('Both inputs should be matrices.')
-
- if x.get_shape().as_list()[1] != y.get_shape().as_list()[1]:
- raise ValueError('The number of features should be the same.')
-
- norm = lambda x: tf.reduce_sum(tf.square(x), 1)
-
- # By making the `inner' dimensions of the two matrices equal to 1 using
- # broadcasting then we are essentially substracting every pair of rows
- # of x and y.
- # x will be num_samples x num_features x 1,
- # and y will be 1 x num_features x num_samples (after broadcasting).
- # After the substraction we will get a
- # num_x_samples x num_features x num_y_samples matrix.
- # The resulting dist will be of shape num_y_samples x num_x_samples.
- # and thus we need to transpose it again.
- return tf.transpose(norm(tf.expand_dims(x, 2) - tf.transpose(y)))
-
-
-def gaussian_kernel_matrix(x, y, sigmas):
- r"""Computes a Guassian Radial Basis Kernel between the samples of x and y.
-
- We create a sum of multiple gaussian kernels each having a width sigma_i.
-
- Args:
- x: a tensor of shape [num_samples, num_features]
- y: a tensor of shape [num_samples, num_features]
- sigmas: a tensor of floats which denote the widths of each of the
- gaussians in the kernel.
- Returns:
- A tensor of shape [num_samples{x}, num_samples{y}] with the RBF kernel.
- """
- beta = 1. / (2. * (tf.expand_dims(sigmas, 1)))
-
- dist = compute_pairwise_distances(x, y)
-
- s = tf.matmul(beta, tf.reshape(dist, (1, -1)))
-
- return tf.reshape(tf.reduce_sum(tf.exp(-s), 0), tf.shape(dist))
diff --git a/research/domain_adaptation/pixel_domain_adaptation/BUILD b/research/domain_adaptation/pixel_domain_adaptation/BUILD
deleted file mode 100644
index 2bc8d4a49a828f97b8f45166aa2bbc552d4a3b92..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/pixel_domain_adaptation/BUILD
+++ /dev/null
@@ -1,90 +0,0 @@
-# Description:
-# Contains code for domain-adaptation style transfer.
-
-package(
- default_visibility = [
- ":internal",
- ],
-)
-
-licenses(["notice"]) # Apache 2.0
-
-exports_files(["LICENSE"])
-
-package_group(
- name = "internal",
- packages = [
- "//domain_adaptation/...",
- ],
-)
-
-py_library(
- name = "pixelda_preprocess",
- srcs = ["pixelda_preprocess.py"],
- deps = [
-
- ],
-)
-
-py_test(
- name = "pixelda_preprocess_test",
- srcs = ["pixelda_preprocess_test.py"],
- deps = [
- ":pixelda_preprocess",
-
- ],
-)
-
-py_library(
- name = "pixelda_model",
- srcs = [
- "pixelda_model.py",
- "pixelda_task_towers.py",
- "hparams.py",
- ],
- deps = [
-
- ],
-)
-
-py_library(
- name = "pixelda_utils",
- srcs = ["pixelda_utils.py"],
- deps = [
-
- ],
-)
-
-py_library(
- name = "pixelda_losses",
- srcs = ["pixelda_losses.py"],
- deps = [
-
- ],
-)
-
-py_binary(
- name = "pixelda_train",
- srcs = ["pixelda_train.py"],
- deps = [
- ":pixelda_losses",
- ":pixelda_model",
- ":pixelda_preprocess",
- ":pixelda_utils",
-
- "//domain_adaptation/datasets:dataset_factory",
- ],
-)
-
-py_binary(
- name = "pixelda_eval",
- srcs = ["pixelda_eval.py"],
- deps = [
- ":pixelda_losses",
- ":pixelda_model",
- ":pixelda_preprocess",
- ":pixelda_utils",
-
- "//domain_adaptation/datasets:dataset_factory",
- ],
-)
diff --git a/research/domain_adaptation/pixel_domain_adaptation/README.md b/research/domain_adaptation/pixel_domain_adaptation/README.md
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/domain_adaptation/pixel_domain_adaptation/baselines/BUILD b/research/domain_adaptation/pixel_domain_adaptation/baselines/BUILD
deleted file mode 100644
index c41a4ffeee80114145c4c3fc32a2191879b1b08a..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/pixel_domain_adaptation/baselines/BUILD
+++ /dev/null
@@ -1,23 +0,0 @@
-licenses(["notice"]) # Apache 2.0
-
-py_binary(
- name = "baseline_train",
- srcs = ["baseline_train.py"],
- deps = [
-
- "//domain_adaptation/datasets:dataset_factory",
- "//domain_adaptation/pixel_domain_adaptation:pixelda_model",
- "//domain_adaptation/pixel_domain_adaptation:pixelda_preprocess",
- ],
-)
-
-py_binary(
- name = "baseline_eval",
- srcs = ["baseline_eval.py"],
- deps = [
-
- "//domain_adaptation/datasets:dataset_factory",
- "//domain_adaptation/pixel_domain_adaptation:pixelda_model",
- "//domain_adaptation/pixel_domain_adaptation:pixelda_preprocess",
- ],
-)
diff --git a/research/domain_adaptation/pixel_domain_adaptation/baselines/README.md b/research/domain_adaptation/pixel_domain_adaptation/baselines/README.md
deleted file mode 100644
index d61195ad2de6867801143aeda906cb5efe30a5e3..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/pixel_domain_adaptation/baselines/README.md
+++ /dev/null
@@ -1,60 +0,0 @@
-The best baselines are obtainable via the following configuration:
-
-
-## MNIST => MNIST_M
-
-Accuracy:
-MNIST-Train: 99.9
-MNIST_M-Train: 63.9
-MNIST_M-Valid: 63.9
-MNIST_M-Test: 63.6
-
-Learning Rate = 0.0001
-Weight Decay = 0.0
-Number of Steps: 105,000
-
-## MNIST => USPS
-
-Accuracy:
-MNIST-Train: 100.0
-USPS-Train: 82.8
-USPS-Valid: 82.8
-USPS-Test: 78.9
-
-Learning Rate = 0.0001
-Weight Decay = 0.0
-Number of Steps: 22,000
-
-## MNIST_M => MNIST
-
-Accuracy:
-MNIST_M-Train: 100
-MNIST-Train: 98.5
-MNIST-Valid: 98.5
-MNIST-Test: 98.1
-
-Learning Rate = 0.001
-Weight Decay = 0.0
-Number of Steps: 604,400
-
-## MNIST_M => MNIST_M
-
-Accuracy:
-MNIST_M-Train: 100.0
-MNIST_M-Valid: 96.6
-MNIST_M-Test: 96.4
-
-Learning Rate = 0.001
-Weight Decay = 0.0
-Number of Steps: 139,400
-
-## USPS => USPS
-
-Accuracy:
-USPS-Train: 100.0
-USPS-Valid: 100.0
-USPS-Test: 96.5
-
-Learning Rate = 0.001
-Weight Decay = 0.0
-Number of Steps: 67,000
diff --git a/research/domain_adaptation/pixel_domain_adaptation/baselines/baseline_eval.py b/research/domain_adaptation/pixel_domain_adaptation/baselines/baseline_eval.py
deleted file mode 100644
index 6b7ef6452b4897b00dc8c977bf40526ad5052ede..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/pixel_domain_adaptation/baselines/baseline_eval.py
+++ /dev/null
@@ -1,141 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-r"""Evals the classification/pose baselines."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from functools import partial
-
-import math
-
-# Dependency imports
-
-import tensorflow as tf
-
-from domain_adaptation.datasets import dataset_factory
-from domain_adaptation.pixel_domain_adaptation import pixelda_preprocess
-from domain_adaptation.pixel_domain_adaptation import pixelda_task_towers
-
-flags = tf.app.flags
-FLAGS = flags.FLAGS
-
-slim = tf.contrib.slim
-
-flags.DEFINE_string('master', '', 'BNS name of the tensorflow server')
-
-flags.DEFINE_string(
- 'checkpoint_dir', None, 'The location of the checkpoint files.')
-
-flags.DEFINE_string(
- 'eval_dir', None, 'The directory where evaluation logs are written.')
-
-flags.DEFINE_integer('batch_size', 32, 'The number of samples per batch.')
-
-flags.DEFINE_string('dataset_name', None, 'The name of the dataset.')
-
-flags.DEFINE_string('dataset_dir', None,
- 'The directory where the data is stored.')
-
-flags.DEFINE_string('split_name', None, 'The name of the train/test split.')
-
-flags.DEFINE_integer('eval_interval_secs', 60 * 5,
- 'How often (in seconds) to run evaluation.')
-
-flags.DEFINE_integer(
- 'num_readers', 4,
- 'The number of parallel readers that read data from the dataset.')
-
-def main(unused_argv):
- tf.logging.set_verbosity(tf.logging.INFO)
- hparams = tf.contrib.training.HParams()
- hparams.weight_decay_task_classifier = 0.0
-
- if FLAGS.dataset_name in ['mnist', 'mnist_m', 'usps']:
- hparams.task_tower = 'mnist'
- else:
- raise ValueError('Unknown dataset %s' % FLAGS.dataset_name)
-
- if not tf.gfile.Exists(FLAGS.eval_dir):
- tf.gfile.MakeDirs(FLAGS.eval_dir)
-
- with tf.Graph().as_default():
- dataset = dataset_factory.get_dataset(FLAGS.dataset_name, FLAGS.split_name,
- FLAGS.dataset_dir)
- num_classes = dataset.num_classes
- num_samples = dataset.num_samples
-
- preprocess_fn = partial(pixelda_preprocess.preprocess_classification,
- is_training=False)
-
- images, labels = dataset_factory.provide_batch(
- FLAGS.dataset_name,
- FLAGS.split_name,
- dataset_dir=FLAGS.dataset_dir,
- num_readers=FLAGS.num_readers,
- batch_size=FLAGS.batch_size,
- num_preprocessing_threads=FLAGS.num_readers)
-
- # Define the model
- logits, _ = pixelda_task_towers.add_task_specific_model(
- images, hparams, num_classes=num_classes, is_training=True)
-
- #####################
- # Define the losses #
- #####################
- if 'classes' in labels:
- one_hot_labels = labels['classes']
- loss = tf.losses.softmax_cross_entropy(
- onehot_labels=one_hot_labels, logits=logits)
- tf.summary.scalar('losses/Classification_Loss', loss)
- else:
- raise ValueError('Only support classification for now.')
-
- total_loss = tf.losses.get_total_loss()
-
- predictions = tf.reshape(tf.argmax(logits, 1), shape=[-1])
- class_labels = tf.argmax(labels['classes'], 1)
-
- metrics_to_values, metrics_to_updates = slim.metrics.aggregate_metric_map({
- 'Mean_Loss':
- tf.contrib.metrics.streaming_mean(total_loss),
- 'Accuracy':
- tf.contrib.metrics.streaming_accuracy(predictions,
- tf.reshape(
- class_labels,
- shape=[-1])),
- 'Recall_at_5':
- tf.contrib.metrics.streaming_recall_at_k(logits, class_labels, 5),
- })
-
- tf.summary.histogram('outputs/Predictions', predictions)
- tf.summary.histogram('outputs/Ground_Truth', class_labels)
-
- for name, value in metrics_to_values.iteritems():
- tf.summary.scalar(name, value)
-
- num_batches = int(math.ceil(num_samples / float(FLAGS.batch_size)))
-
- slim.evaluation.evaluation_loop(
- master=FLAGS.master,
- checkpoint_dir=FLAGS.checkpoint_dir,
- logdir=FLAGS.eval_dir,
- num_evals=num_batches,
- eval_op=metrics_to_updates.values(),
- eval_interval_secs=FLAGS.eval_interval_secs)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/domain_adaptation/pixel_domain_adaptation/baselines/baseline_train.py b/research/domain_adaptation/pixel_domain_adaptation/baselines/baseline_train.py
deleted file mode 100644
index 8c92bd81a7b68879000dd793ba2fd013f395f408..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/pixel_domain_adaptation/baselines/baseline_train.py
+++ /dev/null
@@ -1,161 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-r"""Trains the classification/pose baselines."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from functools import partial
-
-# Dependency imports
-
-import tensorflow as tf
-
-from domain_adaptation.datasets import dataset_factory
-from domain_adaptation.pixel_domain_adaptation import pixelda_preprocess
-from domain_adaptation.pixel_domain_adaptation import pixelda_task_towers
-
-flags = tf.app.flags
-FLAGS = flags.FLAGS
-
-slim = tf.contrib.slim
-
-flags.DEFINE_string('master', '', 'BNS name of the tensorflow server')
-
-flags.DEFINE_integer('task', 0, 'The task ID.')
-
-flags.DEFINE_integer('num_ps_tasks', 0,
- 'The number of parameter servers. If the value is 0, then '
- 'the parameters are handled locally by the worker.')
-
-flags.DEFINE_integer('batch_size', 32, 'The number of samples per batch.')
-
-flags.DEFINE_string('dataset_name', None, 'The name of the dataset.')
-
-flags.DEFINE_string('dataset_dir', None,
- 'The directory where the data is stored.')
-
-flags.DEFINE_string('split_name', None, 'The name of the train/test split.')
-
-flags.DEFINE_float('learning_rate', 0.001, 'The initial learning rate.')
-
-flags.DEFINE_integer(
- 'learning_rate_decay_steps', 20000,
- 'The frequency, in steps, at which the learning rate is decayed.')
-
-flags.DEFINE_float('learning_rate_decay_factor',
- 0.95,
- 'The factor with which the learning rate is decayed.')
-
-flags.DEFINE_float('adam_beta1', 0.5, 'The beta1 value for the AdamOptimizer')
-
-flags.DEFINE_float('weight_decay', 1e-5,
- 'The L2 coefficient on the model weights.')
-
-flags.DEFINE_string(
- 'logdir', None, 'The location of the logs and checkpoints.')
-
-flags.DEFINE_integer('save_interval_secs', 600,
- 'How often, in seconds, we save the model to disk.')
-
-flags.DEFINE_integer('save_summaries_secs', 600,
- 'How often, in seconds, we compute the summaries.')
-
-flags.DEFINE_integer(
- 'num_readers', 4,
- 'The number of parallel readers that read data from the dataset.')
-
-flags.DEFINE_float(
- 'moving_average_decay', 0.9999,
- 'The amount of decay to use for moving averages.')
-
-
-def main(unused_argv):
- tf.logging.set_verbosity(tf.logging.INFO)
- hparams = tf.contrib.training.HParams()
- hparams.weight_decay_task_classifier = FLAGS.weight_decay
-
- if FLAGS.dataset_name in ['mnist', 'mnist_m', 'usps']:
- hparams.task_tower = 'mnist'
- else:
- raise ValueError('Unknown dataset %s' % FLAGS.dataset_name)
-
- with tf.Graph().as_default():
- with tf.device(
- tf.train.replica_device_setter(FLAGS.num_ps_tasks, merge_devices=True)):
- dataset = dataset_factory.get_dataset(FLAGS.dataset_name,
- FLAGS.split_name, FLAGS.dataset_dir)
- num_classes = dataset.num_classes
-
- preprocess_fn = partial(pixelda_preprocess.preprocess_classification,
- is_training=True)
-
- images, labels = dataset_factory.provide_batch(
- FLAGS.dataset_name,
- FLAGS.split_name,
- dataset_dir=FLAGS.dataset_dir,
- num_readers=FLAGS.num_readers,
- batch_size=FLAGS.batch_size,
- num_preprocessing_threads=FLAGS.num_readers)
- # preprocess_fn=preprocess_fn)
-
- # Define the model
- logits, _ = pixelda_task_towers.add_task_specific_model(
- images, hparams, num_classes=num_classes, is_training=True)
-
- # Define the losses
- if 'classes' in labels:
- one_hot_labels = labels['classes']
- loss = tf.losses.softmax_cross_entropy(
- onehot_labels=one_hot_labels, logits=logits)
- tf.summary.scalar('losses/Classification_Loss', loss)
- else:
- raise ValueError('Only support classification for now.')
-
- total_loss = tf.losses.get_total_loss()
- tf.summary.scalar('losses/Total_Loss', total_loss)
-
- # Setup the moving averages
- moving_average_variables = slim.get_model_variables()
- variable_averages = tf.train.ExponentialMovingAverage(
- FLAGS.moving_average_decay, slim.get_or_create_global_step())
- tf.add_to_collection(
- tf.GraphKeys.UPDATE_OPS,
- variable_averages.apply(moving_average_variables))
-
- # Specify the optimization scheme:
- learning_rate = tf.train.exponential_decay(
- FLAGS.learning_rate,
- slim.get_or_create_global_step(),
- FLAGS.learning_rate_decay_steps,
- FLAGS.learning_rate_decay_factor,
- staircase=True)
-
- optimizer = tf.train.AdamOptimizer(learning_rate, beta1=FLAGS.adam_beta1)
-
- train_op = slim.learning.create_train_op(total_loss, optimizer)
-
- slim.learning.train(
- train_op,
- FLAGS.logdir,
- master=FLAGS.master,
- is_chief=(FLAGS.task == 0),
- save_summaries_secs=FLAGS.save_summaries_secs,
- save_interval_secs=FLAGS.save_interval_secs)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/domain_adaptation/pixel_domain_adaptation/hparams.py b/research/domain_adaptation/pixel_domain_adaptation/hparams.py
deleted file mode 100644
index ba9539f7d435c86f9fc92ed3406835bdaf2b50f3..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/pixel_domain_adaptation/hparams.py
+++ /dev/null
@@ -1,201 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Define model HParams."""
-import tensorflow as tf
-
-
-def create_hparams(hparam_string=None):
- """Create model hyperparameters. Parse nondefault from given string."""
- hparams = tf.contrib.training.HParams(
- # The name of the architecture to use.
- arch='resnet',
- lrelu_leakiness=0.2,
- batch_norm_decay=0.9,
- weight_decay=1e-5,
- normal_init_std=0.02,
- generator_kernel_size=3,
- discriminator_kernel_size=3,
-
- # Stop training after this many examples are processed
- # If none, train indefinitely
- num_training_examples=0,
-
- # Apply data augmentation to datasets
- # Applies only in training job
- augment_source_images=False,
- augment_target_images=False,
-
- # Discriminator
- # Number of filters in first layer of discriminator
- num_discriminator_filters=64,
- discriminator_conv_block_size=1, # How many convs to have at each size
- discriminator_filter_factor=2.0, # Multiply # filters by this each layer
- # Add gaussian noise with this stddev to every hidden layer of D
- discriminator_noise_stddev=0.2, # lmetz: Start seeing results at >= 0.1
- # If true, add this gaussian noise to input images to D as well
- discriminator_image_noise=False,
- discriminator_first_stride=1, # Stride in first conv of discriminator
- discriminator_do_pooling=False, # If true, replace stride 2 with avg pool
- discriminator_dropout_keep_prob=0.9, # keep probability for dropout
-
- # DCGAN Generator
- # Number of filters in generator decoder last layer (repeatedly halved
- # from 1st layer)
- num_decoder_filters=64,
- # Number of filters in generator encoder 1st layer (repeatedly doubled
- # after 1st layer)
- num_encoder_filters=64,
-
- # This is the shape to which the noise vector is projected (if we're
- # transferring from noise).
- # Write this way instead of [4, 4, 64] for hparam search flexibility
- projection_shape_size=4,
- projection_shape_channels=64,
-
- # Indicates the method by which we enlarge the spatial representation
- # of an image. Possible values include:
- # - resize_conv: Performs a nearest neighbor resize followed by a conv.
- # - conv2d_transpose: Performs a conv2d_transpose.
- upsample_method='resize_conv',
-
- # Visualization
- summary_steps=500, # Output image summary every N steps
-
- ###################################
- # Task Classifier Hyperparameters #
- ###################################
-
- # Which task-specific prediction tower to use. Possible choices are:
- # none: No task tower.
- # doubling_pose_estimator: classifier + quaternion regressor.
- # [conv + pool]* + FC
- # Classifiers used in DSN paper:
- # gtsrb: Classifier used for GTSRB
- # svhn: Classifier used for SVHN
- # mnist: Classifier used for MNIST
- # pose_mini: Classifier + regressor used for pose_mini
- task_tower='doubling_pose_estimator',
- weight_decay_task_classifier=1e-5,
- source_task_loss_weight=1.0,
- transferred_task_loss_weight=1.0,
-
- # Number of private layers in doubling_pose_estimator task tower
- num_private_layers=2,
-
- # The weight for the log quaternion loss we use for source and transferred
- # samples of the cropped_linemod dataset.
- # In the DSN work, 1/8 of the classifier weight worked well for our log
- # quaternion loss
- source_pose_weight=0.125 * 2.0,
- transferred_pose_weight=0.125 * 1.0,
-
- # If set to True, the style transfer network also attempts to change its
- # weights to maximize the performance of the task tower. If set to False,
- # then the style transfer network only attempts to change its weights to
- # make the transferred images more likely according to the domain
- # classifier.
- task_tower_in_g_step=True,
- task_loss_in_g_weight=1.0, # Weight of task loss in G
-
- #########################################
- # 'simple` generator arch model hparams #
- #########################################
- simple_num_conv_layers=1,
- simple_conv_filters=8,
-
- #########################
- # Resnet Hyperparameters#
- #########################
- resnet_blocks=6, # Number of resnet blocks
- resnet_filters=64, # Number of filters per conv in resnet blocks
- # If true, add original input back to result of convolutions inside the
- # resnet arch. If false, it turns into a simple stack of conv/relu/BN
- # layers.
- resnet_residuals=True,
-
- #######################################
- # The residual / interpretable model. #
- #######################################
- res_int_blocks=2, # The number of residual blocks.
- res_int_convs=2, # The number of conv calls inside each block.
- res_int_filters=64, # The number of filters used by each convolution.
-
- ####################
- # Latent variables #
- ####################
- # if true, then generate random noise and project to input for generator
- noise_channel=True,
- # The number of dimensions in the input noise vector.
- noise_dims=10,
-
- # If true, then one hot encode source image class and project as an
- # additional channel for the input to generator. This gives the generator
- # access to the class, which may help generation performance.
- condition_on_source_class=False,
-
- ########################
- # Loss Hyperparameters #
- ########################
- domain_loss_weight=1.0,
- style_transfer_loss_weight=1.0,
-
- ########################################################################
- # Encourages the transferred images to be similar to the source images #
- # using a configurable metric. #
- ########################################################################
-
- # The weight of the loss function encouraging the source and transferred
- # images to be similar. If set to 0, then the loss function is not used.
- transferred_similarity_loss_weight=0.0,
-
- # The type of loss used to encourage transferred and source image
- # similarity. Valid values include:
- # mpse: Mean Pairwise Squared Error
- # mse: Mean Squared Error
- # hinged_mse: Computes the mean squared error using squared differences
- # greater than hparams.transferred_similarity_max_diff
- # hinged_mae: Computes the mean absolute error using absolute
- # differences greater than hparams.transferred_similarity_max_diff.
- transferred_similarity_loss='mpse',
-
- # The maximum allowable difference between the source and target images.
- # This value is used, in effect, to produce a hinge loss. Note that the
- # range of values should be between 0 and 1.
- transferred_similarity_max_diff=0.4,
-
- ################################
- # Optimization Hyperparameters #
- ################################
- learning_rate=0.001,
- batch_size=32,
- lr_decay_steps=20000,
- lr_decay_rate=0.95,
-
- # Recomendation from the DCGAN paper:
- adam_beta1=0.5,
- clip_gradient_norm=5.0,
-
- # The number of times we run the discriminator train_op in a row.
- discriminator_steps=1,
-
- # The number of times we run the generator train_op in a row.
- generator_steps=1)
-
- if hparam_string:
- tf.logging.info('Parsing command line hparams: %s', hparam_string)
- hparams.parse(hparam_string)
-
- tf.logging.info('Final parsed hparams: %s', hparams.values())
- return hparams
diff --git a/research/domain_adaptation/pixel_domain_adaptation/pixelda_eval.py b/research/domain_adaptation/pixel_domain_adaptation/pixelda_eval.py
deleted file mode 100644
index 23824249a9e95586ed85e40cd89c5f6814977969..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/pixel_domain_adaptation/pixelda_eval.py
+++ /dev/null
@@ -1,298 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-r"""Evaluates the PIXELDA model.
-
--- Compiles the model for CPU.
-$ bazel build -c opt third_party/tensorflow_models/domain_adaptation/pixel_domain_adaptation:pixelda_eval
-
--- Compile the model for GPU.
-$ bazel build -c opt --copt=-mavx --config=cuda \
- third_party/tensorflow_models/domain_adaptation/pixel_domain_adaptation:pixelda_eval
-
--- Runs the training.
-$ ./bazel-bin/third_party/tensorflow_models/domain_adaptation/pixel_domain_adaptation/pixelda_eval \
- --source_dataset=mnist \
- --target_dataset=mnist_m \
- --dataset_dir=/tmp/datasets/ \
- --alsologtostderr
-
--- Visualize the results.
-$ bash learning/brain/tensorboard/tensorboard.sh \
- --port 2222 --logdir=/tmp/pixelda/
-"""
-from functools import partial
-import math
-
-# Dependency imports
-
-import tensorflow as tf
-
-from domain_adaptation.datasets import dataset_factory
-from domain_adaptation.pixel_domain_adaptation import pixelda_model
-from domain_adaptation.pixel_domain_adaptation import pixelda_preprocess
-from domain_adaptation.pixel_domain_adaptation import pixelda_utils
-from domain_adaptation.pixel_domain_adaptation import pixelda_losses
-from domain_adaptation.pixel_domain_adaptation.hparams import create_hparams
-
-slim = tf.contrib.slim
-
-flags = tf.app.flags
-FLAGS = flags.FLAGS
-
-flags.DEFINE_string('master', '', 'BNS name of the TensorFlow master to use.')
-
-flags.DEFINE_string('checkpoint_dir', '/tmp/pixelda/',
- 'Directory where the model was written to.')
-
-flags.DEFINE_string('eval_dir', '/tmp/pixelda/',
- 'Directory where the results are saved to.')
-
-flags.DEFINE_integer('eval_interval_secs', 60,
- 'The frequency, in seconds, with which evaluation is run.')
-
-flags.DEFINE_string('target_split_name', 'test',
- 'The name of the train/test split.')
-flags.DEFINE_string('source_split_name', 'train', 'Split for source dataset.'
- ' Defaults to train.')
-
-flags.DEFINE_string('source_dataset', 'mnist',
- 'The name of the source dataset.')
-
-flags.DEFINE_string('target_dataset', 'mnist_m',
- 'The name of the target dataset.')
-
-flags.DEFINE_string(
- 'dataset_dir',
- '', # None,
- 'The directory where the datasets can be found.')
-
-flags.DEFINE_integer(
- 'num_readers', 4,
- 'The number of parallel readers that read data from the dataset.')
-
-flags.DEFINE_integer('num_preprocessing_threads', 4,
- 'The number of threads used to create the batches.')
-
-# HParams
-
-flags.DEFINE_string('hparams', '', 'Comma separated hyperparameter values')
-
-
-def run_eval(run_dir, checkpoint_dir, hparams):
- """Runs the eval loop.
-
- Args:
- run_dir: The directory where eval specific logs are placed
- checkpoint_dir: The directory where the checkpoints are stored
- hparams: The hyperparameters struct.
-
- Raises:
- ValueError: if hparams.arch is not recognized.
- """
- for checkpoint_path in slim.evaluation.checkpoints_iterator(
- checkpoint_dir, FLAGS.eval_interval_secs):
- with tf.Graph().as_default():
- #########################
- # Preprocess the inputs #
- #########################
- target_dataset = dataset_factory.get_dataset(
- FLAGS.target_dataset,
- split_name=FLAGS.target_split_name,
- dataset_dir=FLAGS.dataset_dir)
- target_images, target_labels = dataset_factory.provide_batch(
- FLAGS.target_dataset, FLAGS.target_split_name, FLAGS.dataset_dir,
- FLAGS.num_readers, hparams.batch_size,
- FLAGS.num_preprocessing_threads)
- num_target_classes = target_dataset.num_classes
- target_labels['class'] = tf.argmax(target_labels['classes'], 1)
- del target_labels['classes']
-
- if hparams.arch not in ['dcgan']:
- source_dataset = dataset_factory.get_dataset(
- FLAGS.source_dataset,
- split_name=FLAGS.source_split_name,
- dataset_dir=FLAGS.dataset_dir)
- num_source_classes = source_dataset.num_classes
- source_images, source_labels = dataset_factory.provide_batch(
- FLAGS.source_dataset, FLAGS.source_split_name, FLAGS.dataset_dir,
- FLAGS.num_readers, hparams.batch_size,
- FLAGS.num_preprocessing_threads)
- source_labels['class'] = tf.argmax(source_labels['classes'], 1)
- del source_labels['classes']
- if num_source_classes != num_target_classes:
- raise ValueError(
- 'Input and output datasets must have same number of classes')
- else:
- source_images = None
- source_labels = None
-
- ####################
- # Define the model #
- ####################
- end_points = pixelda_model.create_model(
- hparams,
- target_images,
- source_images=source_images,
- source_labels=source_labels,
- is_training=False,
- num_classes=num_target_classes)
-
- #######################
- # Metrics & Summaries #
- #######################
- names_to_values, names_to_updates = create_metrics(end_points,
- source_labels,
- target_labels, hparams)
- pixelda_utils.summarize_model(end_points)
- pixelda_utils.summarize_transferred_grid(
- end_points['transferred_images'], source_images, name='Transferred')
- if 'source_images_recon' in end_points:
- pixelda_utils.summarize_transferred_grid(
- end_points['source_images_recon'],
- source_images,
- name='Source Reconstruction')
- pixelda_utils.summarize_images(target_images, 'Target')
-
- for name, value in names_to_values.iteritems():
- tf.summary.scalar(name, value)
-
- # Use the entire split by default
- num_examples = target_dataset.num_samples
-
- num_batches = math.ceil(num_examples / float(hparams.batch_size))
- global_step = slim.get_or_create_global_step()
-
- result = slim.evaluation.evaluate_once(
- master=FLAGS.master,
- checkpoint_path=checkpoint_path,
- logdir=run_dir,
- num_evals=num_batches,
- eval_op=names_to_updates.values(),
- final_op=names_to_values)
-
-
-def to_degrees(log_quaternion_loss):
- """Converts a log quaternion distance to an angle.
-
- Args:
- log_quaternion_loss: The log quaternion distance between two
- unit quaternions (or a batch of pairs of quaternions).
-
- Returns:
- The angle in degrees of the implied angle-axis representation.
- """
- return tf.acos(-(tf.exp(log_quaternion_loss) - 1)) * 2 * 180 / math.pi
-
-
-def create_metrics(end_points, source_labels, target_labels, hparams):
- """Create metrics for the model.
-
- Args:
- end_points: A dictionary of end point name to tensor
- source_labels: Labels for source images. batch_size x 1
- target_labels: Labels for target images. batch_size x 1
- hparams: The hyperparameters struct.
-
- Returns:
- Tuple of (names_to_values, names_to_updates), dictionaries that map a metric
- name to its value and update op, respectively
-
- """
- ###########################################
- # Evaluate the Domain Prediction Accuracy #
- ###########################################
- batch_size = hparams.batch_size
- names_to_values, names_to_updates = slim.metrics.aggregate_metric_map({
- ('eval/Domain_Accuracy-Transferred'):
- tf.contrib.metrics.streaming_accuracy(
- tf.to_int32(
- tf.round(tf.sigmoid(end_points[
- 'transferred_domain_logits']))),
- tf.zeros(batch_size, dtype=tf.int32)),
- ('eval/Domain_Accuracy-Target'):
- tf.contrib.metrics.streaming_accuracy(
- tf.to_int32(
- tf.round(tf.sigmoid(end_points['target_domain_logits']))),
- tf.ones(batch_size, dtype=tf.int32))
- })
-
- ################################
- # Evaluate the task classifier #
- ################################
- if 'source_task_logits' in end_points:
- metric_name = 'eval/Task_Accuracy-Source'
- names_to_values[metric_name], names_to_updates[
- metric_name] = tf.contrib.metrics.streaming_accuracy(
- tf.argmax(end_points['source_task_logits'], 1),
- source_labels['class'])
-
- if 'transferred_task_logits' in end_points:
- metric_name = 'eval/Task_Accuracy-Transferred'
- names_to_values[metric_name], names_to_updates[
- metric_name] = tf.contrib.metrics.streaming_accuracy(
- tf.argmax(end_points['transferred_task_logits'], 1),
- source_labels['class'])
-
- if 'target_task_logits' in end_points:
- metric_name = 'eval/Task_Accuracy-Target'
- names_to_values[metric_name], names_to_updates[
- metric_name] = tf.contrib.metrics.streaming_accuracy(
- tf.argmax(end_points['target_task_logits'], 1),
- target_labels['class'])
-
- ##########################################################################
- # Pose data-specific losses.
- ##########################################################################
- if 'quaternion' in source_labels.keys():
- params = {}
- params['use_logging'] = False
- params['batch_size'] = batch_size
-
- angle_loss_source = to_degrees(
- pixelda_losses.log_quaternion_loss_batch(end_points[
- 'source_quaternion'], source_labels['quaternion'], params))
- angle_loss_transferred = to_degrees(
- pixelda_losses.log_quaternion_loss_batch(end_points[
- 'transferred_quaternion'], source_labels['quaternion'], params))
- angle_loss_target = to_degrees(
- pixelda_losses.log_quaternion_loss_batch(end_points[
- 'target_quaternion'], target_labels['quaternion'], params))
-
- metric_name = 'eval/Angle_Loss-Source'
- names_to_values[metric_name], names_to_updates[
- metric_name] = slim.metrics.mean(angle_loss_source)
-
- metric_name = 'eval/Angle_Loss-Transferred'
- names_to_values[metric_name], names_to_updates[
- metric_name] = slim.metrics.mean(angle_loss_transferred)
-
- metric_name = 'eval/Angle_Loss-Target'
- names_to_values[metric_name], names_to_updates[
- metric_name] = slim.metrics.mean(angle_loss_target)
-
- return names_to_values, names_to_updates
-
-
-def main(_):
- tf.logging.set_verbosity(tf.logging.INFO)
- hparams = create_hparams(FLAGS.hparams)
- run_eval(
- run_dir=FLAGS.eval_dir,
- checkpoint_dir=FLAGS.checkpoint_dir,
- hparams=hparams)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/domain_adaptation/pixel_domain_adaptation/pixelda_losses.py b/research/domain_adaptation/pixel_domain_adaptation/pixelda_losses.py
deleted file mode 100644
index cf39765d4d28c5a04cb8868cdc465cdd0129b0df..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/pixel_domain_adaptation/pixelda_losses.py
+++ /dev/null
@@ -1,385 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Defines the various loss functions in use by the PIXELDA model."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-# Dependency imports
-
-import tensorflow as tf
-
-slim = tf.contrib.slim
-
-
-def add_domain_classifier_losses(end_points, hparams):
- """Adds losses related to the domain-classifier.
-
- Args:
- end_points: A map of network end point names to `Tensors`.
- hparams: The hyperparameters struct.
-
- Returns:
- loss: A `Tensor` representing the total task-classifier loss.
- """
- if hparams.domain_loss_weight == 0:
- tf.logging.info(
- 'Domain classifier loss weight is 0, so not creating losses.')
- return 0
-
- # The domain prediction loss is minimized with respect to the domain
- # classifier features only. Its aim is to predict the domain of the images.
- # Note: 1 = 'real image' label, 0 = 'fake image' label
- transferred_domain_loss = tf.losses.sigmoid_cross_entropy(
- multi_class_labels=tf.zeros_like(end_points['transferred_domain_logits']),
- logits=end_points['transferred_domain_logits'])
- tf.summary.scalar('Domain_loss_transferred', transferred_domain_loss)
-
- target_domain_loss = tf.losses.sigmoid_cross_entropy(
- multi_class_labels=tf.ones_like(end_points['target_domain_logits']),
- logits=end_points['target_domain_logits'])
- tf.summary.scalar('Domain_loss_target', target_domain_loss)
-
- # Compute the total domain loss:
- total_domain_loss = transferred_domain_loss + target_domain_loss
- total_domain_loss *= hparams.domain_loss_weight
- tf.summary.scalar('Domain_loss_total', total_domain_loss)
-
- return total_domain_loss
-
-def log_quaternion_loss_batch(predictions, labels, params):
- """A helper function to compute the error between quaternions.
-
- Args:
- predictions: A Tensor of size [batch_size, 4].
- labels: A Tensor of size [batch_size, 4].
- params: A dictionary of parameters. Expecting 'use_logging', 'batch_size'.
-
- Returns:
- A Tensor of size [batch_size], denoting the error between the quaternions.
- """
- use_logging = params['use_logging']
- assertions = []
- if use_logging:
- assertions.append(
- tf.Assert(
- tf.reduce_all(
- tf.less(
- tf.abs(tf.reduce_sum(tf.square(predictions), [1]) - 1),
- 1e-4)),
- ['The l2 norm of each prediction quaternion vector should be 1.']))
- assertions.append(
- tf.Assert(
- tf.reduce_all(
- tf.less(
- tf.abs(tf.reduce_sum(tf.square(labels), [1]) - 1), 1e-4)),
- ['The l2 norm of each label quaternion vector should be 1.']))
-
- with tf.control_dependencies(assertions):
- product = tf.multiply(predictions, labels)
- internal_dot_products = tf.reduce_sum(product, [1])
-
- if use_logging:
- internal_dot_products = tf.Print(internal_dot_products, [
- internal_dot_products,
- tf.shape(internal_dot_products)
- ], 'internal_dot_products:')
-
- logcost = tf.log(1e-4 + 1 - tf.abs(internal_dot_products))
- return logcost
-
-
-def log_quaternion_loss(predictions, labels, params):
- """A helper function to compute the mean error between batches of quaternions.
-
- The caller is expected to add the loss to the graph.
-
- Args:
- predictions: A Tensor of size [batch_size, 4].
- labels: A Tensor of size [batch_size, 4].
- params: A dictionary of parameters. Expecting 'use_logging', 'batch_size'.
-
- Returns:
- A Tensor of size 1, denoting the mean error between batches of quaternions.
- """
- use_logging = params['use_logging']
- logcost = log_quaternion_loss_batch(predictions, labels, params)
- logcost = tf.reduce_sum(logcost, [0])
- batch_size = params['batch_size']
- logcost = tf.multiply(logcost, 1.0 / batch_size, name='log_quaternion_loss')
- if use_logging:
- logcost = tf.Print(
- logcost, [logcost], '[logcost]', name='log_quaternion_loss_print')
- return logcost
-
-def _quaternion_loss(labels, predictions, weight, batch_size, domain,
- add_summaries):
- """Creates a Quaternion Loss.
-
- Args:
- labels: The true quaternions.
- predictions: The predicted quaternions.
- weight: A scalar weight.
- batch_size: The size of the batches.
- domain: The name of the domain from which the labels were taken.
- add_summaries: Whether or not to add summaries for the losses.
-
- Returns:
- A `Tensor` representing the loss.
- """
- assert domain in ['Source', 'Transferred']
-
- params = {'use_logging': False, 'batch_size': batch_size}
- loss = weight * log_quaternion_loss(labels, predictions, params)
-
- if add_summaries:
- assert_op = tf.Assert(tf.is_finite(loss), [loss])
- with tf.control_dependencies([assert_op]):
- tf.summary.histogram(
- 'Log_Quaternion_Loss_%s' % domain, loss, collections='losses')
- tf.summary.scalar(
- 'Task_Quaternion_Loss_%s' % domain, loss, collections='losses')
-
- return loss
-
-
-def _add_task_specific_losses(end_points, source_labels, num_classes, hparams,
- add_summaries=False):
- """Adds losses related to the task-classifier.
-
- Args:
- end_points: A map of network end point names to `Tensors`.
- source_labels: A dictionary of output labels to `Tensors`.
- num_classes: The number of classes used by the classifier.
- hparams: The hyperparameters struct.
- add_summaries: Whether or not to add the summaries.
-
- Returns:
- loss: A `Tensor` representing the total task-classifier loss.
- """
- # TODO(ddohan): Make sure the l2 regularization is added to the loss
-
- one_hot_labels = slim.one_hot_encoding(source_labels['class'], num_classes)
- total_loss = 0
-
- if 'source_task_logits' in end_points:
- loss = tf.losses.softmax_cross_entropy(
- onehot_labels=one_hot_labels,
- logits=end_points['source_task_logits'],
- weights=hparams.source_task_loss_weight)
- if add_summaries:
- tf.summary.scalar('Task_Classifier_Loss_Source', loss)
- total_loss += loss
-
- if 'transferred_task_logits' in end_points:
- loss = tf.losses.softmax_cross_entropy(
- onehot_labels=one_hot_labels,
- logits=end_points['transferred_task_logits'],
- weights=hparams.transferred_task_loss_weight)
- if add_summaries:
- tf.summary.scalar('Task_Classifier_Loss_Transferred', loss)
- total_loss += loss
-
- #########################
- # Pose specific losses. #
- #########################
- if 'quaternion' in source_labels:
- total_loss += _quaternion_loss(
- source_labels['quaternion'],
- end_points['source_quaternion'],
- hparams.source_pose_weight,
- hparams.batch_size,
- 'Source',
- add_summaries)
-
- total_loss += _quaternion_loss(
- source_labels['quaternion'],
- end_points['transferred_quaternion'],
- hparams.transferred_pose_weight,
- hparams.batch_size,
- 'Transferred',
- add_summaries)
-
- if add_summaries:
- tf.summary.scalar('Task_Loss_Total', total_loss)
-
- return total_loss
-
-
-def _transferred_similarity_loss(reconstructions,
- source_images,
- weight=1.0,
- method='mse',
- max_diff=0.4,
- name='similarity'):
- """Computes a loss encouraging similarity between source and transferred.
-
- Args:
- reconstructions: A `Tensor` of shape [batch_size, height, width, channels]
- source_images: A `Tensor` of shape [batch_size, height, width, channels].
- weight: Multiple similarity loss by this weight before returning
- method: One of:
- mpse = Mean Pairwise Squared Error
- mse = Mean Squared Error
- hinged_mse = Computes the mean squared error using squared differences
- greater than hparams.transferred_similarity_max_diff
- hinged_mae = Computes the mean absolute error using absolute
- differences greater than hparams.transferred_similarity_max_diff.
- max_diff: Maximum unpenalized difference for hinged losses
- name: Identifying name to use for creating summaries
-
-
- Returns:
- A `Tensor` representing the transferred similarity loss.
-
- Raises:
- ValueError: if `method` is not recognized.
- """
- if weight == 0:
- return 0
-
- source_channels = source_images.shape.as_list()[-1]
- reconstruction_channels = reconstructions.shape.as_list()[-1]
-
- # Convert grayscale source to RGB if target is RGB
- if source_channels == 1 and reconstruction_channels != 1:
- source_images = tf.tile(source_images, [1, 1, 1, reconstruction_channels])
- if reconstruction_channels == 1 and source_channels != 1:
- reconstructions = tf.tile(reconstructions, [1, 1, 1, source_channels])
-
- if method == 'mpse':
- reconstruction_similarity_loss_fn = (
- tf.contrib.losses.mean_pairwise_squared_error)
- elif method == 'masked_mpse':
-
- def masked_mpse(predictions, labels, weight):
- """Masked mpse assuming we have a depth to create a mask from."""
- assert labels.shape.as_list()[-1] == 4
- mask = tf.to_float(tf.less(labels[:, :, :, 3:4], 0.99))
- mask = tf.tile(mask, [1, 1, 1, 4])
- predictions *= mask
- labels *= mask
- tf.image_summary('masked_pred', predictions)
- tf.image_summary('masked_label', labels)
- return tf.contrib.losses.mean_pairwise_squared_error(
- predictions, labels, weight)
-
- reconstruction_similarity_loss_fn = masked_mpse
- elif method == 'mse':
- reconstruction_similarity_loss_fn = tf.contrib.losses.mean_squared_error
- elif method == 'hinged_mse':
-
- def hinged_mse(predictions, labels, weight):
- diffs = tf.square(predictions - labels)
- diffs = tf.maximum(0.0, diffs - max_diff)
- return tf.reduce_mean(diffs) * weight
-
- reconstruction_similarity_loss_fn = hinged_mse
- elif method == 'hinged_mae':
-
- def hinged_mae(predictions, labels, weight):
- diffs = tf.abs(predictions - labels)
- diffs = tf.maximum(0.0, diffs - max_diff)
- return tf.reduce_mean(diffs) * weight
-
- reconstruction_similarity_loss_fn = hinged_mae
- else:
- raise ValueError('Unknown reconstruction loss %s' % method)
-
- reconstruction_similarity_loss = reconstruction_similarity_loss_fn(
- reconstructions, source_images, weight)
-
- name = '%s_Similarity_(%s)' % (name, method)
- tf.summary.scalar(name, reconstruction_similarity_loss)
- return reconstruction_similarity_loss
-
-
-def g_step_loss(source_images, source_labels, end_points, hparams, num_classes):
- """Configures the loss function which runs during the g-step.
-
- Args:
- source_images: A `Tensor` of shape [batch_size, height, width, channels].
- source_labels: A dictionary of `Tensors` of shape [batch_size]. Valid keys
- are 'class' and 'quaternion'.
- end_points: A map of the network end points.
- hparams: The hyperparameters struct.
- num_classes: Number of classes for classifier loss
-
- Returns:
- A `Tensor` representing a loss function.
-
- Raises:
- ValueError: if hparams.transferred_similarity_loss_weight is non-zero but
- hparams.transferred_similarity_loss is invalid.
- """
- generator_loss = 0
-
- ################################################################
- # Adds a loss which encourages the discriminator probabilities #
- # to be high (near one).
- ################################################################
-
- # As per the GAN paper, maximize the log probs, instead of minimizing
- # log(1-probs). Since we're minimizing, we'll minimize -log(probs) which is
- # the same thing.
- style_transfer_loss = tf.losses.sigmoid_cross_entropy(
- logits=end_points['transferred_domain_logits'],
- multi_class_labels=tf.ones_like(end_points['transferred_domain_logits']),
- weights=hparams.style_transfer_loss_weight)
- tf.summary.scalar('Style_transfer_loss', style_transfer_loss)
- generator_loss += style_transfer_loss
-
- # Optimizes the style transfer network to produce transferred images similar
- # to the source images.
- generator_loss += _transferred_similarity_loss(
- end_points['transferred_images'],
- source_images,
- weight=hparams.transferred_similarity_loss_weight,
- method=hparams.transferred_similarity_loss,
- name='transferred_similarity')
-
- # Optimizes the style transfer network to maximize classification accuracy.
- if source_labels is not None and hparams.task_tower_in_g_step:
- generator_loss += _add_task_specific_losses(
- end_points, source_labels, num_classes,
- hparams) * hparams.task_loss_in_g_weight
-
- return generator_loss
-
-
-def d_step_loss(end_points, source_labels, num_classes, hparams):
- """Configures the losses during the D-Step.
-
- Note that during the D-step, the model optimizes both the domain (binary)
- classifier and the task classifier.
-
- Args:
- end_points: A map of the network end points.
- source_labels: A dictionary of output labels to `Tensors`.
- num_classes: The number of classes used by the classifier.
- hparams: The hyperparameters struct.
-
- Returns:
- A `Tensor` representing the value of the D-step loss.
- """
- domain_classifier_loss = add_domain_classifier_losses(end_points, hparams)
-
- task_classifier_loss = 0
- if source_labels is not None:
- task_classifier_loss = _add_task_specific_losses(
- end_points, source_labels, num_classes, hparams, add_summaries=True)
-
- return domain_classifier_loss + task_classifier_loss
diff --git a/research/domain_adaptation/pixel_domain_adaptation/pixelda_model.py b/research/domain_adaptation/pixel_domain_adaptation/pixelda_model.py
deleted file mode 100644
index 16b550a62d88ec2724c91f9dab9e3b34c736ec4f..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/pixel_domain_adaptation/pixelda_model.py
+++ /dev/null
@@ -1,713 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Contains the Domain Adaptation via Style Transfer (PixelDA) model components.
-
-A number of details in the implementation make reference to one of the following
-works:
-
-- "Unsupervised Representation Learning with Deep Convolutional
- Generative Adversarial Networks""
- https://arxiv.org/abs/1511.06434
-
-This paper makes several architecture recommendations:
-1. Use strided convs in discriminator, fractional-strided convs in generator
-2. batchnorm everywhere
-3. remove fully connected layers for deep models
-4. ReLu for all layers in generator, except tanh on output
-5. LeakyReLu for everything in discriminator
-"""
-import functools
-import math
-
-# Dependency imports
-import numpy as np
-
-import tensorflow as tf
-
-slim = tf.contrib.slim
-
-from domain_adaptation.pixel_domain_adaptation import pixelda_task_towers
-
-
-def create_model(hparams,
- target_images,
- source_images=None,
- source_labels=None,
- is_training=False,
- noise=None,
- num_classes=None):
- """Create a GAN model.
-
- Arguments:
- hparams: HParam object specifying model params
- target_images: A `Tensor` of size [batch_size, height, width, channels]. It
- is assumed that the images are [-1, 1] normalized.
- source_images: A `Tensor` of size [batch_size, height, width, channels]. It
- is assumed that the images are [-1, 1] normalized.
- source_labels: A `Tensor` of size [batch_size] of categorical labels between
- [0, num_classes]
- is_training: whether model is currently training
- noise: If None, model generates its own noise. Otherwise use provided.
- num_classes: Number of classes for classification
-
- Returns:
- end_points dict with model outputs
-
- Raises:
- ValueError: unknown hparams.arch setting
- """
- if num_classes is None and hparams.arch in ['resnet', 'simple']:
- raise ValueError('Num classes must be provided to create task classifier')
-
- if target_images.dtype != tf.float32:
- raise ValueError('target_images must be tf.float32 and [-1, 1] normalized.')
- if source_images is not None and source_images.dtype != tf.float32:
- raise ValueError('source_images must be tf.float32 and [-1, 1] normalized.')
-
- ###########################
- # Create latent variables #
- ###########################
- latent_vars = dict()
-
- if hparams.noise_channel:
- noise_shape = [hparams.batch_size, hparams.noise_dims]
- if noise is not None:
- assert noise.shape.as_list() == noise_shape
- tf.logging.info('Using provided noise')
- else:
- tf.logging.info('Using random noise')
- noise = tf.random_uniform(
- shape=noise_shape,
- minval=-1,
- maxval=1,
- dtype=tf.float32,
- name='random_noise')
- latent_vars['noise'] = noise
-
- ####################
- # Create generator #
- ####################
-
- with slim.arg_scope(
- [slim.conv2d, slim.conv2d_transpose, slim.fully_connected],
- normalizer_params=batch_norm_params(is_training,
- hparams.batch_norm_decay),
- weights_initializer=tf.random_normal_initializer(
- stddev=hparams.normal_init_std),
- weights_regularizer=tf.contrib.layers.l2_regularizer(
- hparams.weight_decay)):
- with slim.arg_scope([slim.conv2d], padding='SAME'):
- if hparams.arch == 'dcgan':
- end_points = dcgan(
- target_images, latent_vars, hparams, scope='generator')
- elif hparams.arch == 'resnet':
- end_points = resnet_generator(
- source_images,
- target_images.shape.as_list()[1:4],
- hparams=hparams,
- latent_vars=latent_vars)
- elif hparams.arch == 'residual_interpretation':
- end_points = residual_interpretation_generator(
- source_images, is_training=is_training, hparams=hparams)
- elif hparams.arch == 'simple':
- end_points = simple_generator(
- source_images,
- target_images,
- is_training=is_training,
- hparams=hparams,
- latent_vars=latent_vars)
- elif hparams.arch == 'identity':
- # Pass through unmodified, besides changing # channels
- # Used to calculate baseline numbers
- # Also set `generator_steps=0` for baseline
- if hparams.generator_steps:
- raise ValueError('Must set generator_steps=0 for identity arch. Is %s'
- % hparams.generator_steps)
- transferred_images = source_images
- source_channels = source_images.shape.as_list()[-1]
- target_channels = target_images.shape.as_list()[-1]
- if source_channels == 1 and target_channels == 3:
- transferred_images = tf.tile(source_images, [1, 1, 1, 3])
- if source_channels == 3 and target_channels == 1:
- transferred_images = tf.image.rgb_to_grayscale(source_images)
- end_points = {'transferred_images': transferred_images}
- else:
- raise ValueError('Unknown architecture: %s' % hparams.arch)
-
- #####################
- # Domain Classifier #
- #####################
- if hparams.arch in [
- 'dcgan', 'resnet', 'residual_interpretation', 'simple', 'identity',
- ]:
-
- # Add a discriminator for these architectures
- end_points['transferred_domain_logits'] = predict_domain(
- end_points['transferred_images'],
- hparams,
- is_training=is_training,
- reuse=False)
- end_points['target_domain_logits'] = predict_domain(
- target_images,
- hparams,
- is_training=is_training,
- reuse=True)
-
- ###################
- # Task Classifier #
- ###################
- if hparams.task_tower != 'none' and hparams.arch in [
- 'resnet', 'residual_interpretation', 'simple', 'identity',
- ]:
- with tf.variable_scope('discriminator'):
- with tf.variable_scope('task_tower'):
- end_points['source_task_logits'], end_points[
- 'source_quaternion'] = pixelda_task_towers.add_task_specific_model(
- source_images,
- hparams,
- num_classes=num_classes,
- is_training=is_training,
- reuse_private=False,
- private_scope='source_task_classifier',
- reuse_shared=False)
- end_points['transferred_task_logits'], end_points[
- 'transferred_quaternion'] = (
- pixelda_task_towers.add_task_specific_model(
- end_points['transferred_images'],
- hparams,
- num_classes=num_classes,
- is_training=is_training,
- reuse_private=False,
- private_scope='transferred_task_classifier',
- reuse_shared=True))
- end_points['target_task_logits'], end_points[
- 'target_quaternion'] = pixelda_task_towers.add_task_specific_model(
- target_images,
- hparams,
- num_classes=num_classes,
- is_training=is_training,
- reuse_private=True,
- private_scope='transferred_task_classifier',
- reuse_shared=True)
- # Remove any endpoints with None values
- return dict((k, v) for k, v in end_points.iteritems() if v is not None)
-
-
-def batch_norm_params(is_training, batch_norm_decay):
- return {
- 'is_training': is_training,
- # Decay for the moving averages.
- 'decay': batch_norm_decay,
- # epsilon to prevent 0s in variance.
- 'epsilon': 0.001,
- }
-
-
-def lrelu(x, leakiness=0.2):
- """Relu, with optional leaky support."""
- return tf.where(tf.less(x, 0.0), leakiness * x, x, name='leaky_relu')
-
-
-def upsample(net, num_filters, scale=2, method='resize_conv', scope=None):
- """Performs spatial upsampling of the given features.
-
- Args:
- net: A `Tensor` of shape [batch_size, height, width, filters].
- num_filters: The number of output filters.
- scale: The scale of the upsampling. Must be a positive integer greater or
- equal to two.
- method: The method by which the features are upsampled. Valid options
- include 'resize_conv' and 'conv2d_transpose'.
- scope: An optional variable scope.
-
- Returns:
- A new set of features of shape
- [batch_size, height*scale, width*scale, num_filters].
-
- Raises:
- ValueError: if `method` is not valid or
- """
- if scale < 2:
- raise ValueError('scale must be greater or equal to two.')
-
- with tf.variable_scope(scope, 'upsample', [net]):
- if method == 'resize_conv':
- net = tf.image.resize_nearest_neighbor(
- net, [net.shape.as_list()[1] * scale,
- net.shape.as_list()[2] * scale],
- align_corners=True,
- name='resize')
- return slim.conv2d(net, num_filters, stride=1, scope='conv')
- elif method == 'conv2d_transpose':
- return slim.conv2d_transpose(net, num_filters, scope='deconv')
- else:
- raise ValueError('Upsample method [%s] was not recognized.' % method)
-
-
-def project_latent_vars(hparams, proj_shape, latent_vars, combine_method='sum'):
- """Generate noise and project to input volume size.
-
- Args:
- hparams: The hyperparameter HParams struct.
- proj_shape: Shape to project noise (not including batch size).
- latent_vars: dictionary of `'key': Tensor of shape [batch_size, N]`
- combine_method: How to combine the projected values.
- sum = project to volume then sum
- concat = concatenate along last dimension (i.e. channel)
-
- Returns:
- If combine_method=sum, a `Tensor` of size `hparams.projection_shape`
- If combine_method=concat and there are N latent vars, a `Tensor` of size
- `hparams.projection_shape`, with the last channel multiplied by N
-
-
- Raises:
- ValueError: combine_method is not one of sum/concat
- """
- values = []
- for var in latent_vars:
- with tf.variable_scope(var):
- # Project & reshape noise to a HxWxC input
- projected = slim.fully_connected(
- latent_vars[var],
- np.prod(proj_shape),
- activation_fn=tf.nn.relu,
- normalizer_fn=slim.batch_norm)
- values.append(tf.reshape(projected, [hparams.batch_size] + proj_shape))
-
- if combine_method == 'sum':
- result = values[0]
- for value in values[1:]:
- result += value
- elif combine_method == 'concat':
- # Concatenate along last axis
- result = tf.concat(values, len(proj_shape))
- else:
- raise ValueError('Unknown combine_method %s' % combine_method)
-
- tf.logging.info('Latent variables projected to size %s volume', result.shape)
-
- return result
-
-
-def resnet_block(net, hparams):
- """Create a resnet block."""
- net_in = net
- net = slim.conv2d(
- net,
- hparams.resnet_filters,
- stride=1,
- normalizer_fn=slim.batch_norm,
- activation_fn=tf.nn.relu)
- net = slim.conv2d(
- net,
- hparams.resnet_filters,
- stride=1,
- normalizer_fn=slim.batch_norm,
- activation_fn=None)
- if hparams.resnet_residuals:
- net += net_in
- return net
-
-
-def resnet_stack(images, output_shape, hparams, scope=None):
- """Create a resnet style transfer block.
-
- Args:
- images: [batch-size, height, width, channels] image tensor to feed as input
- output_shape: output image shape in form [height, width, channels]
- hparams: hparams objects
- scope: Variable scope
-
- Returns:
- Images after processing with resnet blocks.
- """
- end_points = {}
- if hparams.noise_channel:
- # separate the noise for visualization
- end_points['noise'] = images[:, :, :, -1]
- assert images.shape.as_list()[1:3] == output_shape[0:2]
-
- with tf.variable_scope(scope, 'resnet_style_transfer', [images]):
- with slim.arg_scope(
- [slim.conv2d],
- normalizer_fn=slim.batch_norm,
- kernel_size=[hparams.generator_kernel_size] * 2,
- stride=1):
- net = slim.conv2d(
- images,
- hparams.resnet_filters,
- normalizer_fn=None,
- activation_fn=tf.nn.relu)
- for block in range(hparams.resnet_blocks):
- net = resnet_block(net, hparams)
- end_points['resnet_block_{}'.format(block)] = net
-
- net = slim.conv2d(
- net,
- output_shape[-1],
- kernel_size=[1, 1],
- normalizer_fn=None,
- activation_fn=tf.nn.tanh,
- scope='conv_out')
- end_points['transferred_images'] = net
- return net, end_points
-
-
-def predict_domain(images,
- hparams,
- is_training=False,
- reuse=False,
- scope='discriminator'):
- """Creates a discriminator for a GAN.
-
- Args:
- images: A `Tensor` of size [batch_size, height, width, channels]. It is
- assumed that the images are centered between -1 and 1.
- hparams: hparam object with params for discriminator
- is_training: Specifies whether or not we're training or testing.
- reuse: Whether to reuse variable scope
- scope: An optional variable_scope.
-
- Returns:
- [batch size, 1] - logit output of discriminator.
- """
- with tf.variable_scope(scope, 'discriminator', [images], reuse=reuse):
- lrelu_partial = functools.partial(lrelu, leakiness=hparams.lrelu_leakiness)
- with slim.arg_scope(
- [slim.conv2d],
- kernel_size=[hparams.discriminator_kernel_size] * 2,
- activation_fn=lrelu_partial,
- stride=2,
- normalizer_fn=slim.batch_norm):
-
- def add_noise(hidden, scope_num=None):
- if scope_num:
- hidden = slim.dropout(
- hidden,
- hparams.discriminator_dropout_keep_prob,
- is_training=is_training,
- scope='dropout_%s' % scope_num)
- if hparams.discriminator_noise_stddev == 0:
- return hidden
- return hidden + tf.random_normal(
- hidden.shape.as_list(),
- mean=0.0,
- stddev=hparams.discriminator_noise_stddev)
-
- # As per the recommendation of the DCGAN paper, we don't use batch norm
- # on the discriminator input (https://arxiv.org/pdf/1511.06434v2.pdf).
- if hparams.discriminator_image_noise:
- images = add_noise(images)
- net = slim.conv2d(
- images,
- hparams.num_discriminator_filters,
- normalizer_fn=None,
- stride=hparams.discriminator_first_stride,
- scope='conv1_stride%s' % hparams.discriminator_first_stride)
- net = add_noise(net, 1)
-
- block_id = 2
- # Repeatedly stack
- # discriminator_conv_block_size-1 conv layers with stride 1
- # followed by a stride 2 layer
- # Add (optional) noise at every point
- while net.shape.as_list()[1] > hparams.projection_shape_size:
- num_filters = int(hparams.num_discriminator_filters *
- (hparams.discriminator_filter_factor**(block_id - 1)))
- for conv_id in range(1, hparams.discriminator_conv_block_size):
- net = slim.conv2d(
- net,
- num_filters,
- stride=1,
- scope='conv_%s_%s' % (block_id, conv_id))
- if hparams.discriminator_do_pooling:
- net = slim.conv2d(
- net, num_filters, scope='conv_%s_prepool' % block_id)
- net = slim.avg_pool2d(
- net, kernel_size=[2, 2], stride=2, scope='pool_%s' % block_id)
- else:
- net = slim.conv2d(
- net, num_filters, scope='conv_%s_stride2' % block_id)
- net = add_noise(net, block_id)
- block_id += 1
- net = slim.flatten(net)
- net = slim.fully_connected(
- net,
- 1,
- # Models with BN here generally produce noise
- normalizer_fn=None,
- activation_fn=None,
- scope='fc_logit_out') # Returns logits!
- return net
-
-
-def dcgan_generator(images, output_shape, hparams, scope=None):
- """Transforms the visual style of the input images.
-
- Args:
- images: A `Tensor` of shape [batch_size, height, width, channels].
- output_shape: A list or tuple of 3 elements: the output height, width and
- number of channels.
- hparams: hparams object with generator parameters
- scope: Scope to place generator inside
-
- Returns:
- A `Tensor` of shape [batch_size, height, width, output_channels] which
- represents the result of style transfer.
-
- Raises:
- ValueError: If `output_shape` is not a list or tuple or if it doesn't have
- three elements or if `output_shape` or `images` arent square.
- """
- if not isinstance(output_shape, (tuple, list)):
- raise ValueError('output_shape must be a tuple or list.')
- elif len(output_shape) != 3:
- raise ValueError('output_shape must have three elements.')
-
- if output_shape[0] != output_shape[1]:
- raise ValueError('output_shape must be square')
- if images.shape.as_list()[1] != images.shape.as_list()[2]:
- raise ValueError('images height and width must match.')
-
- outdim = output_shape[0]
- indim = images.shape.as_list()[1]
- num_iterations = int(math.ceil(math.log(float(outdim) / float(indim), 2.0)))
-
- with slim.arg_scope(
- [slim.conv2d, slim.conv2d_transpose],
- kernel_size=[hparams.generator_kernel_size] * 2,
- stride=2):
- with tf.variable_scope(scope or 'generator'):
-
- net = images
-
- # Repeatedly halve # filters until = hparams.decode_filters in last layer
- for i in range(num_iterations):
- num_filters = hparams.num_decoder_filters * 2**(num_iterations - i - 1)
- net = slim.conv2d_transpose(net, num_filters, scope='deconv_%s' % i)
-
- # Crop down to desired size (e.g. 32x32 -> 28x28)
- dif = net.shape.as_list()[1] - outdim
- low = dif / 2
- high = net.shape.as_list()[1] - low
- net = net[:, low:high, low:high, :]
-
- # No batch norm on generator output
- net = slim.conv2d(
- net,
- output_shape[2],
- kernel_size=[1, 1],
- stride=1,
- normalizer_fn=None,
- activation_fn=tf.tanh,
- scope='conv_out')
- return net
-
-
-def dcgan(target_images, latent_vars, hparams, scope='dcgan'):
- """Creates the PixelDA model.
-
- Args:
- target_images: A `Tensor` of shape [batch_size, height, width, 3]
- sampled from the image domain to which we want to transfer.
- latent_vars: dictionary of 'key': Tensor of shape [batch_size, N]
- hparams: The hyperparameter map.
- scope: Surround generator component with this scope
-
- Returns:
- A dictionary of model outputs.
- """
- proj_shape = [
- hparams.projection_shape_size, hparams.projection_shape_size,
- hparams.projection_shape_channels
- ]
- source_volume = project_latent_vars(
- hparams, proj_shape, latent_vars, combine_method='concat')
-
- ###################################################
- # Transfer the source images to the target style. #
- ###################################################
- with tf.variable_scope(scope, 'generator', [target_images]):
- transferred_images = dcgan_generator(
- source_volume,
- output_shape=target_images.shape.as_list()[1:4],
- hparams=hparams)
- assert transferred_images.shape.as_list() == target_images.shape.as_list()
-
- return {'transferred_images': transferred_images}
-
-
-def resnet_generator(images, output_shape, hparams, latent_vars=None):
- """Creates a ResNet-based generator.
-
- Args:
- images: A `Tensor` of shape [batch_size, height, width, num_channels]
- sampled from the image domain from which we want to transfer
- output_shape: A length-3 array indicating the height, width and channels of
- the output.
- hparams: The hyperparameter map.
- latent_vars: dictionary of 'key': Tensor of shape [batch_size, N]
-
- Returns:
- A dictionary of model outputs.
- """
- with tf.variable_scope('generator'):
- if latent_vars:
- noise_channel = project_latent_vars(
- hparams,
- proj_shape=images.shape.as_list()[1:3] + [1],
- latent_vars=latent_vars,
- combine_method='concat')
- images = tf.concat([images, noise_channel], 3)
-
- transferred_images, end_points = resnet_stack(
- images,
- output_shape=output_shape,
- hparams=hparams,
- scope='resnet_stack')
- end_points['transferred_images'] = transferred_images
-
- return end_points
-
-
-def residual_interpretation_block(images, hparams, scope):
- """Learns a residual image which is added to the incoming image.
-
- Args:
- images: A `Tensor` of size [batch_size, height, width, 3]
- hparams: The hyperparameters struct.
- scope: The name of the variable op scope.
-
- Returns:
- The updated images.
- """
- with tf.variable_scope(scope):
- with slim.arg_scope(
- [slim.conv2d],
- normalizer_fn=None,
- kernel_size=[hparams.generator_kernel_size] * 2):
-
- net = images
- for _ in range(hparams.res_int_convs):
- net = slim.conv2d(
- net, hparams.res_int_filters, activation_fn=tf.nn.relu)
- net = slim.conv2d(net, 3, activation_fn=tf.nn.tanh)
-
- # Add the residual
- images += net
-
- # Clip the output
- images = tf.maximum(images, -1.0)
- images = tf.minimum(images, 1.0)
- return images
-
-
-def residual_interpretation_generator(images,
- is_training,
- hparams,
- latent_vars=None):
- """Creates a generator producing purely residual transformations.
-
- A residual generator differs from the resnet generator in that each 'block' of
- the residual generator produces a residual image. Consequently, the 'progress'
- of the model generation process can be directly observed at inference time,
- making it easier to diagnose and understand.
-
- Args:
- images: A `Tensor` of shape [batch_size, height, width, num_channels]
- sampled from the image domain from which we want to transfer. It is
- assumed that the images are centered between -1 and 1.
- is_training: whether or not the model is training.
- hparams: The hyperparameter map.
- latent_vars: dictionary of 'key': Tensor of shape [batch_size, N]
-
- Returns:
- A dictionary of model outputs.
- """
- end_points = {}
-
- with tf.variable_scope('generator'):
- if latent_vars:
- projected_latent = project_latent_vars(
- hparams,
- proj_shape=images.shape.as_list()[1:3] + [images.shape.as_list()[-1]],
- latent_vars=latent_vars,
- combine_method='sum')
- images += projected_latent
- with tf.variable_scope(None, 'residual_style_transfer', [images]):
- for i in range(hparams.res_int_blocks):
- images = residual_interpretation_block(images, hparams,
- 'residual_%d' % i)
- end_points['transferred_images_%d' % i] = images
-
- end_points['transferred_images'] = images
-
- return end_points
-
-
-def simple_generator(source_images, target_images, is_training, hparams,
- latent_vars):
- """Simple generator architecture (stack of convs) for trying small models."""
- end_points = {}
- with tf.variable_scope('generator'):
- feed_source_images = source_images
-
- if latent_vars:
- projected_latent = project_latent_vars(
- hparams,
- proj_shape=source_images.shape.as_list()[1:3] + [1],
- latent_vars=latent_vars,
- combine_method='concat')
- feed_source_images = tf.concat([source_images, projected_latent], 3)
-
- end_points = {}
-
- ###################################################
- # Transfer the source images to the target style. #
- ###################################################
- with slim.arg_scope(
- [slim.conv2d],
- normalizer_fn=slim.batch_norm,
- stride=1,
- kernel_size=[hparams.generator_kernel_size] * 2):
- net = feed_source_images
-
- # N convolutions
- for i in range(1, hparams.simple_num_conv_layers):
- normalizer_fn = None
- if i != 0:
- normalizer_fn = slim.batch_norm
- net = slim.conv2d(
- net,
- hparams.simple_conv_filters,
- normalizer_fn=normalizer_fn,
- activation_fn=tf.nn.relu)
-
- # Project back to right # image channels
- net = slim.conv2d(
- net,
- target_images.shape.as_list()[-1],
- kernel_size=[1, 1],
- stride=1,
- normalizer_fn=None,
- activation_fn=tf.tanh,
- scope='conv_out')
-
- transferred_images = net
- assert transferred_images.shape.as_list() == target_images.shape.as_list()
- end_points['transferred_images'] = transferred_images
-
- return end_points
diff --git a/research/domain_adaptation/pixel_domain_adaptation/pixelda_preprocess.py b/research/domain_adaptation/pixel_domain_adaptation/pixelda_preprocess.py
deleted file mode 100644
index 747c17b18bf007d85e606015da6687a343bf74d2..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/pixel_domain_adaptation/pixelda_preprocess.py
+++ /dev/null
@@ -1,129 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Contains functions for preprocessing the inputs."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-# Dependency imports
-
-import tensorflow as tf
-
-
-def preprocess_classification(image, labels, is_training=False):
- """Preprocesses the image and labels for classification purposes.
-
- Preprocessing includes shifting the images to be 0-centered between -1 and 1.
- This is not only a popular method of preprocessing (inception) but is also
- the mechanism used by DSNs.
-
- Args:
- image: A `Tensor` of size [height, width, 3].
- labels: A dictionary of labels.
- is_training: Whether or not we're training the model.
-
- Returns:
- The preprocessed image and labels.
- """
- # If the image is uint8, this will scale it to 0-1.
- image = tf.image.convert_image_dtype(image, tf.float32)
- image -= 0.5
- image *= 2
-
- return image, labels
-
-
-def preprocess_style_transfer(image,
- labels,
- augment=False,
- size=None,
- is_training=False):
- """Preprocesses the image and labels for style transfer purposes.
-
- Args:
- image: A `Tensor` of size [height, width, 3].
- labels: A dictionary of labels.
- augment: Whether to apply data augmentation to inputs
- size: The height and width to which images should be resized. If left as
- `None`, then no resizing is performed
- is_training: Whether or not we're training the model
-
- Returns:
- The preprocessed image and labels. Scaled to [-1, 1]
- """
- # If the image is uint8, this will scale it to 0-1.
- image = tf.image.convert_image_dtype(image, tf.float32)
- if augment and is_training:
- image = image_augmentation(image)
-
- if size:
- image = resize_image(image, size)
-
- image -= 0.5
- image *= 2
-
- return image, labels
-
-
-def image_augmentation(image):
- """Performs data augmentation by randomly permuting the inputs.
-
- Args:
- image: A float `Tensor` of size [height, width, channels] with values
- in range[0,1].
-
- Returns:
- The mutated batch of images
- """
- # Apply photometric data augmentation (contrast etc.)
- num_channels = image.shape_as_list()[-1]
- if num_channels == 4:
- # Only augment image part
- image, depth = image[:, :, 0:3], image[:, :, 3:4]
- elif num_channels == 1:
- image = tf.image.grayscale_to_rgb(image)
- image = tf.image.random_brightness(image, max_delta=0.1)
- image = tf.image.random_saturation(image, lower=0.5, upper=1.5)
- image = tf.image.random_hue(image, max_delta=0.032)
- image = tf.image.random_contrast(image, lower=0.5, upper=1.5)
- image = tf.clip_by_value(image, 0, 1.0)
- if num_channels == 4:
- image = tf.concat(2, [image, depth])
- elif num_channels == 1:
- image = tf.image.rgb_to_grayscale(image)
- return image
-
-
-def resize_image(image, size=None):
- """Resize image to target size.
-
- Args:
- image: A `Tensor` of size [height, width, 3].
- size: (height, width) to resize image to.
-
- Returns:
- resized image
- """
- if size is None:
- raise ValueError('Must specify size')
-
- if image.shape_as_list()[:2] == size:
- # Don't resize if not necessary
- return image
- image = tf.expand_dims(image, 0)
- image = tf.image.resize_images(image, size)
- image = tf.squeeze(image, 0)
- return image
diff --git a/research/domain_adaptation/pixel_domain_adaptation/pixelda_preprocess_test.py b/research/domain_adaptation/pixel_domain_adaptation/pixelda_preprocess_test.py
deleted file mode 100644
index 73f8c7ff05fc7d2614c419759a02f78ffbcdfec0..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/pixel_domain_adaptation/pixelda_preprocess_test.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Tests for domain_adaptation.pixel_domain_adaptation.pixelda_preprocess."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-# Dependency imports
-
-import tensorflow as tf
-
-from domain_adaptation.pixel_domain_adaptation import pixelda_preprocess
-
-
-class PixelDAPreprocessTest(tf.test.TestCase):
-
- def assert_preprocess_classification_is_centered(self, dtype, is_training):
- tf.set_random_seed(0)
-
- if dtype == tf.uint8:
- image = tf.random_uniform((100, 200, 3), maxval=255, dtype=tf.int64)
- image = tf.cast(image, tf.uint8)
- else:
- image = tf.random_uniform((100, 200, 3), maxval=1.0, dtype=dtype)
-
- labels = {}
- image, labels = pixelda_preprocess.preprocess_classification(
- image, labels, is_training=is_training)
-
- with self.test_session() as sess:
- np_image = sess.run(image)
-
- self.assertTrue(np_image.min() <= -0.95)
- self.assertTrue(np_image.min() >= -1.0)
- self.assertTrue(np_image.max() >= 0.95)
- self.assertTrue(np_image.max() <= 1.0)
-
- def testPreprocessClassificationZeroCentersUint8DuringTrain(self):
- self.assert_preprocess_classification_is_centered(
- tf.uint8, is_training=True)
-
- def testPreprocessClassificationZeroCentersUint8DuringTest(self):
- self.assert_preprocess_classification_is_centered(
- tf.uint8, is_training=False)
-
- def testPreprocessClassificationZeroCentersFloatDuringTrain(self):
- self.assert_preprocess_classification_is_centered(
- tf.float32, is_training=True)
-
- def testPreprocessClassificationZeroCentersFloatDuringTest(self):
- self.assert_preprocess_classification_is_centered(
- tf.float32, is_training=False)
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/domain_adaptation/pixel_domain_adaptation/pixelda_task_towers.py b/research/domain_adaptation/pixel_domain_adaptation/pixelda_task_towers.py
deleted file mode 100644
index 1cb42e2d890a7759318cf0981640c0dd1645461e..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/pixel_domain_adaptation/pixelda_task_towers.py
+++ /dev/null
@@ -1,317 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Task towers for PixelDA model."""
-import tensorflow as tf
-
-slim = tf.contrib.slim
-
-
-def add_task_specific_model(images,
- hparams,
- num_classes=10,
- is_training=False,
- reuse_private=False,
- private_scope=None,
- reuse_shared=False,
- shared_scope=None):
- """Create a classifier for the given images.
-
- The classifier is composed of a few 'private' layers followed by a few
- 'shared' layers. This lets us account for different image 'style', while
- sharing the last few layers as 'content' layers.
-
- Args:
- images: A `Tensor` of size [batch_size, height, width, 3].
- hparams: model hparams
- num_classes: The number of output classes.
- is_training: whether model is training
- reuse_private: Whether or not to reuse the private weights, which are the
- first few layers in the classifier
- private_scope: The name of the variable_scope for the private (unshared)
- components of the classifier.
- reuse_shared: Whether or not to reuse the shared weights, which are the last
- few layers in the classifier
- shared_scope: The name of the variable_scope for the shared components of
- the classifier.
-
- Returns:
- The logits, a `Tensor` of shape [batch_size, num_classes].
-
- Raises:
- ValueError: If hparams.task_classifier is an unknown value
- """
-
- model = hparams.task_tower
- # Make sure the classifier name shows up in graph
- shared_scope = shared_scope or (model + '_shared')
- kwargs = {
- 'num_classes': num_classes,
- 'is_training': is_training,
- 'reuse_private': reuse_private,
- 'reuse_shared': reuse_shared,
- }
-
- if private_scope:
- kwargs['private_scope'] = private_scope
- if shared_scope:
- kwargs['shared_scope'] = shared_scope
-
- quaternion_pred = None
- with slim.arg_scope(
- [slim.conv2d, slim.fully_connected],
- activation_fn=tf.nn.relu,
- weights_regularizer=tf.contrib.layers.l2_regularizer(
- hparams.weight_decay_task_classifier)):
- with slim.arg_scope([slim.conv2d], padding='SAME'):
- if model == 'doubling_pose_estimator':
- logits, quaternion_pred = doubling_cnn_class_and_quaternion(
- images, num_private_layers=hparams.num_private_layers, **kwargs)
- elif model == 'mnist':
- logits, _ = mnist_classifier(images, **kwargs)
- elif model == 'svhn':
- logits, _ = svhn_classifier(images, **kwargs)
- elif model == 'gtsrb':
- logits, _ = gtsrb_classifier(images, **kwargs)
- elif model == 'pose_mini':
- logits, quaternion_pred = pose_mini_tower(images, **kwargs)
- else:
- raise ValueError('Unknown task classifier %s' % model)
-
- return logits, quaternion_pred
-
-
-#####################################
-# Classifiers used in the DSN paper #
-#####################################
-
-
-def mnist_classifier(images,
- is_training=False,
- num_classes=10,
- reuse_private=False,
- private_scope='mnist',
- reuse_shared=False,
- shared_scope='task_model'):
- """Creates the convolutional MNIST model from the gradient reversal paper.
-
- Note that since the output is a set of 'logits', the values fall in the
- interval of (-infinity, infinity). Consequently, to convert the outputs to a
- probability distribution over the characters, one will need to convert them
- using the softmax function:
- logits, endpoints = conv_mnist(images, is_training=False)
- predictions = tf.nn.softmax(logits)
-
- Args:
- images: the MNIST digits, a tensor of size [batch_size, 28, 28, 1].
- is_training: specifies whether or not we're currently training the model.
- This variable will determine the behaviour of the dropout layer.
- num_classes: the number of output classes to use.
-
- Returns:
- the output logits, a tensor of size [batch_size, num_classes].
- a dictionary with key/values the layer names and tensors.
- """
-
- net = {}
-
- with tf.variable_scope(private_scope, reuse=reuse_private):
- net['conv1'] = slim.conv2d(images, 32, [5, 5], scope='conv1')
- net['pool1'] = slim.max_pool2d(net['conv1'], [2, 2], 2, scope='pool1')
-
- with tf.variable_scope(shared_scope, reuse=reuse_shared):
- net['conv2'] = slim.conv2d(net['pool1'], 48, [5, 5], scope='conv2')
- net['pool2'] = slim.max_pool2d(net['conv2'], [2, 2], 2, scope='pool2')
- net['fc3'] = slim.fully_connected(
- slim.flatten(net['pool2']), 100, scope='fc3')
- net['fc4'] = slim.fully_connected(
- slim.flatten(net['fc3']), 100, scope='fc4')
- logits = slim.fully_connected(
- net['fc4'], num_classes, activation_fn=None, scope='fc5')
- return logits, net
-
-
-def svhn_classifier(images,
- is_training=False,
- num_classes=10,
- reuse_private=False,
- private_scope=None,
- reuse_shared=False,
- shared_scope='task_model'):
- """Creates the convolutional SVHN model from the gradient reversal paper.
-
- Note that since the output is a set of 'logits', the values fall in the
- interval of (-infinity, infinity). Consequently, to convert the outputs to a
- probability distribution over the characters, one will need to convert them
- using the softmax function:
- logits = mnist.Mnist(images, is_training=False)
- predictions = tf.nn.softmax(logits)
-
- Args:
- images: the SVHN digits, a tensor of size [batch_size, 40, 40, 3].
- is_training: specifies whether or not we're currently training the model.
- This variable will determine the behaviour of the dropout layer.
- num_classes: the number of output classes to use.
-
- Returns:
- the output logits, a tensor of size [batch_size, num_classes].
- a dictionary with key/values the layer names and tensors.
- """
-
- net = {}
-
- with tf.variable_scope(private_scope, reuse=reuse_private):
- net['conv1'] = slim.conv2d(images, 64, [5, 5], scope='conv1')
- net['pool1'] = slim.max_pool2d(net['conv1'], [3, 3], 2, scope='pool1')
-
- with tf.variable_scope(shared_scope, reuse=reuse_shared):
- net['conv2'] = slim.conv2d(net['pool1'], 64, [5, 5], scope='conv2')
- net['pool2'] = slim.max_pool2d(net['conv2'], [3, 3], 2, scope='pool2')
- net['conv3'] = slim.conv2d(net['pool2'], 128, [5, 5], scope='conv3')
-
- net['fc3'] = slim.fully_connected(
- slim.flatten(net['conv3']), 3072, scope='fc3')
- net['fc4'] = slim.fully_connected(
- slim.flatten(net['fc3']), 2048, scope='fc4')
-
- logits = slim.fully_connected(
- net['fc4'], num_classes, activation_fn=None, scope='fc5')
-
- return logits, net
-
-
-def gtsrb_classifier(images,
- is_training=False,
- num_classes=43,
- reuse_private=False,
- private_scope='gtsrb',
- reuse_shared=False,
- shared_scope='task_model'):
- """Creates the convolutional GTSRB model from the gradient reversal paper.
-
- Note that since the output is a set of 'logits', the values fall in the
- interval of (-infinity, infinity). Consequently, to convert the outputs to a
- probability distribution over the characters, one will need to convert them
- using the softmax function:
- logits = mnist.Mnist(images, is_training=False)
- predictions = tf.nn.softmax(logits)
-
- Args:
- images: the SVHN digits, a tensor of size [batch_size, 40, 40, 3].
- is_training: specifies whether or not we're currently training the model.
- This variable will determine the behaviour of the dropout layer.
- num_classes: the number of output classes to use.
- reuse_private: Whether or not to reuse the private components of the model.
- private_scope: The name of the private scope.
- reuse_shared: Whether or not to reuse the shared components of the model.
- shared_scope: The name of the shared scope.
-
- Returns:
- the output logits, a tensor of size [batch_size, num_classes].
- a dictionary with key/values the layer names and tensors.
- """
-
- net = {}
-
- with tf.variable_scope(private_scope, reuse=reuse_private):
- net['conv1'] = slim.conv2d(images, 96, [5, 5], scope='conv1')
- net['pool1'] = slim.max_pool2d(net['conv1'], [2, 2], 2, scope='pool1')
- with tf.variable_scope(shared_scope, reuse=reuse_shared):
- net['conv2'] = slim.conv2d(net['pool1'], 144, [3, 3], scope='conv2')
- net['pool2'] = slim.max_pool2d(net['conv2'], [2, 2], 2, scope='pool2')
- net['conv3'] = slim.conv2d(net['pool2'], 256, [5, 5], scope='conv3')
- net['pool3'] = slim.max_pool2d(net['conv3'], [2, 2], 2, scope='pool3')
-
- net['fc3'] = slim.fully_connected(
- slim.flatten(net['pool3']), 512, scope='fc3')
- logits = slim.fully_connected(
- net['fc3'], num_classes, activation_fn=None, scope='fc4')
-
- return logits, net
-
-
-#########################
-# pose_mini task towers #
-#########################
-
-
-def pose_mini_tower(images,
- num_classes=11,
- is_training=False,
- reuse_private=False,
- private_scope='pose_mini',
- reuse_shared=False,
- shared_scope='task_model'):
- """Task tower for the pose_mini dataset."""
-
- with tf.variable_scope(private_scope, reuse=reuse_private):
- net = slim.conv2d(images, 32, [5, 5], scope='conv1')
- net = slim.max_pool2d(net, [2, 2], stride=2, scope='pool1')
- with tf.variable_scope(shared_scope, reuse=reuse_shared):
- net = slim.conv2d(net, 64, [5, 5], scope='conv2')
- net = slim.max_pool2d(net, [2, 2], stride=2, scope='pool2')
- net = slim.flatten(net)
-
- net = slim.fully_connected(net, 128, scope='fc3')
- net = slim.dropout(net, 0.5, is_training=is_training, scope='dropout')
- with tf.variable_scope('quaternion_prediction'):
- quaternion_pred = slim.fully_connected(
- net, 4, activation_fn=tf.tanh, scope='fc_q')
- quaternion_pred = tf.nn.l2_normalize(quaternion_pred, 1)
-
- logits = slim.fully_connected(
- net, num_classes, activation_fn=None, scope='fc4')
-
- return logits, quaternion_pred
-
-
-def doubling_cnn_class_and_quaternion(images,
- num_private_layers=1,
- num_classes=10,
- is_training=False,
- reuse_private=False,
- private_scope='doubling_cnn',
- reuse_shared=False,
- shared_scope='task_model'):
- """Alternate conv, pool while doubling filter count."""
- net = images
- depth = 32
- layer_id = 1
-
- with tf.variable_scope(private_scope, reuse=reuse_private):
- while num_private_layers > 0 and net.shape.as_list()[1] > 5:
- net = slim.conv2d(net, depth, [3, 3], scope='conv%s' % layer_id)
- net = slim.max_pool2d(net, [2, 2], stride=2, scope='pool%s' % layer_id)
- depth *= 2
- layer_id += 1
- num_private_layers -= 1
-
- with tf.variable_scope(shared_scope, reuse=reuse_shared):
- while net.shape.as_list()[1] > 5:
- net = slim.conv2d(net, depth, [3, 3], scope='conv%s' % layer_id)
- net = slim.max_pool2d(net, [2, 2], stride=2, scope='pool%s' % layer_id)
- depth *= 2
- layer_id += 1
-
- net = slim.flatten(net)
- net = slim.fully_connected(net, 100, scope='fc1')
- net = slim.dropout(net, 0.5, is_training=is_training, scope='dropout')
- quaternion_pred = slim.fully_connected(
- net, 4, activation_fn=tf.tanh, scope='fc_q')
- quaternion_pred = tf.nn.l2_normalize(quaternion_pred, 1)
-
- logits = slim.fully_connected(
- net, num_classes, activation_fn=None, scope='fc_logits')
-
- return logits, quaternion_pred
diff --git a/research/domain_adaptation/pixel_domain_adaptation/pixelda_train.py b/research/domain_adaptation/pixel_domain_adaptation/pixelda_train.py
deleted file mode 100644
index 4ca072cceafa48769623381b8e564fe650f2a514..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/pixel_domain_adaptation/pixelda_train.py
+++ /dev/null
@@ -1,409 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-r"""Trains the PixelDA model."""
-
-from functools import partial
-import os
-
-# Dependency imports
-
-import tensorflow as tf
-
-from domain_adaptation.datasets import dataset_factory
-from domain_adaptation.pixel_domain_adaptation import pixelda_losses
-from domain_adaptation.pixel_domain_adaptation import pixelda_model
-from domain_adaptation.pixel_domain_adaptation import pixelda_preprocess
-from domain_adaptation.pixel_domain_adaptation import pixelda_utils
-from domain_adaptation.pixel_domain_adaptation.hparams import create_hparams
-
-slim = tf.contrib.slim
-
-flags = tf.app.flags
-FLAGS = flags.FLAGS
-
-flags.DEFINE_string('master', '', 'BNS name of the TensorFlow master to use.')
-
-flags.DEFINE_integer(
- 'ps_tasks', 0,
- 'The number of parameter servers. If the value is 0, then the parameters '
- 'are handled locally by the worker.')
-
-flags.DEFINE_integer(
- 'task', 0,
- 'The Task ID. This value is used when training with multiple workers to '
- 'identify each worker.')
-
-flags.DEFINE_string('train_log_dir', '/tmp/pixelda/',
- 'Directory where to write event logs.')
-
-flags.DEFINE_integer(
- 'save_summaries_steps', 500,
- 'The frequency with which summaries are saved, in seconds.')
-
-flags.DEFINE_integer('save_interval_secs', 300,
- 'The frequency with which the model is saved, in seconds.')
-
-flags.DEFINE_boolean('summarize_gradients', False,
- 'Whether to summarize model gradients')
-
-flags.DEFINE_integer(
- 'print_loss_steps', 100,
- 'The frequency with which the losses are printed, in steps.')
-
-flags.DEFINE_string('source_dataset', 'mnist', 'The name of the source dataset.'
- ' If hparams="arch=dcgan", this flag is ignored.')
-
-flags.DEFINE_string('target_dataset', 'mnist_m',
- 'The name of the target dataset.')
-
-flags.DEFINE_string('source_split_name', 'train',
- 'Name of the train split for the source.')
-
-flags.DEFINE_string('target_split_name', 'train',
- 'Name of the train split for the target.')
-
-flags.DEFINE_string('dataset_dir', '',
- 'The directory where the datasets can be found.')
-
-flags.DEFINE_integer(
- 'num_readers', 4,
- 'The number of parallel readers that read data from the dataset.')
-
-flags.DEFINE_integer('num_preprocessing_threads', 4,
- 'The number of threads used to create the batches.')
-
-# HParams
-
-flags.DEFINE_string('hparams', '', 'Comma separated hyperparameter values')
-
-
-def _get_vars_and_update_ops(hparams, scope):
- """Returns the variables and update ops for a particular variable scope.
-
- Args:
- hparams: The hyperparameters struct.
- scope: The variable scope.
-
- Returns:
- A tuple consisting of trainable variables and update ops.
- """
- is_trainable = lambda x: x in tf.trainable_variables()
- var_list = filter(is_trainable, slim.get_model_variables(scope))
- global_step = slim.get_or_create_global_step()
-
- update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS, scope)
-
- tf.logging.info('All variables for scope: %s',
- slim.get_model_variables(scope))
- tf.logging.info('Trainable variables for scope: %s', var_list)
-
- return var_list, update_ops
-
-
-def _train(discriminator_train_op,
- generator_train_op,
- logdir,
- master='',
- is_chief=True,
- scaffold=None,
- hooks=None,
- chief_only_hooks=None,
- save_checkpoint_secs=600,
- save_summaries_steps=100,
- hparams=None):
- """Runs the training loop.
-
- Args:
- discriminator_train_op: A `Tensor` that, when executed, will apply the
- gradients and return the loss value for the discriminator.
- generator_train_op: A `Tensor` that, when executed, will apply the
- gradients and return the loss value for the generator.
- logdir: The directory where the graph and checkpoints are saved.
- master: The URL of the master.
- is_chief: Specifies whether or not the training is being run by the primary
- replica during replica training.
- scaffold: An tf.train.Scaffold instance.
- hooks: List of `tf.train.SessionRunHook` callbacks which are run inside the
- training loop.
- chief_only_hooks: List of `tf.train.SessionRunHook` instances which are run
- inside the training loop for the chief trainer only.
- save_checkpoint_secs: The frequency, in seconds, that a checkpoint is saved
- using a default checkpoint saver. If `save_checkpoint_secs` is set to
- `None`, then the default checkpoint saver isn't used.
- save_summaries_steps: The frequency, in number of global steps, that the
- summaries are written to disk using a default summary saver. If
- `save_summaries_steps` is set to `None`, then the default summary saver
- isn't used.
- hparams: The hparams struct.
-
- Returns:
- the value of the loss function after training.
-
- Raises:
- ValueError: if `logdir` is `None` and either `save_checkpoint_secs` or
- `save_summaries_steps` are `None.
- """
- global_step = slim.get_or_create_global_step()
-
- scaffold = scaffold or tf.train.Scaffold()
-
- hooks = hooks or []
-
- if is_chief:
- session_creator = tf.train.ChiefSessionCreator(
- scaffold=scaffold, checkpoint_dir=logdir, master=master)
-
- if chief_only_hooks:
- hooks.extend(chief_only_hooks)
- hooks.append(tf.train.StepCounterHook(output_dir=logdir))
-
- if save_summaries_steps:
- if logdir is None:
- raise ValueError(
- 'logdir cannot be None when save_summaries_steps is None')
- hooks.append(
- tf.train.SummarySaverHook(
- scaffold=scaffold,
- save_steps=save_summaries_steps,
- output_dir=logdir))
-
- if save_checkpoint_secs:
- if logdir is None:
- raise ValueError(
- 'logdir cannot be None when save_checkpoint_secs is None')
- hooks.append(
- tf.train.CheckpointSaverHook(
- logdir, save_secs=save_checkpoint_secs, scaffold=scaffold))
- else:
- session_creator = tf.train.WorkerSessionCreator(
- scaffold=scaffold, master=master)
-
- with tf.train.MonitoredSession(
- session_creator=session_creator, hooks=hooks) as session:
- loss = None
- while not session.should_stop():
- # Run the domain classifier op X times.
- for _ in range(hparams.discriminator_steps):
- if session.should_stop():
- return loss
- loss, np_global_step = session.run(
- [discriminator_train_op, global_step])
- if np_global_step % FLAGS.print_loss_steps == 0:
- tf.logging.info('Step %d: Discriminator Loss = %.2f', np_global_step,
- loss)
-
- # Run the generator op X times.
- for _ in range(hparams.generator_steps):
- if session.should_stop():
- return loss
- loss, np_global_step = session.run([generator_train_op, global_step])
- if np_global_step % FLAGS.print_loss_steps == 0:
- tf.logging.info('Step %d: Generator Loss = %.2f', np_global_step,
- loss)
- return loss
-
-
-def run_training(run_dir, checkpoint_dir, hparams):
- """Runs the training loop.
-
- Args:
- run_dir: The directory where training specific logs are placed
- checkpoint_dir: The directory where the checkpoints and log files are
- stored.
- hparams: The hyperparameters struct.
-
- Raises:
- ValueError: if hparams.arch is not recognized.
- """
- for path in [run_dir, checkpoint_dir]:
- if not tf.gfile.Exists(path):
- tf.gfile.MakeDirs(path)
-
- # Serialize hparams to log dir
- hparams_filename = os.path.join(checkpoint_dir, 'hparams.json')
- with tf.gfile.FastGFile(hparams_filename, 'w') as f:
- f.write(hparams.to_json())
-
- with tf.Graph().as_default():
- with tf.device(tf.train.replica_device_setter(FLAGS.ps_tasks)):
- global_step = slim.get_or_create_global_step()
-
- #########################
- # Preprocess the inputs #
- #########################
- target_dataset = dataset_factory.get_dataset(
- FLAGS.target_dataset,
- split_name='train',
- dataset_dir=FLAGS.dataset_dir)
- target_images, _ = dataset_factory.provide_batch(
- FLAGS.target_dataset, 'train', FLAGS.dataset_dir, FLAGS.num_readers,
- hparams.batch_size, FLAGS.num_preprocessing_threads)
- num_target_classes = target_dataset.num_classes
-
- if hparams.arch not in ['dcgan']:
- source_dataset = dataset_factory.get_dataset(
- FLAGS.source_dataset,
- split_name='train',
- dataset_dir=FLAGS.dataset_dir)
- num_source_classes = source_dataset.num_classes
- source_images, source_labels = dataset_factory.provide_batch(
- FLAGS.source_dataset, 'train', FLAGS.dataset_dir, FLAGS.num_readers,
- hparams.batch_size, FLAGS.num_preprocessing_threads)
- # Data provider provides 1 hot labels, but we expect categorical.
- source_labels['class'] = tf.argmax(source_labels['classes'], 1)
- del source_labels['classes']
- if num_source_classes != num_target_classes:
- raise ValueError(
- 'Source and Target datasets must have same number of classes. '
- 'Are %d and %d' % (num_source_classes, num_target_classes))
- else:
- source_images = None
- source_labels = None
-
- ####################
- # Define the model #
- ####################
- end_points = pixelda_model.create_model(
- hparams,
- target_images,
- source_images=source_images,
- source_labels=source_labels,
- is_training=True,
- num_classes=num_target_classes)
-
- #################################
- # Get the variables to optimize #
- #################################
- generator_vars, generator_update_ops = _get_vars_and_update_ops(
- hparams, 'generator')
- discriminator_vars, discriminator_update_ops = _get_vars_and_update_ops(
- hparams, 'discriminator')
-
- ########################
- # Configure the losses #
- ########################
- generator_loss = pixelda_losses.g_step_loss(
- source_images,
- source_labels,
- end_points,
- hparams,
- num_classes=num_target_classes)
- discriminator_loss = pixelda_losses.d_step_loss(
- end_points, source_labels, num_target_classes, hparams)
-
- ###########################
- # Create the training ops #
- ###########################
- learning_rate = hparams.learning_rate
- if hparams.lr_decay_steps:
- learning_rate = tf.train.exponential_decay(
- learning_rate,
- slim.get_or_create_global_step(),
- decay_steps=hparams.lr_decay_steps,
- decay_rate=hparams.lr_decay_rate,
- staircase=True)
- tf.summary.scalar('Learning_rate', learning_rate)
-
-
- if hparams.discriminator_steps == 0:
- discriminator_train_op = tf.no_op()
- else:
- discriminator_optimizer = tf.train.AdamOptimizer(
- learning_rate, beta1=hparams.adam_beta1)
-
- discriminator_train_op = slim.learning.create_train_op(
- discriminator_loss,
- discriminator_optimizer,
- update_ops=discriminator_update_ops,
- variables_to_train=discriminator_vars,
- clip_gradient_norm=hparams.clip_gradient_norm,
- summarize_gradients=FLAGS.summarize_gradients)
-
- if hparams.generator_steps == 0:
- generator_train_op = tf.no_op()
- else:
- generator_optimizer = tf.train.AdamOptimizer(
- learning_rate, beta1=hparams.adam_beta1)
- generator_train_op = slim.learning.create_train_op(
- generator_loss,
- generator_optimizer,
- update_ops=generator_update_ops,
- variables_to_train=generator_vars,
- clip_gradient_norm=hparams.clip_gradient_norm,
- summarize_gradients=FLAGS.summarize_gradients)
-
- #############
- # Summaries #
- #############
- pixelda_utils.summarize_model(end_points)
- pixelda_utils.summarize_transferred_grid(
- end_points['transferred_images'], source_images, name='Transferred')
- if 'source_images_recon' in end_points:
- pixelda_utils.summarize_transferred_grid(
- end_points['source_images_recon'],
- source_images,
- name='Source Reconstruction')
- pixelda_utils.summaries_color_distributions(end_points['transferred_images'],
- 'Transferred')
- pixelda_utils.summaries_color_distributions(target_images, 'Target')
-
- if source_images is not None:
- pixelda_utils.summarize_transferred(source_images,
- end_points['transferred_images'])
- pixelda_utils.summaries_color_distributions(source_images, 'Source')
- pixelda_utils.summaries_color_distributions(
- tf.abs(source_images - end_points['transferred_images']),
- 'Abs(Source_minus_Transferred)')
-
- number_of_steps = None
- if hparams.num_training_examples:
- # Want to control by amount of data seen, not # steps
- number_of_steps = hparams.num_training_examples / hparams.batch_size
-
- hooks = [tf.train.StepCounterHook(),]
-
- chief_only_hooks = [
- tf.train.CheckpointSaverHook(
- saver=tf.train.Saver(),
- checkpoint_dir=run_dir,
- save_secs=FLAGS.save_interval_secs)
- ]
-
- if number_of_steps:
- hooks.append(tf.train.StopAtStepHook(last_step=number_of_steps))
-
- _train(
- discriminator_train_op,
- generator_train_op,
- logdir=run_dir,
- master=FLAGS.master,
- is_chief=FLAGS.task == 0,
- hooks=hooks,
- chief_only_hooks=chief_only_hooks,
- save_checkpoint_secs=None,
- save_summaries_steps=FLAGS.save_summaries_steps,
- hparams=hparams)
-
-def main(_):
- tf.logging.set_verbosity(tf.logging.INFO)
- hparams = create_hparams(FLAGS.hparams)
- run_training(
- run_dir=FLAGS.train_log_dir,
- checkpoint_dir=FLAGS.train_log_dir,
- hparams=hparams)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/domain_adaptation/pixel_domain_adaptation/pixelda_utils.py b/research/domain_adaptation/pixel_domain_adaptation/pixelda_utils.py
deleted file mode 100644
index 28e8006f267f9bf7f13c3dff78625cc4cbd00185..0000000000000000000000000000000000000000
--- a/research/domain_adaptation/pixel_domain_adaptation/pixelda_utils.py
+++ /dev/null
@@ -1,195 +0,0 @@
-# Copyright 2017 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Utilities for PixelDA model."""
-import math
-
-# Dependency imports
-
-import tensorflow as tf
-
-slim = tf.contrib.slim
-
-flags = tf.app.flags
-FLAGS = flags.FLAGS
-
-
-def remove_depth(images):
- """Takes a batch of images and remove depth channel if present."""
- if images.shape.as_list()[-1] == 4:
- return images[:, :, :, 0:3]
- return images
-
-
-def image_grid(images, max_grid_size=4):
- """Given images and N, return first N^2 images as an NxN image grid.
-
- Args:
- images: a `Tensor` of size [batch_size, height, width, channels]
- max_grid_size: Maximum image grid height/width
-
- Returns:
- Single image batch, of dim [1, h*n, w*n, c]
- """
- images = remove_depth(images)
- batch_size = images.shape.as_list()[0]
- grid_size = min(int(math.sqrt(batch_size)), max_grid_size)
- assert images.shape.as_list()[0] >= grid_size * grid_size
-
- # If we have a depth channel
- if images.shape.as_list()[-1] == 4:
- images = images[:grid_size * grid_size, :, :, 0:3]
- depth = tf.image.grayscale_to_rgb(images[:grid_size * grid_size, :, :, 3:4])
-
- images = tf.reshape(images, [-1, images.shape.as_list()[2], 3])
- split = tf.split(0, grid_size, images)
- depth = tf.reshape(depth, [-1, images.shape.as_list()[2], 3])
- depth_split = tf.split(0, grid_size, depth)
- grid = tf.concat(split + depth_split, 1)
- return tf.expand_dims(grid, 0)
- else:
- images = images[:grid_size * grid_size, :, :, :]
- images = tf.reshape(
- images, [-1, images.shape.as_list()[2],
- images.shape.as_list()[3]])
- split = tf.split(images, grid_size, 0)
- grid = tf.concat(split, 1)
- return tf.expand_dims(grid, 0)
-
-
-def source_and_output_image_grid(output_images,
- source_images=None,
- max_grid_size=4):
- """Create NxN image grid for output, concatenate source grid if given.
-
- Makes grid out of output_images and, if provided, source_images, and
- concatenates them.
-
- Args:
- output_images: [batch_size, h, w, c] tensor of images
- source_images: optional[batch_size, h, w, c] tensor of images
- max_grid_size: Image grid height/width
-
- Returns:
- Single image batch, of dim [1, h*n, w*n, c]
-
-
- """
- output_grid = image_grid(output_images, max_grid_size=max_grid_size)
- if source_images is not None:
- source_grid = image_grid(source_images, max_grid_size=max_grid_size)
- # Make sure they have the same # of channels before concat
- # Assumes either 1 or 3 channels
- if output_grid.shape.as_list()[-1] != source_grid.shape.as_list()[-1]:
- if output_grid.shape.as_list()[-1] == 1:
- output_grid = tf.tile(output_grid, [1, 1, 1, 3])
- if source_grid.shape.as_list()[-1] == 1:
- source_grid = tf.tile(source_grid, [1, 1, 1, 3])
- output_grid = tf.concat([output_grid, source_grid], 1)
- return output_grid
-
-
-def summarize_model(end_points):
- """Summarizes the given model via its end_points.
-
- Args:
- end_points: A dictionary of end_point names to `Tensor`.
- """
- tf.summary.histogram('domain_logits_transferred',
- tf.sigmoid(end_points['transferred_domain_logits']))
-
- tf.summary.histogram('domain_logits_target',
- tf.sigmoid(end_points['target_domain_logits']))
-
-
-def summarize_transferred_grid(transferred_images,
- source_images=None,
- name='Transferred'):
- """Produces a visual grid summarization of the image transferrence.
-
- Args:
- transferred_images: A `Tensor` of size [batch_size, height, width, c].
- source_images: A `Tensor` of size [batch_size, height, width, c].
- name: Name to use in summary name
- """
- if source_images is not None:
- grid = source_and_output_image_grid(transferred_images, source_images)
- else:
- grid = image_grid(transferred_images)
- tf.summary.image('%s_Images_Grid' % name, grid, max_outputs=1)
-
-
-def summarize_transferred(source_images,
- transferred_images,
- max_images=20,
- name='Transferred'):
- """Produces a visual summary of the image transferrence.
-
- This summary displays the source image, transferred image, and a grayscale
- difference image which highlights the differences between input and output.
-
- Args:
- source_images: A `Tensor` of size [batch_size, height, width, channels].
- transferred_images: A `Tensor` of size [batch_size, height, width, channels]
- max_images: The number of images to show.
- name: Name to use in summary name
-
- Raises:
- ValueError: If number of channels in source and target are incompatible
- """
- source_channels = source_images.shape.as_list()[-1]
- transferred_channels = transferred_images.shape.as_list()[-1]
- if source_channels < transferred_channels:
- if source_channels != 1:
- raise ValueError(
- 'Source must be 1 channel or same # of channels as target')
- source_images = tf.tile(source_images, [1, 1, 1, transferred_channels])
- if transferred_channels < source_channels:
- if transferred_channels != 1:
- raise ValueError(
- 'Target must be 1 channel or same # of channels as source')
- transferred_images = tf.tile(transferred_images, [1, 1, 1, source_channels])
- diffs = tf.abs(source_images - transferred_images)
- diffs = tf.reduce_max(diffs, reduction_indices=[3], keep_dims=True)
- diffs = tf.tile(diffs, [1, 1, 1, max(source_channels, transferred_channels)])
-
- transition_images = tf.concat([
- source_images,
- transferred_images,
- diffs,
- ], 2)
-
- tf.summary.image(
- '%s_difference' % name, transition_images, max_outputs=max_images)
-
-
-def summaries_color_distributions(images, name):
- """Produces a histogram of the color distributions of the images.
-
- Args:
- images: A `Tensor` of size [batch_size, height, width, 3].
- name: The name of the images being summarized.
- """
- tf.summary.histogram('color_values/%s' % name, images)
-
-
-def summarize_images(images, name):
- """Produces a visual summary of the given images.
-
- Args:
- images: A `Tensor` of size [batch_size, height, width, 3].
- name: The name of the images being summarized.
- """
- grid = image_grid(images)
- tf.summary.image('%s_Images' % name, grid, max_outputs=1)
diff --git a/research/feelvos/CONTRIBUTING.md b/research/feelvos/CONTRIBUTING.md
deleted file mode 100644
index 939e5341e74dc2371c8b47f0e27b50581bed5f63..0000000000000000000000000000000000000000
--- a/research/feelvos/CONTRIBUTING.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# How to Contribute
-
-We'd love to accept your patches and contributions to this project. There are
-just a few small guidelines you need to follow.
-
-## Contributor License Agreement
-
-Contributions to this project must be accompanied by a Contributor License
-Agreement. You (or your employer) retain the copyright to your contribution;
-this simply gives us permission to use and redistribute your contributions as
-part of the project. Head over to to see
-your current agreements on file or to sign a new one.
-
-You generally only need to submit a CLA once, so if you've already submitted one
-(even if it was for a different project), you probably don't need to do it
-again.
-
-## Code reviews
-
-All submissions, including submissions by project members, require review. We
-use GitHub pull requests for this purpose. Consult
-[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
-information on using pull requests.
-
-## Community Guidelines
-
-This project follows [Google's Open Source Community
-Guidelines](https://opensource.google.com/conduct/).
diff --git a/research/feelvos/LICENSE b/research/feelvos/LICENSE
deleted file mode 100644
index d645695673349e3947e8e5ae42332d0ac3164cd7..0000000000000000000000000000000000000000
--- a/research/feelvos/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/research/feelvos/README.md b/research/feelvos/README.md
deleted file mode 100644
index 69017c8b19fc1427c47cbdfbdce408ffa92ec32c..0000000000000000000000000000000000000000
--- a/research/feelvos/README.md
+++ /dev/null
@@ -1,102 +0,0 @@
-
-
-
-
-# FEELVOS: Fast End-to-End Embedding Learning for Video Object Segmentation
-
-FEELVOS is a fast model for video object segmentation which does not rely on fine-tuning on the
-first frame.
-
-For details, please refer to our paper. If you find the code useful, please
-also consider citing it.
-
-* FEELVOS:
-
-```
-@inproceedings{feelvos2019,
- title={FEELVOS: Fast End-to-End Embedding Learning for Video Object Segmentation},
- author={Paul Voigtlaender and Yuning Chai and Florian Schroff and Hartwig Adam and Bastian Leibe and Liang-Chieh Chen},
- booktitle={CVPR},
- year={2019}
-}
-```
-
-## Dependencies
-
-FEELVOS requires a good GPU with around 12 GB of memory and depends on the following libraries
-
-* TensorFlow
-* Pillow
-* Numpy
-* Scipy
-* Scikit Learn Image
-* tf Slim (which is included in the "tensorflow/models/research/" checkout)
-* DeepLab (which is included in the "tensorflow/models/research/" checkout)
-* correlation_cost (optional, see below)
-
-For detailed steps to install Tensorflow, follow the [Tensorflow installation
-instructions](https://www.tensorflow.org/install/). A typical user can install
-Tensorflow using the following command:
-
-```bash
-pip install tensorflow-gpu
-```
-
-The remaining libraries can also be installed with pip using:
-
-```bash
-pip install pillow scipy scikit-image
-```
-
-## Dependency on correlation_cost
-
-For fast cross-correlation, we use correlation cost as an external dependency. By default FEELVOS
-will use a slow and memory hungry fallback implementation without correlation_cost. If you care for
-performance, you should set up correlation_cost by following the instructions in
-correlation_cost/README and afterwards setting ```USE_CORRELATION_COST = True``` in
-utils/embedding_utils.py.
-
-## Pre-trained Models
-
-We provide 2 pre-trained FEELVOS models, both are based on Xception-65:
-
-* [Trained on DAVIS 2017](http://download.tensorflow.org/models/feelvos_davis17_trained.tar.gz)
-* [Trained on DAVIS 2017 and YouTube-VOS](http://download.tensorflow.org/models/feelvos_davis17_and_youtubevos_trained.tar.gz)
-
-Additionally, we provide a [DeepLab checkpoint for Xception-65 pre-trained on ImageNet and COCO](http://download.tensorflow.org/models/xception_65_coco_pretrained_2018_10_02.tar.gz),
-which can be used as an initialization for training FEELVOS.
-
-## Pre-computed Segmentation Masks
-
-We provide [pre-computed segmentation masks](http://download.tensorflow.org/models/feelvos_precomputed_masks.zip)
-for FEELVOS both for training with and without YouTube-VOS data for the following datasets:
-
-* DAVIS 2017 validation set
-* DAVIS 2017 test-dev set
-* YouTube-Objects dataset
-
-## Local Inference
-For a demo of local inference on DAVIS 2017 run
-
-```bash
-# From tensorflow/models/research/feelvos
-sh eval.sh
-```
-
-## Local Training
-For a demo of local training on DAVIS 2017 run
-
-```bash
-# From tensorflow/models/research/feelvos
-sh train.sh
-```
-
-## Contacts (Maintainers)
-* Paul Voigtlaender, github: [pvoigtlaender](https://github.com/pvoigtlaender)
-* Yuning Chai, github: [yuningchai](https://github.com/yuningchai)
-* Liang-Chieh Chen, github: [aquariusjay](https://github.com/aquariusjay)
-
-## License
-
-All the codes in feelvos folder is covered by the [LICENSE](https://github.com/tensorflow/models/blob/master/LICENSE)
-under tensorflow/models. Please refer to the LICENSE for details.
diff --git a/research/feelvos/__init__.py b/research/feelvos/__init__.py
deleted file mode 100644
index 6f1373443d0ff84fd90714e41dade400ab41a22c..0000000000000000000000000000000000000000
--- a/research/feelvos/__init__.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
diff --git a/research/feelvos/common.py b/research/feelvos/common.py
deleted file mode 100644
index 98f5a9ce348aea36efa4b3cc57048d3659f18895..0000000000000000000000000000000000000000
--- a/research/feelvos/common.py
+++ /dev/null
@@ -1,163 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Provides flags that are common to scripts.
-
-Common flags from train/vis_video.py are collected in this script.
-"""
-import tensorflow as tf
-
-from deeplab import common
-
-flags = tf.app.flags
-
-flags.DEFINE_enum(
- 'classification_loss', 'softmax_with_attention',
- ['softmax', 'triplet', 'softmax_with_attention'],
- 'Type of loss function used for classifying pixels, can be either softmax, '
- 'softmax_with_attention, or triplet.')
-
-flags.DEFINE_integer('k_nearest_neighbors', 1,
- 'The number of nearest neighbors to use.')
-
-flags.DEFINE_integer('embedding_dimension', 100, 'The dimension used for the '
- 'learned embedding')
-
-flags.DEFINE_boolean('use_softmax_feedback', True,
- 'Whether to give the softmax predictions of the last '
- 'frame as additional input to the segmentation head.')
-
-flags.DEFINE_boolean('sample_adjacent_and_consistent_query_frames', True,
- 'If true, the query frames (all but the first frame '
- 'which is the reference frame) will be sampled such '
- 'that they are adjacent video frames and have the same '
- 'crop coordinates and flip augmentation. Note that if '
- 'use_softmax_feedback is True, this option will '
- 'automatically be activated.')
-
-flags.DEFINE_integer('embedding_seg_feature_dimension', 256,
- 'The dimensionality used in the segmentation head layers.')
-
-flags.DEFINE_integer('embedding_seg_n_layers', 4, 'The number of layers in the '
- 'segmentation head.')
-
-flags.DEFINE_integer('embedding_seg_kernel_size', 7, 'The kernel size used in '
- 'the segmentation head.')
-
-flags.DEFINE_multi_integer('embedding_seg_atrous_rates', [],
- 'The atrous rates to use for the segmentation head.')
-
-flags.DEFINE_boolean('normalize_nearest_neighbor_distances', True,
- 'Whether to normalize the nearest neighbor distances '
- 'to [0,1] using sigmoid, scale and shift.')
-
-flags.DEFINE_boolean('also_attend_to_previous_frame', True, 'Whether to also '
- 'use nearest neighbor attention with respect to the '
- 'previous frame.')
-
-flags.DEFINE_bool('use_local_previous_frame_attention', True,
- 'Whether to restrict the previous frame attention to a local '
- 'search window. Only has an effect, if '
- 'also_attend_to_previous_frame is True.')
-
-flags.DEFINE_integer('previous_frame_attention_window_size', 15,
- 'The window size used for local previous frame attention,'
- ' if use_local_previous_frame_attention is True.')
-
-flags.DEFINE_boolean('use_first_frame_matching', True, 'Whether to extract '
- 'features by matching to the reference frame. This should '
- 'always be true except for ablation experiments.')
-
-FLAGS = flags.FLAGS
-
-# Constants
-
-# Perform semantic segmentation predictions.
-OUTPUT_TYPE = common.OUTPUT_TYPE
-
-# Semantic segmentation item names.
-LABELS_CLASS = common.LABELS_CLASS
-IMAGE = common.IMAGE
-HEIGHT = common.HEIGHT
-WIDTH = common.WIDTH
-IMAGE_NAME = common.IMAGE_NAME
-SOURCE_ID = 'source_id'
-VIDEO_ID = 'video_id'
-LABEL = common.LABEL
-ORIGINAL_IMAGE = common.ORIGINAL_IMAGE
-PRECEDING_FRAME_LABEL = 'preceding_frame_label'
-
-# Test set name.
-TEST_SET = common.TEST_SET
-
-# Internal constants.
-OBJECT_LABEL = 'object_label'
-
-
-class VideoModelOptions(common.ModelOptions):
- """Internal version of immutable class to hold model options."""
-
- def __new__(cls,
- outputs_to_num_classes,
- crop_size=None,
- atrous_rates=None,
- output_stride=8):
- """Constructor to set default values.
-
- Args:
- outputs_to_num_classes: A dictionary from output type to the number of
- classes. For example, for the task of semantic segmentation with 21
- semantic classes, we would have outputs_to_num_classes['semantic'] = 21.
- crop_size: A tuple [crop_height, crop_width].
- atrous_rates: A list of atrous convolution rates for ASPP.
- output_stride: The ratio of input to output spatial resolution.
-
- Returns:
- A new VideoModelOptions instance.
- """
- self = super(VideoModelOptions, cls).__new__(
- cls,
- outputs_to_num_classes,
- crop_size,
- atrous_rates,
- output_stride)
- # Add internal flags.
- self.classification_loss = FLAGS.classification_loss
-
- return self
-
-
-def parse_decoder_output_stride():
- """Parses decoder output stride.
-
- FEELVOS assumes decoder_output_stride = 4. Thus, this function is created for
- this particular purpose.
-
- Returns:
- An integer specifying the decoder_output_stride.
-
- Raises:
- ValueError: If decoder_output_stride is None or contains more than one
- element.
- """
- if FLAGS.decoder_output_stride:
- decoder_output_stride = [
- int(x) for x in FLAGS.decoder_output_stride]
- if len(decoder_output_stride) != 1:
- raise ValueError('Expect decoder output stride has only one element.')
- decoder_output_stride = decoder_output_stride[0]
- else:
- raise ValueError('Expect flag decoder output stride not to be None.')
- return decoder_output_stride
diff --git a/research/feelvos/correlation_cost/README.md b/research/feelvos/correlation_cost/README.md
deleted file mode 100644
index 6cdbe550c7fcf63191f6967dd99c72cf341302bc..0000000000000000000000000000000000000000
--- a/research/feelvos/correlation_cost/README.md
+++ /dev/null
@@ -1,36 +0,0 @@
-# correlation_cost
-
-FEELVOS uses correlation_cost as an optional dependency to improve the speed and memory consumption
-of cross-correlation.
-
-## Installation
-
-Unfortunately we cannot provide the code for correlation_cost directly, so you
-will have to copy some files from this pull request
-https://github.com/tensorflow/tensorflow/pull/21392/. For your convenience we
-prepared scripts to download and adjust the code automatically.
-
-In the best case, all you need to do is run compile.sh with the path to your
-CUDA installation (tested only with CUDA 9).
-Note that the path should be to a folder containing the cuda folder, not to the
-cuda folder itself, e.g. if your cuda is in /usr/local/cuda-9.0, you can create
-a symlink /usr/local/cuda pointing to /usr/local/cuda-9.0 and then run
-
-```bash
-sh build.sh /usr/local/
-```
-
-This will
-
-* Download the code via ```sh get_code.sh ```
-* Apply minor adjustments to the code via ```sh fix_code.sh```
-* Clone the dependencies cub and thrust from github via ```sh clone_dependencies.sh```
-* Compile a shared library correlation_cost.so for correlation_cost via
-```sh compile.sh "${CUDA_DIR}"```
-
-Please review the licenses of correlation_cost, cub, and thrust.
-
-## Enabling correlation_cost
-If you managed to create the correlation_cost.so file, then set
-```USE_CORRELATION_COST = True``` in feelvos/utils/embedding_utils.py and try to run
-```sh eval.sh```.
diff --git a/research/feelvos/correlation_cost/build.sh b/research/feelvos/correlation_cost/build.sh
deleted file mode 100755
index 37d9adb3147df07646a462fd170772393abf5642..0000000000000000000000000000000000000000
--- a/research/feelvos/correlation_cost/build.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/bash
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-#
-# This script is used to download and build the code for correlation_cost.
-#
-# Usage:
-# sh ./build.sh cuda_dir
-# Where cuda_dir points to a directory containing the cuda folder (not the cuda folder itself).
-#
-#
-
-if [ "$#" -ne 1 ]; then
- echo "Illegal number of parameters, usage: ./build.sh cuda_dir"
- echo "Where cuda_dir points to a directory containing the cuda folder (not the cuda folder itself)"
- exit 1
-fi
-
-set -e
-set -x
-
-sh ./get_code.sh
-sh ./fix_code.sh
-sh ./clone_dependencies.sh
-sh ./compile.sh $1
diff --git a/research/feelvos/correlation_cost/clone_dependencies.sh b/research/feelvos/correlation_cost/clone_dependencies.sh
deleted file mode 100755
index 9174313f58a833a5ab547e21c63cdc87681cbc5d..0000000000000000000000000000000000000000
--- a/research/feelvos/correlation_cost/clone_dependencies.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-#
-# This script is used to clone the dependencies, i.e. cub and thrust, of correlation_cost from github.
-#
-# Usage:
-# sh ./clone_dependencies.sh
-#
-#
-
-# Clone cub.
-if [ ! -d cub ] ; then
- git clone https://github.com/dmlc/cub.git
-fi
-# Clone thrust.
-if [ ! -d thrust ] ; then
- git clone https://github.com/thrust/thrust.git
-fi
diff --git a/research/feelvos/correlation_cost/compile.sh b/research/feelvos/correlation_cost/compile.sh
deleted file mode 100755
index 6025292dfa78b44dd6fcf2f1b349af936a43fcc7..0000000000000000000000000000000000000000
--- a/research/feelvos/correlation_cost/compile.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/bash
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-#
-# This script is used to compile the code for correlation_cost and create correlation_cost.so.
-#
-# Usage:
-# sh ./compile.sh cuda_dir
-# Where cuda_dir points to a directory containing the cuda folder (not the cuda folder itself).
-#
-#
-
-if [ "$#" -ne 1 ]; then
- echo "Illegal number of parameters, usage: ./compile.sh cuda_dir"
- exit 1
-fi
-CUDA_DIR=$1
-
-if [ ! -d "${CUDA_DIR}/cuda" ]; then
- echo "cuda_dir must point to a directory containing the cuda folder, not to the cuda folder itself"
- exit 1
-fi
-
-TF_CFLAGS=( $(python -c 'import tensorflow as tf; print(" ".join(tf.sysconfig.get_compile_flags()))') )
-TF_LFLAGS=( $(python -c 'import tensorflow as tf; print(" ".join(tf.sysconfig.get_link_flags()))') )
-CUB_DIR=cub
-THRUST_DIR=thrust
-
-# Depending on the versions of your nvcc and gcc, the flag --expt-relaxed-constexpr might be required or should be removed.
-# If nvcc complains about a too new gcc version, you can point it to another gcc
-# version by using something like nvcc -ccbin /path/to/your/gcc6
-nvcc -std=c++11 --expt-relaxed-constexpr -I ./ -I ${CUB_DIR}/../ -I ${THRUST_DIR} -I ${CUDA_DIR}/ -c -o correlation_cost_op_gpu.o kernels/correlation_cost_op_gpu.cu.cc ${TF_CFLAGS[@]} -D GOOGLE_CUDA=1 -x cu -Xcompiler -fPIC
-
-g++ -std=c++11 -I ./ -L ${CUDA_DIR}/cuda/lib64 -shared -o correlation_cost.so ops/correlation_cost_op.cc kernels/correlation_cost_op.cc correlation_cost_op_gpu.o ${TF_CFLAGS[@]} -fPIC -lcudart ${TF_LFLAGS[@]} -D GOOGLE_CUDA=1
diff --git a/research/feelvos/correlation_cost/fix_code.sh b/research/feelvos/correlation_cost/fix_code.sh
deleted file mode 100755
index d4f285db3d745fc55a20bac57f97c6ca2fd8a5c4..0000000000000000000000000000000000000000
--- a/research/feelvos/correlation_cost/fix_code.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/bash
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-#
-# This script is used to modify the downloaded code.
-#
-# Usage:
-# sh ./fix_code.sh
-#
-#
-
-sed -i "s/tensorflow\/contrib\/correlation_cost\///g" kernels/correlation_cost_op_gpu.cu.cc
-sed -i "s/tensorflow\/contrib\/correlation_cost\///g" kernels/correlation_cost_op.cc
-sed -i "s/external\/cub_archive\//cub\//g" kernels/correlation_cost_op_gpu.cu.cc
-
-sed -i "s/from tensorflow.contrib.util import loader/import tensorflow as tf/g" python/ops/correlation_cost_op.py
-grep -v "from tensorflow" python/ops/correlation_cost_op.py | grep -v resource_loader.get_path_to_datafile > correlation_cost_op.py.tmp && mv correlation_cost_op.py.tmp python/ops/correlation_cost_op.py
-sed -i "s/array_ops/tf/g" python/ops/correlation_cost_op.py
-sed -i "s/ops/tf/g" python/ops/correlation_cost_op.py
-sed -i "s/loader.load_op_library(/tf.load_op_library('feelvos\/correlation_cost\/correlation_cost.so')/g" python/ops/correlation_cost_op.py
-sed -i "s/gen_correlation_cost_op/_correlation_cost_op_so/g" python/ops/correlation_cost_op.py
diff --git a/research/feelvos/correlation_cost/get_code.sh b/research/feelvos/correlation_cost/get_code.sh
deleted file mode 100755
index 337142166ac4b61835417e807ef0a495532d749c..0000000000000000000000000000000000000000
--- a/research/feelvos/correlation_cost/get_code.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/bash
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-#
-# This script is used to download the code for correlation_cost.
-#
-# Usage:
-# sh ./get_code.sh
-#
-#
-
-mkdir -p kernels ops python/ops
-touch __init__.py
-touch python/__init__.py
-touch python/ops/__init__.py
-wget https://raw.githubusercontent.com/tensorflow/tensorflow/91b163b9bd8dd0f8c2631b4245a67dfd387536a6/tensorflow/contrib/correlation_cost/ops/correlation_cost_op.cc -O ops/correlation_cost_op.cc
-wget https://raw.githubusercontent.com/tensorflow/tensorflow/91b163b9bd8dd0f8c2631b4245a67dfd387536a6/tensorflow/contrib/correlation_cost/python/ops/correlation_cost_op.py -O python/ops/correlation_cost_op.py
-wget https://raw.githubusercontent.com/tensorflow/tensorflow/91b163b9bd8dd0f8c2631b4245a67dfd387536a6/tensorflow/contrib/correlation_cost/kernels/correlation_cost_op.cc -O kernels/correlation_cost_op.cc
-wget https://raw.githubusercontent.com/tensorflow/tensorflow/91b163b9bd8dd0f8c2631b4245a67dfd387536a6/tensorflow/contrib/correlation_cost/kernels/correlation_cost_op.h -O kernels/correlation_cost_op.h
-wget https://raw.githubusercontent.com/tensorflow/tensorflow/91b163b9bd8dd0f8c2631b4245a67dfd387536a6/tensorflow/contrib/correlation_cost/kernels/correlation_cost_op_gpu.cu.cc -O kernels/correlation_cost_op_gpu.cu.cc
diff --git a/research/feelvos/datasets/__init__.py b/research/feelvos/datasets/__init__.py
deleted file mode 100644
index 6f1373443d0ff84fd90714e41dade400ab41a22c..0000000000000000000000000000000000000000
--- a/research/feelvos/datasets/__init__.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
diff --git a/research/feelvos/datasets/build_davis2017_data.py b/research/feelvos/datasets/build_davis2017_data.py
deleted file mode 100644
index 5e093fc3b4531f5439957ea3608770441bd5ce4a..0000000000000000000000000000000000000000
--- a/research/feelvos/datasets/build_davis2017_data.py
+++ /dev/null
@@ -1,163 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Converts DAVIS 2017 data to TFRecord file format with SequenceExample protos.
-"""
-
-import io
-import math
-import os
-from StringIO import StringIO
-import numpy as np
-import PIL
-import tensorflow as tf
-
-FLAGS = tf.app.flags.FLAGS
-
-tf.app.flags.DEFINE_string('data_folder', 'DAVIS2017/',
- 'Folder containing the DAVIS 2017 data')
-
-tf.app.flags.DEFINE_string('imageset', 'val',
- 'Which subset to use, either train or val')
-
-tf.app.flags.DEFINE_string(
- 'output_dir', './tfrecord',
- 'Path to save converted TFRecords of TensorFlow examples.')
-
-_NUM_SHARDS_TRAIN = 10
-_NUM_SHARDS_VAL = 1
-
-
-def read_image(path):
- with open(path) as fid:
- image_str = fid.read()
- image = PIL.Image.open(io.BytesIO(image_str))
- w, h = image.size
- return image_str, (h, w)
-
-
-def read_annotation(path):
- """Reads a single image annotation from a png image.
-
- Args:
- path: Path to the png image.
-
- Returns:
- png_string: The png encoded as string.
- size: Tuple of (height, width).
- """
- with open(path) as fid:
- x = np.array(PIL.Image.open(fid))
- h, w = x.shape
- im = PIL.Image.fromarray(x)
-
- output = StringIO()
- im.save(output, format='png')
- png_string = output.getvalue()
- output.close()
-
- return png_string, (h, w)
-
-
-def process_video(key, input_dir, anno_dir):
- """Creates a SequenceExample for the video.
-
- Args:
- key: Name of the video.
- input_dir: Directory which contains the image files.
- anno_dir: Directory which contains the annotation files.
-
- Returns:
- The created SequenceExample.
- """
- frame_names = sorted(tf.gfile.ListDirectory(input_dir))
- anno_files = sorted(tf.gfile.ListDirectory(anno_dir))
- assert len(frame_names) == len(anno_files)
-
- sequence = tf.train.SequenceExample()
- context = sequence.context.feature
- features = sequence.feature_lists.feature_list
-
- for i, name in enumerate(frame_names):
- image_str, image_shape = read_image(
- os.path.join(input_dir, name))
- anno_str, anno_shape = read_annotation(
- os.path.join(anno_dir, name[:-4] + '.png'))
- image_encoded = features['image/encoded'].feature.add()
- image_encoded.bytes_list.value.append(image_str)
- segmentation_encoded = features['segmentation/object/encoded'].feature.add()
- segmentation_encoded.bytes_list.value.append(anno_str)
-
- np.testing.assert_array_equal(np.array(image_shape), np.array(anno_shape))
-
- if i == 0:
- first_shape = np.array(image_shape)
- else:
- np.testing.assert_array_equal(np.array(image_shape), first_shape)
-
- context['video_id'].bytes_list.value.append(key.encode('ascii'))
- context['clip/frames'].int64_list.value.append(len(frame_names))
- context['image/format'].bytes_list.value.append('JPEG')
- context['image/channels'].int64_list.value.append(3)
- context['image/height'].int64_list.value.append(first_shape[0])
- context['image/width'].int64_list.value.append(first_shape[1])
- context['segmentation/object/format'].bytes_list.value.append('PNG')
- context['segmentation/object/height'].int64_list.value.append(first_shape[0])
- context['segmentation/object/width'].int64_list.value.append(first_shape[1])
-
- return sequence
-
-
-def convert(data_folder, imageset, output_dir, num_shards):
- """Converts the specified subset of DAVIS 2017 to TFRecord format.
-
- Args:
- data_folder: The path to the DAVIS 2017 data.
- imageset: The subset to use, either train or val.
- output_dir: Where to store the TFRecords.
- num_shards: The number of shards used for storing the data.
- """
- sets_file = os.path.join(data_folder, 'ImageSets', '2017', imageset + '.txt')
- vids = [x.strip() for x in open(sets_file).readlines()]
- num_vids = len(vids)
- num_vids_per_shard = int(math.ceil(num_vids) / float(num_shards))
- for shard_id in range(num_shards):
- output_filename = os.path.join(
- output_dir,
- '%s-%05d-of-%05d.tfrecord' % (imageset, shard_id, num_shards))
- with tf.python_io.TFRecordWriter(output_filename) as tfrecord_writer:
- start_idx = shard_id * num_vids_per_shard
- end_idx = min((shard_id + 1) * num_vids_per_shard, num_vids)
- for i in range(start_idx, end_idx):
- print('Converting video %d/%d shard %d video %s' % (
- i + 1, num_vids, shard_id, vids[i]))
- img_dir = os.path.join(data_folder, 'JPEGImages', '480p', vids[i])
- anno_dir = os.path.join(data_folder, 'Annotations', '480p', vids[i])
- example = process_video(vids[i], img_dir, anno_dir)
- tfrecord_writer.write(example.SerializeToString())
-
-
-def main(unused_argv):
- imageset = FLAGS.imageset
- assert imageset in ('train', 'val')
- if imageset == 'train':
- num_shards = _NUM_SHARDS_TRAIN
- else:
- num_shards = _NUM_SHARDS_VAL
- convert(FLAGS.data_folder, FLAGS.imageset, FLAGS.output_dir, num_shards)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/feelvos/datasets/download_and_convert_davis17.sh b/research/feelvos/datasets/download_and_convert_davis17.sh
deleted file mode 100644
index 011be61ba7586c8f3d141ccc00194d1c7ae56c3a..0000000000000000000000000000000000000000
--- a/research/feelvos/datasets/download_and_convert_davis17.sh
+++ /dev/null
@@ -1,77 +0,0 @@
-#!/bin/bash
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-#
-# Script to download and preprocess the DAVIS 2017 dataset.
-#
-# Usage:
-# bash ./download_and_convert_davis17.sh
-
-# Exit immediately if a command exits with a non-zero status.
-set -e
-
-CURRENT_DIR=$(pwd)
-WORK_DIR="./davis17"
-mkdir -p "${WORK_DIR}"
-cd "${WORK_DIR}"
-
-# Helper function to download and unpack the DAVIS 2017 dataset.
-download_and_uncompress() {
- local BASE_URL=${1}
- local FILENAME=${2}
-
- if [ ! -f "${FILENAME}" ]; then
- echo "Downloading ${FILENAME} to ${WORK_DIR}"
- wget -nd -c "${BASE_URL}/${FILENAME}"
- echo "Uncompressing ${FILENAME}"
- unzip "${FILENAME}"
- fi
-}
-
-BASE_URL="https://data.vision.ee.ethz.ch/csergi/share/davis/"
-FILENAME="DAVIS-2017-trainval-480p.zip"
-
-download_and_uncompress "${BASE_URL}" "${FILENAME}"
-
-cd "${CURRENT_DIR}"
-
-# Root path for DAVIS 2017 dataset.
-DAVIS_ROOT="${WORK_DIR}/DAVIS"
-
-# Build TFRecords of the dataset.
-# First, create output directory for storing TFRecords.
-OUTPUT_DIR="${WORK_DIR}/tfrecord"
-mkdir -p "${OUTPUT_DIR}"
-
-IMAGE_FOLDER="${DAVIS_ROOT}/JPEGImages"
-LIST_FOLDER="${DAVIS_ROOT}/ImageSets/Segmentation"
-
-# Convert validation set.
-if [ ! -f "${OUTPUT_DIR}/val-00000-of-00001.tfrecord" ]; then
- echo "Converting DAVIS 2017 dataset (val)..."
- python ./build_davis2017_data.py \
- --data_folder="${DAVIS_ROOT}" \
- --imageset=val \
- --output_dir="${OUTPUT_DIR}"
-fi
-
-# Convert training set.
-if [ ! -f "${OUTPUT_DIR}/train-00009-of-00010.tfrecord" ]; then
- echo "Converting DAVIS 2017 dataset (train)..."
- python ./build_davis2017_data.py \
- --data_folder="${DAVIS_ROOT}" \
- --imageset=train \
- --output_dir="${OUTPUT_DIR}"
-fi
diff --git a/research/feelvos/datasets/tfsequence_example_decoder.py b/research/feelvos/datasets/tfsequence_example_decoder.py
deleted file mode 100644
index 2fa3e95d5b98eb00aa485371037b4ad6b0e7ece3..0000000000000000000000000000000000000000
--- a/research/feelvos/datasets/tfsequence_example_decoder.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Contains the TFExampleDecoder.
-
-The TFExampleDecode is a DataDecoder used to decode TensorFlow Example protos.
-In order to do so each requested item must be paired with one or more Example
-features that are parsed to produce the Tensor-based manifestation of the item.
-"""
-
-import tensorflow as tf
-slim = tf.contrib.slim
-data_decoder = slim.data_decoder
-
-
-class TFSequenceExampleDecoder(data_decoder.DataDecoder):
- """A decoder for TensorFlow SequenceExamples.
-
- Decoding SequenceExample proto buffers is comprised of two stages:
- (1) Example parsing and (2) tensor manipulation.
-
- In the first stage, the tf.parse_single_sequence_example function is called
- with a list of FixedLenFeatures and SparseLenFeatures. These instances tell TF
- how to parse the example. The output of this stage is a set of tensors.
-
- In the second stage, the resulting tensors are manipulated to provide the
- requested 'item' tensors.
-
- To perform this decoding operation, a SequenceExampleDecoder is given a list
- of ItemHandlers. Each ItemHandler indicates the set of features for stage 1
- and contains the instructions for post_processing its tensors for stage 2.
- """
-
- def __init__(self, keys_to_context_features, keys_to_sequence_features,
- items_to_handlers):
- """Constructs the decoder.
-
- Args:
- keys_to_context_features: a dictionary from TF-SequenceExample context
- keys to either tf.VarLenFeature or tf.FixedLenFeature instances.
- See tensorflow's parsing_ops.py.
- keys_to_sequence_features: a dictionary from TF-SequenceExample sequence
- keys to either tf.VarLenFeature or tf.FixedLenSequenceFeature instances.
- See tensorflow's parsing_ops.py.
- items_to_handlers: a dictionary from items (strings) to ItemHandler
- instances. Note that the ItemHandler's are provided the keys that they
- use to return the final item Tensors.
-
- Raises:
- ValueError: if the same key is present for context features and sequence
- features.
- """
- unique_keys = set()
- unique_keys.update(keys_to_context_features)
- unique_keys.update(keys_to_sequence_features)
- if len(unique_keys) != (
- len(keys_to_context_features) + len(keys_to_sequence_features)):
- # This situation is ambiguous in the decoder's keys_to_tensors variable.
- raise ValueError('Context and sequence keys are not unique. \n'
- ' Context keys: %s \n Sequence keys: %s' %
- (list(keys_to_context_features.keys()),
- list(keys_to_sequence_features.keys())))
-
- self._keys_to_context_features = keys_to_context_features
- self._keys_to_sequence_features = keys_to_sequence_features
- self._items_to_handlers = items_to_handlers
-
- def list_items(self):
- """See base class."""
- return self._items_to_handlers.keys()
-
- def decode(self, serialized_example, items=None):
- """Decodes the given serialized TF-SequenceExample.
-
- Args:
- serialized_example: a serialized TF-SequenceExample tensor.
- items: the list of items to decode. These must be a subset of the item
- keys in self._items_to_handlers. If `items` is left as None, then all
- of the items in self._items_to_handlers are decoded.
-
- Returns:
- the decoded items, a list of tensor.
- """
-
- context, feature_list = tf.parse_single_sequence_example(
- serialized_example, self._keys_to_context_features,
- self._keys_to_sequence_features)
-
- # Reshape non-sparse elements just once:
- for k in self._keys_to_context_features:
- v = self._keys_to_context_features[k]
- if isinstance(v, tf.FixedLenFeature):
- context[k] = tf.reshape(context[k], v.shape)
-
- if not items:
- items = self._items_to_handlers.keys()
-
- outputs = []
- for item in items:
- handler = self._items_to_handlers[item]
- keys_to_tensors = {
- key: context[key] if key in context else feature_list[key]
- for key in handler.keys
- }
- outputs.append(handler.tensors_to_item(keys_to_tensors))
- return outputs
diff --git a/research/feelvos/datasets/video_dataset.py b/research/feelvos/datasets/video_dataset.py
deleted file mode 100644
index 17b62e989af866df0232a0e6d921faee84fe1fa7..0000000000000000000000000000000000000000
--- a/research/feelvos/datasets/video_dataset.py
+++ /dev/null
@@ -1,196 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Provides data from video object segmentation datasets.
-
-This file provides both images and annotations (instance segmentations) for
-TensorFlow. Currently, we support the following datasets:
-
-1. DAVIS 2017 (https://davischallenge.org/davis2017/code.html).
-
-2. DAVIS 2016 (https://davischallenge.org/davis2016/code.html).
-
-3. YouTube-VOS (https://youtube-vos.org/dataset/download).
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-import os.path
-import tensorflow as tf
-from feelvos.datasets import tfsequence_example_decoder
-
-slim = tf.contrib.slim
-dataset = slim.dataset
-tfexample_decoder = slim.tfexample_decoder
-
-
-_ITEMS_TO_DESCRIPTIONS = {
- 'image': 'A color image of varying height and width.',
- 'labels_class': ('A semantic segmentation label whose size matches image.'
- 'Its values range from 0 (background) to num_classes.'),
-}
-
-# Named tuple to describe the dataset properties.
-DatasetDescriptor = collections.namedtuple(
- 'DatasetDescriptor',
- ['splits_to_sizes', # Splits of the dataset into training, val, and test.
- 'num_classes', # Number of semantic classes.
- 'ignore_label', # Ignore label value.
- ]
-)
-
-_DAVIS_2016_INFORMATION = DatasetDescriptor(
- splits_to_sizes={'train': [30, 1830],
- 'val': [20, 1376]},
- num_classes=2,
- ignore_label=255,
-)
-
-_DAVIS_2017_INFORMATION = DatasetDescriptor(
- splits_to_sizes={'train': [60, 4219],
- 'val': [30, 2023],
- 'test-dev': [30, 2037]},
- num_classes=None, # Number of instances per videos differ.
- ignore_label=255,
-)
-
-_YOUTUBE_VOS_2018_INFORMATION = DatasetDescriptor(
- # Leave these sizes as None to allow for different splits into
- # training and validation sets.
- splits_to_sizes={'train': [None, None],
- 'val': [None, None]},
- num_classes=None, # Number of instances per video differs.
- ignore_label=255,
-)
-
-_DATASETS_INFORMATION = {
- 'davis_2016': _DAVIS_2016_INFORMATION,
- 'davis_2017': _DAVIS_2017_INFORMATION,
- 'youtube_vos_2018': _YOUTUBE_VOS_2018_INFORMATION,
-}
-
-# Default file pattern of SSTable. Note we include '-' to avoid the confusion
-# between `train-` and `trainval-` sets.
-_FILE_PATTERN = '%s-*'
-
-
-def get_dataset(dataset_name,
- split_name,
- dataset_dir,
- file_pattern=None,
- data_type='tf_sequence_example',
- decode_video_frames=False):
- """Gets an instance of slim Dataset.
-
- Args:
- dataset_name: String, dataset name.
- split_name: String, the train/val Split name.
- dataset_dir: String, the directory of the dataset sources.
- file_pattern: String, file pattern of SSTable.
- data_type: String, data type. Currently supports 'tf_example' and
- 'annotated_image'.
- decode_video_frames: Boolean, decode the images or not. Not decoding it here
- is useful if we subsample later
-
- Returns:
- An instance of slim Dataset.
-
- Raises:
- ValueError: If the dataset_name or split_name is not recognized, or if
- the dataset_type is not supported.
- """
- if dataset_name not in _DATASETS_INFORMATION:
- raise ValueError('The specified dataset is not supported yet.')
-
- splits_to_sizes = _DATASETS_INFORMATION[dataset_name].splits_to_sizes
-
- if split_name not in splits_to_sizes:
- raise ValueError('data split name %s not recognized' % split_name)
-
- # Prepare the variables for different datasets.
- num_classes = _DATASETS_INFORMATION[dataset_name].num_classes
- ignore_label = _DATASETS_INFORMATION[dataset_name].ignore_label
-
- if file_pattern is None:
- file_pattern = _FILE_PATTERN
- file_pattern = os.path.join(dataset_dir, file_pattern % split_name)
- if data_type == 'tf_sequence_example':
- keys_to_context_features = {
- 'image/format': tf.FixedLenFeature((), tf.string, default_value='jpeg'),
- 'image/height': tf.FixedLenFeature((), tf.int64, default_value=0),
- 'image/width': tf.FixedLenFeature((), tf.int64, default_value=0),
- 'segmentation/object/format': tf.FixedLenFeature(
- (), tf.string, default_value='png'),
- 'video_id': tf.FixedLenFeature((), tf.string, default_value='unknown')
- }
- label_name = 'class' if dataset_name == 'davis_2016' else 'object'
- keys_to_sequence_features = {
- 'image/encoded': tf.FixedLenSequenceFeature((), dtype=tf.string),
- 'segmentation/{}/encoded'.format(label_name):
- tf.FixedLenSequenceFeature((), tf.string),
- 'segmentation/{}/encoded'.format(label_name):
- tf.FixedLenSequenceFeature((), tf.string),
- }
- items_to_handlers = {
- 'height': tfexample_decoder.Tensor('image/height'),
- 'width': tfexample_decoder.Tensor('image/width'),
- 'video_id': tfexample_decoder.Tensor('video_id')
- }
- if decode_video_frames:
- decode_image_handler = tfexample_decoder.Image(
- image_key='image/encoded',
- format_key='image/format',
- channels=3,
- repeated=True)
- items_to_handlers['image'] = decode_image_handler
- decode_label_handler = tfexample_decoder.Image(
- image_key='segmentation/{}/encoded'.format(label_name),
- format_key='segmentation/{}/format'.format(label_name),
- channels=1,
- repeated=True)
- items_to_handlers['labels_class'] = decode_label_handler
- else:
- items_to_handlers['image/encoded'] = tfexample_decoder.Tensor(
- 'image/encoded')
- items_to_handlers[
- 'segmentation/object/encoded'] = tfexample_decoder.Tensor(
- 'segmentation/{}/encoded'.format(label_name))
- decoder = tfsequence_example_decoder.TFSequenceExampleDecoder(
- keys_to_context_features, keys_to_sequence_features, items_to_handlers)
- else:
- raise ValueError('Unknown data type.')
-
- size = splits_to_sizes[split_name]
- if isinstance(size, collections.Sequence):
- num_videos = size[0]
- num_samples = size[1]
- else:
- num_videos = 0
- num_samples = size
-
- return dataset.Dataset(
- data_sources=file_pattern,
- reader=tf.TFRecordReader,
- decoder=decoder,
- num_samples=num_samples,
- num_videos=num_videos,
- items_to_descriptions=_ITEMS_TO_DESCRIPTIONS,
- ignore_label=ignore_label,
- num_classes=num_classes,
- name=dataset_name,
- multi_label=True)
diff --git a/research/feelvos/eval.sh b/research/feelvos/eval.sh
deleted file mode 100755
index 96cb7f409a1e652ba8263f35c3786cb0cb77f5d1..0000000000000000000000000000000000000000
--- a/research/feelvos/eval.sh
+++ /dev/null
@@ -1,86 +0,0 @@
-#!/bin/bash
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-#
-# This script is used to locally run inference on DAVIS 2017. Users could also
-# modify from this script for their use case. See train.sh for an example of
-# local training.
-#
-# Usage:
-# # From the tensorflow/models/research/feelvos directory.
-# sh ./eval.sh
-#
-#
-
-# Exit immediately if a command exits with a non-zero status.
-set -e
-
-# Move one-level up to tensorflow/models/research directory.
-cd ..
-
-# Update PYTHONPATH.
-export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim:`pwd`/feelvos
-
-# Set up the working environment.
-CURRENT_DIR=$(pwd)
-WORK_DIR="${CURRENT_DIR}/feelvos"
-
-# Run embedding_utils_test first to make sure the PYTHONPATH is correctly set.
-python "${WORK_DIR}"/utils/embedding_utils_test.py -v
-
-# Go to datasets folder and download and convert the DAVIS 2017 dataset.
-DATASET_DIR="datasets"
-cd "${WORK_DIR}/${DATASET_DIR}"
-sh download_and_convert_davis17.sh
-
-# Go to models folder and download and unpack the DAVIS 2017 trained model.
-MODELS_DIR="models"
-mkdir -p "${WORK_DIR}/${MODELS_DIR}"
-cd "${WORK_DIR}/${MODELS_DIR}"
-if [ ! -d "feelvos_davis17_trained" ]; then
- wget http://download.tensorflow.org/models/feelvos_davis17_trained.tar.gz
- tar -xvf feelvos_davis17_trained.tar.gz
- echo "model_checkpoint_path: \"model.ckpt-200004\"" > feelvos_davis17_trained/checkpoint
- rm feelvos_davis17_trained.tar.gz
-fi
-CHECKPOINT_DIR="${WORK_DIR}/${MODELS_DIR}/feelvos_davis17_trained/"
-
-# Go back to orignal directory.
-cd "${CURRENT_DIR}"
-
-# Set up the working directories.
-DAVIS_FOLDER="davis17"
-EXP_FOLDER="exp/eval_on_val_set"
-VIS_LOGDIR="${WORK_DIR}/${DATASET_DIR}/${DAVIS_FOLDER}/${EXP_FOLDER}/eval"
-mkdir -p ${VIS_LOGDIR}
-
-DAVIS_DATASET="${WORK_DIR}/${DATASET_DIR}/${DAVIS_FOLDER}/tfrecord"
-
-python "${WORK_DIR}"/vis_video.py \
- --dataset=davis_2017 \
- --dataset_dir="${DAVIS_DATASET}" \
- --vis_logdir="${VIS_LOGDIR}" \
- --checkpoint_dir="${CHECKPOINT_DIR}" \
- --logtostderr \
- --atrous_rates=12 \
- --atrous_rates=24 \
- --atrous_rates=36 \
- --decoder_output_stride=4 \
- --model_variant=xception_65 \
- --multi_grid=1 \
- --multi_grid=1 \
- --multi_grid=1 \
- --output_stride=8 \
- --save_segmentations
diff --git a/research/feelvos/input_preprocess.py b/research/feelvos/input_preprocess.py
deleted file mode 100644
index 954c0b42ef2650b1c25ec8071933beee57e9bd69..0000000000000000000000000000000000000000
--- a/research/feelvos/input_preprocess.py
+++ /dev/null
@@ -1,280 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Prepare the data used for FEELVOS training/evaluation."""
-import tensorflow as tf
-
-from deeplab.core import feature_extractor
-from deeplab.core import preprocess_utils
-
-# The probability of flipping the images and labels
-# left-right during training
-_PROB_OF_FLIP = 0.5
-
-get_random_scale = preprocess_utils.get_random_scale
-randomly_scale_image_and_label = (
- preprocess_utils.randomly_scale_image_and_label)
-
-
-def preprocess_image_and_label(image,
- label,
- crop_height,
- crop_width,
- min_resize_value=None,
- max_resize_value=None,
- resize_factor=None,
- min_scale_factor=1.,
- max_scale_factor=1.,
- scale_factor_step_size=0,
- ignore_label=255,
- is_training=True,
- model_variant=None):
- """Preprocesses the image and label.
-
- Args:
- image: Input image.
- label: Ground truth annotation label.
- crop_height: The height value used to crop the image and label.
- crop_width: The width value used to crop the image and label.
- min_resize_value: Desired size of the smaller image side.
- max_resize_value: Maximum allowed size of the larger image side.
- resize_factor: Resized dimensions are multiple of factor plus one.
- min_scale_factor: Minimum scale factor value.
- max_scale_factor: Maximum scale factor value.
- scale_factor_step_size: The step size from min scale factor to max scale
- factor. The input is randomly scaled based on the value of
- (min_scale_factor, max_scale_factor, scale_factor_step_size).
- ignore_label: The label value which will be ignored for training and
- evaluation.
- is_training: If the preprocessing is used for training or not.
- model_variant: Model variant (string) for choosing how to mean-subtract the
- images. See feature_extractor.network_map for supported model variants.
-
- Returns:
- original_image: Original image (could be resized).
- processed_image: Preprocessed image.
- label: Preprocessed ground truth segmentation label.
-
- Raises:
- ValueError: Ground truth label not provided during training.
- """
- if is_training and label is None:
- raise ValueError('During training, label must be provided.')
- if model_variant is None:
- tf.logging.warning('Default mean-subtraction is performed. Please specify '
- 'a model_variant. See feature_extractor.network_map for '
- 'supported model variants.')
-
- # Keep reference to original image.
- original_image = image
-
- processed_image = tf.cast(image, tf.float32)
-
- if label is not None:
- label = tf.cast(label, tf.int32)
-
- # Resize image and label to the desired range.
- if min_resize_value is not None or max_resize_value is not None:
- [processed_image, label] = (
- preprocess_utils.resize_to_range(
- image=processed_image,
- label=label,
- min_size=min_resize_value,
- max_size=max_resize_value,
- factor=resize_factor,
- align_corners=True))
- # The `original_image` becomes the resized image.
- original_image = tf.identity(processed_image)
-
- # Data augmentation by randomly scaling the inputs.
- scale = get_random_scale(
- min_scale_factor, max_scale_factor, scale_factor_step_size)
- processed_image, label = randomly_scale_image_and_label(
- processed_image, label, scale)
-
- processed_image.set_shape([None, None, 3])
-
- if crop_height is not None and crop_width is not None:
- # Pad image and label to have dimensions >= [crop_height, crop_width].
- image_shape = tf.shape(processed_image)
- image_height = image_shape[0]
- image_width = image_shape[1]
-
- target_height = image_height + tf.maximum(crop_height - image_height, 0)
- target_width = image_width + tf.maximum(crop_width - image_width, 0)
-
- # Pad image with mean pixel value.
- mean_pixel = tf.reshape(
- feature_extractor.mean_pixel(model_variant), [1, 1, 3])
- processed_image = preprocess_utils.pad_to_bounding_box(
- processed_image, 0, 0, target_height, target_width, mean_pixel)
-
- if label is not None:
- label = preprocess_utils.pad_to_bounding_box(
- label, 0, 0, target_height, target_width, ignore_label)
-
- # Randomly crop the image and label.
- if is_training and label is not None:
- processed_image, label = preprocess_utils.random_crop(
- [processed_image, label], crop_height, crop_width)
-
- processed_image.set_shape([crop_height, crop_width, 3])
-
- if label is not None:
- label.set_shape([crop_height, crop_width, 1])
-
- if is_training:
- # Randomly left-right flip the image and label.
- processed_image, label, _ = preprocess_utils.flip_dim(
- [processed_image, label], _PROB_OF_FLIP, dim=1)
-
- return original_image, processed_image, label
-
-
-def preprocess_images_and_labels_consistently(images,
- labels,
- crop_height,
- crop_width,
- min_resize_value=None,
- max_resize_value=None,
- resize_factor=None,
- min_scale_factor=1.,
- max_scale_factor=1.,
- scale_factor_step_size=0,
- ignore_label=255,
- is_training=True,
- model_variant=None):
- """Preprocesses images and labels in a consistent way.
-
- Similar to preprocess_image_and_label, but works on a list of images
- and a list of labels and uses the same crop coordinates and either flips
- all images and labels or none of them.
-
- Args:
- images: List of input images.
- labels: List of ground truth annotation labels.
- crop_height: The height value used to crop the image and label.
- crop_width: The width value used to crop the image and label.
- min_resize_value: Desired size of the smaller image side.
- max_resize_value: Maximum allowed size of the larger image side.
- resize_factor: Resized dimensions are multiple of factor plus one.
- min_scale_factor: Minimum scale factor value.
- max_scale_factor: Maximum scale factor value.
- scale_factor_step_size: The step size from min scale factor to max scale
- factor. The input is randomly scaled based on the value of
- (min_scale_factor, max_scale_factor, scale_factor_step_size).
- ignore_label: The label value which will be ignored for training and
- evaluation.
- is_training: If the preprocessing is used for training or not.
- model_variant: Model variant (string) for choosing how to mean-subtract the
- images. See feature_extractor.network_map for supported model variants.
-
- Returns:
- original_images: Original images (could be resized).
- processed_images: Preprocessed images.
- labels: Preprocessed ground truth segmentation labels.
-
- Raises:
- ValueError: Ground truth label not provided during training.
- """
- if is_training and labels is None:
- raise ValueError('During training, labels must be provided.')
- if model_variant is None:
- tf.logging.warning('Default mean-subtraction is performed. Please specify '
- 'a model_variant. See feature_extractor.network_map for '
- 'supported model variants.')
- if labels is not None:
- assert len(images) == len(labels)
- num_imgs = len(images)
-
- # Keep reference to original images.
- original_images = images
-
- processed_images = [tf.cast(image, tf.float32) for image in images]
-
- if labels is not None:
- labels = [tf.cast(label, tf.int32) for label in labels]
-
- # Resize images and labels to the desired range.
- if min_resize_value is not None or max_resize_value is not None:
- processed_images, labels = zip(*[
- preprocess_utils.resize_to_range(
- image=processed_image,
- label=label,
- min_size=min_resize_value,
- max_size=max_resize_value,
- factor=resize_factor,
- align_corners=True) for processed_image, label
- in zip(processed_images, labels)])
- # The `original_images` becomes the resized images.
- original_images = [tf.identity(processed_image)
- for processed_image in processed_images]
-
- # Data augmentation by randomly scaling the inputs.
- scale = get_random_scale(
- min_scale_factor, max_scale_factor, scale_factor_step_size)
- processed_images, labels = zip(
- *[randomly_scale_image_and_label(processed_image, label, scale)
- for processed_image, label in zip(processed_images, labels)])
-
- for processed_image in processed_images:
- processed_image.set_shape([None, None, 3])
-
- if crop_height is not None and crop_width is not None:
- # Pad image and label to have dimensions >= [crop_height, crop_width].
- image_shape = tf.shape(processed_images[0])
- image_height = image_shape[0]
- image_width = image_shape[1]
-
- target_height = image_height + tf.maximum(crop_height - image_height, 0)
- target_width = image_width + tf.maximum(crop_width - image_width, 0)
-
- # Pad image with mean pixel value.
- mean_pixel = tf.reshape(
- feature_extractor.mean_pixel(model_variant), [1, 1, 3])
- processed_images = [preprocess_utils.pad_to_bounding_box(
- processed_image, 0, 0, target_height, target_width, mean_pixel)
- for processed_image in processed_images]
-
- if labels is not None:
- labels = [preprocess_utils.pad_to_bounding_box(
- label, 0, 0, target_height, target_width, ignore_label)
- for label in labels]
-
- # Randomly crop the images and labels.
- if is_training and labels is not None:
- cropped = preprocess_utils.random_crop(
- processed_images + labels, crop_height, crop_width)
- assert len(cropped) == 2 * num_imgs
- processed_images = cropped[:num_imgs]
- labels = cropped[num_imgs:]
-
- for processed_image in processed_images:
- processed_image.set_shape([crop_height, crop_width, 3])
-
- if labels is not None:
- for label in labels:
- label.set_shape([crop_height, crop_width, 1])
-
- if is_training:
- # Randomly left-right flip the image and label.
- res = preprocess_utils.flip_dim(
- list(processed_images + labels), _PROB_OF_FLIP, dim=1)
- maybe_flipped = res[:-1]
- assert len(maybe_flipped) == 2 * num_imgs
- processed_images = maybe_flipped[:num_imgs]
- labels = maybe_flipped[num_imgs:]
-
- return original_images, processed_images, labels
diff --git a/research/feelvos/model.py b/research/feelvos/model.py
deleted file mode 100644
index f145f91616958b7327d99bb55efb1b7b5016a223..0000000000000000000000000000000000000000
--- a/research/feelvos/model.py
+++ /dev/null
@@ -1,480 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-r"""Provides DeepLab model definition and helper functions.
-
-DeepLab is a deep learning system for semantic image segmentation with
-the following features:
-
-(1) Atrous convolution to explicitly control the resolution at which
-feature responses are computed within Deep Convolutional Neural Networks.
-
-(2) Atrous spatial pyramid pooling (ASPP) to robustly segment objects at
-multiple scales with filters at multiple sampling rates and effective
-fields-of-views.
-
-(3) ASPP module augmented with image-level feature and batch normalization.
-
-(4) A simple yet effective decoder module to recover the object boundaries.
-
-See the following papers for more details:
-
-"Encoder-Decoder with Atrous Separable Convolution for Semantic Image
-Segmentation"
-Liang-Chieh Chen, Yukun Zhu, George Papandreou, Florian Schroff, Hartwig Adam.
-(https://arxiv.org/abs1802.02611)
-
-"Rethinking Atrous Convolution for Semantic Image Segmentation,"
-Liang-Chieh Chen, George Papandreou, Florian Schroff, Hartwig Adam
-(https://arxiv.org/abs/1706.05587)
-
-"DeepLab: Semantic Image Segmentation with Deep Convolutional Nets,
-Atrous Convolution, and Fully Connected CRFs",
-Liang-Chieh Chen*, George Papandreou*, Iasonas Kokkinos, Kevin Murphy,
-Alan L Yuille (* equal contribution)
-(https://arxiv.org/abs/1606.00915)
-
-"Semantic Image Segmentation with Deep Convolutional Nets and Fully Connected
-CRFs"
-Liang-Chieh Chen*, George Papandreou*, Iasonas Kokkinos, Kevin Murphy,
-Alan L. Yuille (* equal contribution)
-(https://arxiv.org/abs/1412.7062)
-"""
-import collections
-import tensorflow as tf
-
-from deeplab import model
-from feelvos import common
-from feelvos.utils import embedding_utils
-from feelvos.utils import train_utils
-
-slim = tf.contrib.slim
-
-
-get_branch_logits = model.get_branch_logits
-get_extra_layer_scopes = model.get_extra_layer_scopes
-multi_scale_logits_v2 = model.multi_scale_logits
-refine_by_decoder = model.refine_by_decoder
-scale_dimension = model.scale_dimension
-split_separable_conv2d = model.split_separable_conv2d
-
-MERGED_LOGITS_SCOPE = model.MERGED_LOGITS_SCOPE
-IMAGE_POOLING_SCOPE = model.IMAGE_POOLING_SCOPE
-ASPP_SCOPE = model.ASPP_SCOPE
-CONCAT_PROJECTION_SCOPE = model.CONCAT_PROJECTION_SCOPE
-
-
-def predict_labels(images,
- model_options,
- image_pyramid=None,
- reference_labels=None,
- k_nearest_neighbors=1,
- embedding_dimension=None,
- use_softmax_feedback=False,
- initial_softmax_feedback=None,
- embedding_seg_feature_dimension=256,
- embedding_seg_n_layers=4,
- embedding_seg_kernel_size=7,
- embedding_seg_atrous_rates=None,
- also_return_softmax_probabilities=False,
- num_frames_per_video=None,
- normalize_nearest_neighbor_distances=False,
- also_attend_to_previous_frame=False,
- use_local_previous_frame_attention=False,
- previous_frame_attention_window_size=9,
- use_first_frame_matching=True,
- also_return_embeddings=False,
- ref_embeddings=None):
- """Predicts segmentation labels.
-
- Args:
- images: A tensor of size [batch, height, width, channels].
- model_options: An InternalModelOptions instance to configure models.
- image_pyramid: Input image scales for multi-scale feature extraction.
- reference_labels: A tensor of size [batch, height, width, 1].
- ground truth labels used to perform a nearest neighbor query
- k_nearest_neighbors: Integer, the number of neighbors to use for nearest
- neighbor queries.
- embedding_dimension: Integer, the dimension used for the learned embedding.
- use_softmax_feedback: Boolean, whether to give the softmax predictions of
- the last frame as additional input to the segmentation head.
- initial_softmax_feedback: Float32 tensor, or None. Can be used to
- initialize the softmax predictions used for the feedback loop.
- Typically only useful for inference. Only has an effect if
- use_softmax_feedback is True.
- embedding_seg_feature_dimension: Integer, the dimensionality used in the
- segmentation head layers.
- embedding_seg_n_layers: Integer, the number of layers in the segmentation
- head.
- embedding_seg_kernel_size: Integer, the kernel size used in the
- segmentation head.
- embedding_seg_atrous_rates: List of integers of length
- embedding_seg_n_layers, the atrous rates to use for the segmentation head.
- also_return_softmax_probabilities: Boolean, if true, additionally return
- the softmax probabilities as second return value.
- num_frames_per_video: Integer, the number of frames per video.
- normalize_nearest_neighbor_distances: Boolean, whether to normalize the
- nearest neighbor distances to [0,1] using sigmoid, scale and shift.
- also_attend_to_previous_frame: Boolean, whether to also use nearest
- neighbor attention with respect to the previous frame.
- use_local_previous_frame_attention: Boolean, whether to restrict the
- previous frame attention to a local search window.
- Only has an effect, if also_attend_to_previous_frame is True.
- previous_frame_attention_window_size: Integer, the window size used for
- local previous frame attention, if use_local_previous_frame_attention
- is True.
- use_first_frame_matching: Boolean, whether to extract features by matching
- to the reference frame. This should always be true except for ablation
- experiments.
- also_return_embeddings: Boolean, whether to return the embeddings as well.
- ref_embeddings: Tuple of
- (first_frame_embeddings, previous_frame_embeddings),
- each of shape [batch, height, width, embedding_dimension], or None.
-
- Returns:
- A dictionary with keys specifying the output_type (e.g., semantic
- prediction) and values storing Tensors representing predictions (argmax
- over channels). Each prediction has size [batch, height, width].
- If also_return_softmax_probabilities is True, the second return value are
- the softmax probabilities.
- If also_return_embeddings is True, it will also return an embeddings
- tensor of shape [batch, height, width, embedding_dimension].
-
- Raises:
- ValueError: If classification_loss is not softmax, softmax_with_attention,
- nor triplet.
- """
- if (model_options.classification_loss == 'triplet' and
- reference_labels is None):
- raise ValueError('Need reference_labels for triplet loss')
-
- if model_options.classification_loss == 'softmax_with_attention':
- if embedding_dimension is None:
- raise ValueError('Need embedding_dimension for softmax_with_attention '
- 'loss')
- if reference_labels is None:
- raise ValueError('Need reference_labels for softmax_with_attention loss')
- res = (
- multi_scale_logits_with_nearest_neighbor_matching(
- images,
- model_options=model_options,
- image_pyramid=image_pyramid,
- is_training=False,
- reference_labels=reference_labels,
- clone_batch_size=1,
- num_frames_per_video=num_frames_per_video,
- embedding_dimension=embedding_dimension,
- max_neighbors_per_object=0,
- k_nearest_neighbors=k_nearest_neighbors,
- use_softmax_feedback=use_softmax_feedback,
- initial_softmax_feedback=initial_softmax_feedback,
- embedding_seg_feature_dimension=embedding_seg_feature_dimension,
- embedding_seg_n_layers=embedding_seg_n_layers,
- embedding_seg_kernel_size=embedding_seg_kernel_size,
- embedding_seg_atrous_rates=embedding_seg_atrous_rates,
- normalize_nearest_neighbor_distances=
- normalize_nearest_neighbor_distances,
- also_attend_to_previous_frame=also_attend_to_previous_frame,
- use_local_previous_frame_attention=
- use_local_previous_frame_attention,
- previous_frame_attention_window_size=
- previous_frame_attention_window_size,
- use_first_frame_matching=use_first_frame_matching,
- also_return_embeddings=also_return_embeddings,
- ref_embeddings=ref_embeddings
- ))
- if also_return_embeddings:
- outputs_to_scales_to_logits, embeddings = res
- else:
- outputs_to_scales_to_logits = res
- embeddings = None
- else:
- outputs_to_scales_to_logits = multi_scale_logits_v2(
- images,
- model_options=model_options,
- image_pyramid=image_pyramid,
- is_training=False,
- fine_tune_batch_norm=False)
-
- predictions = {}
- for output in sorted(outputs_to_scales_to_logits):
- scales_to_logits = outputs_to_scales_to_logits[output]
- original_logits = scales_to_logits[MERGED_LOGITS_SCOPE]
- if isinstance(original_logits, list):
- assert len(original_logits) == 1
- original_logits = original_logits[0]
- logits = tf.image.resize_bilinear(original_logits, tf.shape(images)[1:3],
- align_corners=True)
- if model_options.classification_loss in ('softmax',
- 'softmax_with_attention'):
- predictions[output] = tf.argmax(logits, 3)
- elif model_options.classification_loss == 'triplet':
- # to keep this fast, we do the nearest neighbor assignment on the
- # resolution at which the embedding is extracted and scale the result up
- # afterwards
- embeddings = original_logits
- reference_labels_logits_size = tf.squeeze(
- tf.image.resize_nearest_neighbor(
- reference_labels[tf.newaxis],
- train_utils.resolve_shape(embeddings)[1:3],
- align_corners=True), axis=0)
- nn_labels = embedding_utils.assign_labels_by_nearest_neighbors(
- embeddings[0], embeddings[1:], reference_labels_logits_size,
- k_nearest_neighbors)
- predictions[common.OUTPUT_TYPE] = tf.image.resize_nearest_neighbor(
- nn_labels, tf.shape(images)[1:3], align_corners=True)
- else:
- raise ValueError(
- 'Only support softmax, triplet, or softmax_with_attention for '
- 'classification_loss.')
-
- if also_return_embeddings:
- assert also_return_softmax_probabilities
- return predictions, tf.nn.softmax(original_logits, axis=-1), embeddings
- elif also_return_softmax_probabilities:
- return predictions, tf.nn.softmax(original_logits, axis=-1)
- else:
- return predictions
-
-
-def multi_scale_logits_with_nearest_neighbor_matching(
- images,
- model_options,
- image_pyramid,
- clone_batch_size,
- reference_labels,
- num_frames_per_video,
- embedding_dimension,
- max_neighbors_per_object,
- weight_decay=0.0001,
- is_training=False,
- fine_tune_batch_norm=False,
- k_nearest_neighbors=1,
- use_softmax_feedback=False,
- initial_softmax_feedback=None,
- embedding_seg_feature_dimension=256,
- embedding_seg_n_layers=4,
- embedding_seg_kernel_size=7,
- embedding_seg_atrous_rates=None,
- normalize_nearest_neighbor_distances=False,
- also_attend_to_previous_frame=False,
- damage_initial_previous_frame_mask=False,
- use_local_previous_frame_attention=False,
- previous_frame_attention_window_size=9,
- use_first_frame_matching=True,
- also_return_embeddings=False,
- ref_embeddings=None):
- """Gets the logits for multi-scale inputs using nearest neighbor attention.
-
- Adjusted version of multi_scale_logits_v2 to support nearest neighbor
- attention and a variable number of classes for each element of the batch.
- The returned logits are all downsampled (due to max-pooling layers)
- for both training and evaluation.
-
- Args:
- images: A tensor of size [batch, height, width, channels].
- model_options: A ModelOptions instance to configure models.
- image_pyramid: Input image scales for multi-scale feature extraction.
- clone_batch_size: Integer, the number of videos on a batch.
- reference_labels: The segmentation labels of the reference frame on which
- attention is applied.
- num_frames_per_video: Integer, the number of frames per video.
- embedding_dimension: Integer, the dimension of the embedding.
- max_neighbors_per_object: Integer, the maximum number of candidates
- for the nearest neighbor query per object after subsampling.
- Can be 0 for no subsampling.
- weight_decay: The weight decay for model variables.
- is_training: Is training or not.
- fine_tune_batch_norm: Fine-tune the batch norm parameters or not.
- k_nearest_neighbors: Integer, the number of nearest neighbors to use.
- use_softmax_feedback: Boolean, whether to give the softmax predictions of
- the last frame as additional input to the segmentation head.
- initial_softmax_feedback: List of Float32 tensors, or None.
- Can be used to initialize the softmax predictions used for the feedback
- loop. Only has an effect if use_softmax_feedback is True.
- embedding_seg_feature_dimension: Integer, the dimensionality used in the
- segmentation head layers.
- embedding_seg_n_layers: Integer, the number of layers in the segmentation
- head.
- embedding_seg_kernel_size: Integer, the kernel size used in the
- segmentation head.
- embedding_seg_atrous_rates: List of integers of length
- embedding_seg_n_layers, the atrous rates to use for the segmentation head.
- normalize_nearest_neighbor_distances: Boolean, whether to normalize the
- nearest neighbor distances to [0,1] using sigmoid, scale and shift.
- also_attend_to_previous_frame: Boolean, whether to also use nearest
- neighbor attention with respect to the previous frame.
- damage_initial_previous_frame_mask: Boolean, whether to artificially damage
- the initial previous frame mask. Only has an effect if
- also_attend_to_previous_frame is True.
- use_local_previous_frame_attention: Boolean, whether to restrict the
- previous frame attention to a local search window.
- Only has an effect, if also_attend_to_previous_frame is True.
- previous_frame_attention_window_size: Integer, the window size used for
- local previous frame attention, if use_local_previous_frame_attention
- is True.
- use_first_frame_matching: Boolean, whether to extract features by matching
- to the reference frame. This should always be true except for ablation
- experiments.
- also_return_embeddings: Boolean, whether to return the embeddings as well.
- ref_embeddings: Tuple of
- (first_frame_embeddings, previous_frame_embeddings),
- each of shape [batch, height, width, embedding_dimension], or None.
-
- Returns:
- outputs_to_scales_to_logits: A map of maps from output_type (e.g.,
- semantic prediction) to a dictionary of multi-scale logits names to
- logits. For each output_type, the dictionary has keys which
- correspond to the scales and values which correspond to the logits.
- For example, if `scales` equals [1.0, 1.5], then the keys would
- include 'merged_logits', 'logits_1.00' and 'logits_1.50'.
- If also_return_embeddings is True, it will also return an embeddings
- tensor of shape [batch, height, width, embedding_dimension].
-
- Raises:
- ValueError: If model_options doesn't specify crop_size and its
- add_image_level_feature = True, since add_image_level_feature requires
- crop_size information.
- """
- # Setup default values.
- if not image_pyramid:
- image_pyramid = [1.0]
- crop_height = (
- model_options.crop_size[0]
- if model_options.crop_size else tf.shape(images)[1])
- crop_width = (
- model_options.crop_size[1]
- if model_options.crop_size else tf.shape(images)[2])
-
- # Compute the height, width for the output logits.
- if model_options.decoder_output_stride:
- logits_output_stride = min(model_options.decoder_output_stride)
- else:
- logits_output_stride = model_options.output_stride
- logits_height = scale_dimension(
- crop_height,
- max(1.0, max(image_pyramid)) / logits_output_stride)
- logits_width = scale_dimension(
- crop_width,
- max(1.0, max(image_pyramid)) / logits_output_stride)
-
- # Compute the logits for each scale in the image pyramid.
- outputs_to_scales_to_logits = {
- k: {}
- for k in model_options.outputs_to_num_classes
- }
-
- for image_scale in image_pyramid:
- if image_scale != 1.0:
- scaled_height = scale_dimension(crop_height, image_scale)
- scaled_width = scale_dimension(crop_width, image_scale)
- scaled_crop_size = [scaled_height, scaled_width]
- scaled_images = tf.image.resize_bilinear(
- images, scaled_crop_size, align_corners=True)
- scaled_reference_labels = tf.image.resize_nearest_neighbor(
- reference_labels, scaled_crop_size, align_corners=True
- )
- if model_options.crop_size is None:
- scaled_crop_size = None
- if model_options.crop_size:
- scaled_images.set_shape([None, scaled_height, scaled_width, 3])
- else:
- scaled_crop_size = model_options.crop_size
- scaled_images = images
- scaled_reference_labels = reference_labels
-
- updated_options = model_options._replace(crop_size=scaled_crop_size)
- res = embedding_utils.get_logits_with_matching(
- scaled_images,
- updated_options,
- weight_decay=weight_decay,
- reuse=tf.AUTO_REUSE,
- is_training=is_training,
- fine_tune_batch_norm=fine_tune_batch_norm,
- reference_labels=scaled_reference_labels,
- batch_size=clone_batch_size,
- num_frames_per_video=num_frames_per_video,
- embedding_dimension=embedding_dimension,
- max_neighbors_per_object=max_neighbors_per_object,
- k_nearest_neighbors=k_nearest_neighbors,
- use_softmax_feedback=use_softmax_feedback,
- initial_softmax_feedback=initial_softmax_feedback,
- embedding_seg_feature_dimension=embedding_seg_feature_dimension,
- embedding_seg_n_layers=embedding_seg_n_layers,
- embedding_seg_kernel_size=embedding_seg_kernel_size,
- embedding_seg_atrous_rates=embedding_seg_atrous_rates,
- normalize_nearest_neighbor_distances=
- normalize_nearest_neighbor_distances,
- also_attend_to_previous_frame=also_attend_to_previous_frame,
- damage_initial_previous_frame_mask=damage_initial_previous_frame_mask,
- use_local_previous_frame_attention=use_local_previous_frame_attention,
- previous_frame_attention_window_size=
- previous_frame_attention_window_size,
- use_first_frame_matching=use_first_frame_matching,
- also_return_embeddings=also_return_embeddings,
- ref_embeddings=ref_embeddings
- )
- if also_return_embeddings:
- outputs_to_logits, embeddings = res
- else:
- outputs_to_logits = res
- embeddings = None
-
- # Resize the logits to have the same dimension before merging.
- for output in sorted(outputs_to_logits):
- if isinstance(outputs_to_logits[output], collections.Sequence):
- outputs_to_logits[output] = [tf.image.resize_bilinear(
- x, [logits_height, logits_width], align_corners=True)
- for x in outputs_to_logits[output]]
- else:
- outputs_to_logits[output] = tf.image.resize_bilinear(
- outputs_to_logits[output], [logits_height, logits_width],
- align_corners=True)
-
- # Return when only one input scale.
- if len(image_pyramid) == 1:
- for output in sorted(model_options.outputs_to_num_classes):
- outputs_to_scales_to_logits[output][
- MERGED_LOGITS_SCOPE] = outputs_to_logits[output]
- if also_return_embeddings:
- return outputs_to_scales_to_logits, embeddings
- else:
- return outputs_to_scales_to_logits
-
- # Save logits to the output map.
- for output in sorted(model_options.outputs_to_num_classes):
- outputs_to_scales_to_logits[output][
- 'logits_%.2f' % image_scale] = outputs_to_logits[output]
-
- # Merge the logits from all the multi-scale inputs.
- for output in sorted(model_options.outputs_to_num_classes):
- # Concatenate the multi-scale logits for each output type.
- all_logits = [
- [tf.expand_dims(l, axis=4)]
- for logits in outputs_to_scales_to_logits[output].values()
- for l in logits
- ]
- transposed = map(list, zip(*all_logits))
- all_logits = [tf.concat(t, 4) for t in transposed]
- merge_fn = (
- tf.reduce_max
- if model_options.merge_method == 'max' else tf.reduce_mean)
- outputs_to_scales_to_logits[output][MERGED_LOGITS_SCOPE] = [merge_fn(
- l, axis=4) for l in all_logits]
-
- if also_return_embeddings:
- return outputs_to_scales_to_logits, embeddings
- else:
- return outputs_to_scales_to_logits
diff --git a/research/feelvos/train.py b/research/feelvos/train.py
deleted file mode 100644
index 16c085722749bcfde5aeff15cdbec336e5efe451..0000000000000000000000000000000000000000
--- a/research/feelvos/train.py
+++ /dev/null
@@ -1,630 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Training script for the FEELVOS model.
-
-See model.py for more details and usage.
-"""
-import six
-import tensorflow as tf
-
-from feelvos import common
-from feelvos import model
-from feelvos.datasets import video_dataset
-from feelvos.utils import embedding_utils
-from feelvos.utils import train_utils
-from feelvos.utils import video_input_generator
-from deployment import model_deploy
-
-slim = tf.contrib.slim
-prefetch_queue = slim.prefetch_queue
-flags = tf.app.flags
-FLAGS = flags.FLAGS
-
-# Settings for multi-GPUs/multi-replicas training.
-
-flags.DEFINE_integer('num_clones', 1, 'Number of clones to deploy.')
-
-flags.DEFINE_boolean('clone_on_cpu', False, 'Use CPUs to deploy clones.')
-
-flags.DEFINE_integer('num_replicas', 1, 'Number of worker replicas.')
-
-flags.DEFINE_integer('startup_delay_steps', 15,
- 'Number of training steps between replicas startup.')
-
-flags.DEFINE_integer('num_ps_tasks', 0,
- 'The number of parameter servers. If the value is 0, then '
- 'the parameters are handled locally by the worker.')
-
-flags.DEFINE_string('master', '', 'BNS name of the tensorflow server')
-
-flags.DEFINE_integer('task', 0, 'The task ID.')
-
-# Settings for logging.
-
-flags.DEFINE_string('train_logdir', None,
- 'Where the checkpoint and logs are stored.')
-
-flags.DEFINE_integer('log_steps', 10,
- 'Display logging information at every log_steps.')
-
-flags.DEFINE_integer('save_interval_secs', 1200,
- 'How often, in seconds, we save the model to disk.')
-
-flags.DEFINE_integer('save_summaries_secs', 600,
- 'How often, in seconds, we compute the summaries.')
-
-# Settings for training strategy.
-
-flags.DEFINE_enum('learning_policy', 'poly', ['poly', 'step'],
- 'Learning rate policy for training.')
-
-flags.DEFINE_float('base_learning_rate', 0.0007,
- 'The base learning rate for model training.')
-
-flags.DEFINE_float('learning_rate_decay_factor', 0.1,
- 'The rate to decay the base learning rate.')
-
-flags.DEFINE_integer('learning_rate_decay_step', 2000,
- 'Decay the base learning rate at a fixed step.')
-
-flags.DEFINE_float('learning_power', 0.9,
- 'The power value used in the poly learning policy.')
-
-flags.DEFINE_integer('training_number_of_steps', 200000,
- 'The number of steps used for training')
-
-flags.DEFINE_float('momentum', 0.9, 'The momentum value to use')
-
-flags.DEFINE_integer('train_batch_size', 6,
- 'The number of images in each batch during training.')
-
-flags.DEFINE_integer('train_num_frames_per_video', 3,
- 'The number of frames used per video during training')
-
-flags.DEFINE_float('weight_decay', 0.00004,
- 'The value of the weight decay for training.')
-
-flags.DEFINE_multi_integer('train_crop_size', [465, 465],
- 'Image crop size [height, width] during training.')
-
-flags.DEFINE_float('last_layer_gradient_multiplier', 1.0,
- 'The gradient multiplier for last layers, which is used to '
- 'boost the gradient of last layers if the value > 1.')
-
-flags.DEFINE_boolean('upsample_logits', True,
- 'Upsample logits during training.')
-
-flags.DEFINE_integer('batch_capacity_factor', 16, 'Batch capacity factor.')
-
-flags.DEFINE_integer('num_readers', 1, 'Number of readers for data provider.')
-
-flags.DEFINE_integer('batch_num_threads', 1, 'Batch number of threads.')
-
-flags.DEFINE_integer('prefetch_queue_capacity_factor', 32,
- 'Prefetch queue capacity factor.')
-
-flags.DEFINE_integer('prefetch_queue_num_threads', 1,
- 'Prefetch queue number of threads.')
-
-flags.DEFINE_integer('train_max_neighbors_per_object', 1024,
- 'The maximum number of candidates for the nearest '
- 'neighbor query per object after subsampling')
-
-# Settings for fine-tuning the network.
-
-flags.DEFINE_string('tf_initial_checkpoint', None,
- 'The initial checkpoint in tensorflow format.')
-
-flags.DEFINE_boolean('initialize_last_layer', False,
- 'Initialize the last layer.')
-
-flags.DEFINE_boolean('last_layers_contain_logits_only', False,
- 'Only consider logits as last layers or not.')
-
-flags.DEFINE_integer('slow_start_step', 0,
- 'Training model with small learning rate for few steps.')
-
-flags.DEFINE_float('slow_start_learning_rate', 1e-4,
- 'Learning rate employed during slow start.')
-
-flags.DEFINE_boolean('fine_tune_batch_norm', False,
- 'Fine tune the batch norm parameters or not.')
-
-flags.DEFINE_float('min_scale_factor', 1.,
- 'Mininum scale factor for data augmentation.')
-
-flags.DEFINE_float('max_scale_factor', 1.3,
- 'Maximum scale factor for data augmentation.')
-
-flags.DEFINE_float('scale_factor_step_size', 0,
- 'Scale factor step size for data augmentation.')
-
-flags.DEFINE_multi_integer('atrous_rates', None,
- 'Atrous rates for atrous spatial pyramid pooling.')
-
-flags.DEFINE_integer('output_stride', 8,
- 'The ratio of input to output spatial resolution.')
-
-flags.DEFINE_boolean('sample_only_first_frame_for_finetuning', False,
- 'Whether to only sample the first frame during '
- 'fine-tuning. This should be False when using lucid data, '
- 'but True when fine-tuning on the first frame only. Only '
- 'has an effect if first_frame_finetuning is True.')
-
-flags.DEFINE_multi_integer('first_frame_finetuning', [0],
- 'Whether to only sample the first frame for '
- 'fine-tuning.')
-
-# Dataset settings.
-
-flags.DEFINE_multi_string('dataset', [], 'Name of the segmentation datasets.')
-
-flags.DEFINE_multi_float('dataset_sampling_probabilities', [],
- 'A list of probabilities to sample each of the '
- 'datasets.')
-
-flags.DEFINE_string('train_split', 'train',
- 'Which split of the dataset to be used for training')
-
-flags.DEFINE_multi_string('dataset_dir', [], 'Where the datasets reside.')
-
-flags.DEFINE_multi_integer('three_frame_dataset', [0],
- 'Whether the dataset has exactly three frames per '
- 'video of which the first is to be used as reference'
- ' and the two others are consecutive frames to be '
- 'used as query frames.'
- 'Set true for pascal lucid data.')
-
-flags.DEFINE_boolean('damage_initial_previous_frame_mask', False,
- 'Whether to artificially damage the initial previous '
- 'frame mask. Only has an effect if '
- 'also_attend_to_previous_frame is True.')
-
-flags.DEFINE_float('top_k_percent_pixels', 0.15, 'Float in [0.0, 1.0].'
- 'When its value < 1.0, only compute the loss for the top k'
- 'percent pixels (e.g., the top 20% pixels). This is useful'
- 'for hard pixel mining.')
-
-flags.DEFINE_integer('hard_example_mining_step', 100000,
- 'The training step in which the hard exampling mining '
- 'kicks off. Note that we gradually reduce the mining '
- 'percent to the top_k_percent_pixels. For example, if '
- 'hard_example_mining_step=100K and '
- 'top_k_percent_pixels=0.25, then mining percent will '
- 'gradually reduce from 100% to 25% until 100K steps '
- 'after which we only mine top 25% pixels. Only has an '
- 'effect if top_k_percent_pixels < 1.0')
-
-
-def _build_deeplab(inputs_queue_or_samples, outputs_to_num_classes,
- ignore_label):
- """Builds a clone of DeepLab.
-
- Args:
- inputs_queue_or_samples: A prefetch queue for images and labels, or
- directly a dict of the samples.
- outputs_to_num_classes: A map from output type to the number of classes.
- For example, for the task of semantic segmentation with 21 semantic
- classes, we would have outputs_to_num_classes['semantic'] = 21.
- ignore_label: Ignore label.
-
- Returns:
- A map of maps from output_type (e.g., semantic prediction) to a
- dictionary of multi-scale logits names to logits. For each output_type,
- the dictionary has keys which correspond to the scales and values which
- correspond to the logits. For example, if `scales` equals [1.0, 1.5],
- then the keys would include 'merged_logits', 'logits_1.00' and
- 'logits_1.50'.
-
- Raises:
- ValueError: If classification_loss is not softmax, softmax_with_attention,
- or triplet.
- """
- if hasattr(inputs_queue_or_samples, 'dequeue'):
- samples = inputs_queue_or_samples.dequeue()
- else:
- samples = inputs_queue_or_samples
- train_crop_size = (None if 0 in FLAGS.train_crop_size else
- FLAGS.train_crop_size)
-
- model_options = common.VideoModelOptions(
- outputs_to_num_classes=outputs_to_num_classes,
- crop_size=train_crop_size,
- atrous_rates=FLAGS.atrous_rates,
- output_stride=FLAGS.output_stride)
-
- if model_options.classification_loss == 'softmax_with_attention':
- clone_batch_size = FLAGS.train_batch_size // FLAGS.num_clones
-
- # Create summaries of ground truth labels.
- for n in range(clone_batch_size):
- tf.summary.image(
- 'gt_label_%d' % n,
- tf.cast(samples[common.LABEL][
- n * FLAGS.train_num_frames_per_video:
- (n + 1) * FLAGS.train_num_frames_per_video],
- tf.uint8) * 32, max_outputs=FLAGS.train_num_frames_per_video)
-
- if common.PRECEDING_FRAME_LABEL in samples:
- preceding_frame_label = samples[common.PRECEDING_FRAME_LABEL]
- init_softmax = []
- for n in range(clone_batch_size):
- init_softmax_n = embedding_utils.create_initial_softmax_from_labels(
- preceding_frame_label[n, tf.newaxis],
- samples[common.LABEL][n * FLAGS.train_num_frames_per_video,
- tf.newaxis],
- common.parse_decoder_output_stride(),
- reduce_labels=True)
- init_softmax_n = tf.squeeze(init_softmax_n, axis=0)
- init_softmax.append(init_softmax_n)
- tf.summary.image('preceding_frame_label',
- tf.cast(preceding_frame_label[n, tf.newaxis],
- tf.uint8) * 32)
- else:
- init_softmax = None
-
- outputs_to_scales_to_logits = (
- model.multi_scale_logits_with_nearest_neighbor_matching(
- samples[common.IMAGE],
- model_options=model_options,
- image_pyramid=FLAGS.image_pyramid,
- weight_decay=FLAGS.weight_decay,
- is_training=True,
- fine_tune_batch_norm=FLAGS.fine_tune_batch_norm,
- reference_labels=samples[common.LABEL],
- clone_batch_size=FLAGS.train_batch_size // FLAGS.num_clones,
- num_frames_per_video=FLAGS.train_num_frames_per_video,
- embedding_dimension=FLAGS.embedding_dimension,
- max_neighbors_per_object=FLAGS.train_max_neighbors_per_object,
- k_nearest_neighbors=FLAGS.k_nearest_neighbors,
- use_softmax_feedback=FLAGS.use_softmax_feedback,
- initial_softmax_feedback=init_softmax,
- embedding_seg_feature_dimension=
- FLAGS.embedding_seg_feature_dimension,
- embedding_seg_n_layers=FLAGS.embedding_seg_n_layers,
- embedding_seg_kernel_size=FLAGS.embedding_seg_kernel_size,
- embedding_seg_atrous_rates=FLAGS.embedding_seg_atrous_rates,
- normalize_nearest_neighbor_distances=
- FLAGS.normalize_nearest_neighbor_distances,
- also_attend_to_previous_frame=FLAGS.also_attend_to_previous_frame,
- damage_initial_previous_frame_mask=
- FLAGS.damage_initial_previous_frame_mask,
- use_local_previous_frame_attention=
- FLAGS.use_local_previous_frame_attention,
- previous_frame_attention_window_size=
- FLAGS.previous_frame_attention_window_size,
- use_first_frame_matching=FLAGS.use_first_frame_matching
- ))
- else:
- outputs_to_scales_to_logits = model.multi_scale_logits_v2(
- samples[common.IMAGE],
- model_options=model_options,
- image_pyramid=FLAGS.image_pyramid,
- weight_decay=FLAGS.weight_decay,
- is_training=True,
- fine_tune_batch_norm=FLAGS.fine_tune_batch_norm)
-
- if model_options.classification_loss == 'softmax':
- for output, num_classes in six.iteritems(outputs_to_num_classes):
- train_utils.add_softmax_cross_entropy_loss_for_each_scale(
- outputs_to_scales_to_logits[output],
- samples[common.LABEL],
- num_classes,
- ignore_label,
- loss_weight=1.0,
- upsample_logits=FLAGS.upsample_logits,
- scope=output)
- elif model_options.classification_loss == 'triplet':
- for output, _ in six.iteritems(outputs_to_num_classes):
- train_utils.add_triplet_loss_for_each_scale(
- FLAGS.train_batch_size // FLAGS.num_clones,
- FLAGS.train_num_frames_per_video,
- FLAGS.embedding_dimension, outputs_to_scales_to_logits[output],
- samples[common.LABEL], scope=output)
- elif model_options.classification_loss == 'softmax_with_attention':
- labels = samples[common.LABEL]
- batch_size = FLAGS.train_batch_size // FLAGS.num_clones
- num_frames_per_video = FLAGS.train_num_frames_per_video
- h, w = train_utils.resolve_shape(labels)[1:3]
- labels = tf.reshape(labels, tf.stack(
- [batch_size, num_frames_per_video, h, w, 1]))
- # Strip the reference labels off.
- if FLAGS.also_attend_to_previous_frame or FLAGS.use_softmax_feedback:
- n_ref_frames = 2
- else:
- n_ref_frames = 1
- labels = labels[:, n_ref_frames:]
- # Merge batch and time dimensions.
- labels = tf.reshape(labels, tf.stack(
- [batch_size * (num_frames_per_video - n_ref_frames), h, w, 1]))
-
- for output, num_classes in six.iteritems(outputs_to_num_classes):
- train_utils.add_dynamic_softmax_cross_entropy_loss_for_each_scale(
- outputs_to_scales_to_logits[output],
- labels,
- ignore_label,
- loss_weight=1.0,
- upsample_logits=FLAGS.upsample_logits,
- scope=output,
- top_k_percent_pixels=FLAGS.top_k_percent_pixels,
- hard_example_mining_step=FLAGS.hard_example_mining_step)
- else:
- raise ValueError('Only support softmax, softmax_with_attention'
- ' or triplet for classification_loss.')
-
- return outputs_to_scales_to_logits
-
-
-def main(unused_argv):
- # Set up deployment (i.e., multi-GPUs and/or multi-replicas).
- config = model_deploy.DeploymentConfig(
- num_clones=FLAGS.num_clones,
- clone_on_cpu=FLAGS.clone_on_cpu,
- replica_id=FLAGS.task,
- num_replicas=FLAGS.num_replicas,
- num_ps_tasks=FLAGS.num_ps_tasks)
-
- with tf.Graph().as_default():
- with tf.device(config.inputs_device()):
- train_crop_size = (None if 0 in FLAGS.train_crop_size else
- FLAGS.train_crop_size)
- assert FLAGS.dataset
- assert len(FLAGS.dataset) == len(FLAGS.dataset_dir)
- if len(FLAGS.first_frame_finetuning) == 1:
- first_frame_finetuning = (list(FLAGS.first_frame_finetuning)
- * len(FLAGS.dataset))
- else:
- first_frame_finetuning = FLAGS.first_frame_finetuning
- if len(FLAGS.three_frame_dataset) == 1:
- three_frame_dataset = (list(FLAGS.three_frame_dataset)
- * len(FLAGS.dataset))
- else:
- three_frame_dataset = FLAGS.three_frame_dataset
- assert len(FLAGS.dataset) == len(first_frame_finetuning)
- assert len(FLAGS.dataset) == len(three_frame_dataset)
- datasets, samples_list = zip(
- *[_get_dataset_and_samples(config, train_crop_size, dataset,
- dataset_dir, bool(first_frame_finetuning_),
- bool(three_frame_dataset_))
- for dataset, dataset_dir, first_frame_finetuning_,
- three_frame_dataset_ in zip(FLAGS.dataset, FLAGS.dataset_dir,
- first_frame_finetuning,
- three_frame_dataset)])
- # Note that this way of doing things is wasteful since it will evaluate
- # all branches but just use one of them. But let's do it anyway for now,
- # since it's easy and will probably be fast enough.
- dataset = datasets[0]
- if len(samples_list) == 1:
- samples = samples_list[0]
- else:
- probabilities = FLAGS.dataset_sampling_probabilities
- if probabilities:
- assert len(probabilities) == len(samples_list)
- else:
- # Default to uniform probabilities.
- probabilities = [1.0 / len(samples_list) for _ in samples_list]
- probabilities = tf.constant(probabilities)
- logits = tf.log(probabilities[tf.newaxis])
- rand_idx = tf.squeeze(tf.multinomial(logits, 1, output_dtype=tf.int32),
- axis=[0, 1])
-
- def wrap(x):
- def f():
- return x
- return f
-
- samples = tf.case({tf.equal(rand_idx, idx): wrap(s)
- for idx, s in enumerate(samples_list)},
- exclusive=True)
-
- # Prefetch_queue requires the shape to be known at graph creation time.
- # So we only use it if we crop to a fixed size.
- if train_crop_size is None:
- inputs_queue = samples
- else:
- inputs_queue = prefetch_queue.prefetch_queue(
- samples,
- capacity=FLAGS.prefetch_queue_capacity_factor*config.num_clones,
- num_threads=FLAGS.prefetch_queue_num_threads)
-
- # Create the global step on the device storing the variables.
- with tf.device(config.variables_device()):
- global_step = tf.train.get_or_create_global_step()
-
- # Define the model and create clones.
- model_fn = _build_deeplab
- if FLAGS.classification_loss == 'triplet':
- embedding_dim = FLAGS.embedding_dimension
- output_type_to_dim = {'embedding': embedding_dim}
- else:
- output_type_to_dim = {common.OUTPUT_TYPE: dataset.num_classes}
- model_args = (inputs_queue, output_type_to_dim, dataset.ignore_label)
- clones = model_deploy.create_clones(config, model_fn, args=model_args)
-
- # Gather update_ops from the first clone. These contain, for example,
- # the updates for the batch_norm variables created by model_fn.
- first_clone_scope = config.clone_scope(0)
- update_ops = tf.get_collection(tf.GraphKeys.UPDATE_OPS, first_clone_scope)
-
- # Gather initial summaries.
- summaries = set(tf.get_collection(tf.GraphKeys.SUMMARIES))
-
- # Add summaries for model variables.
- for model_var in tf.contrib.framework.get_model_variables():
- summaries.add(tf.summary.histogram(model_var.op.name, model_var))
-
- # Add summaries for losses.
- for loss in tf.get_collection(tf.GraphKeys.LOSSES, first_clone_scope):
- summaries.add(tf.summary.scalar('losses/%s' % loss.op.name, loss))
-
- # Build the optimizer based on the device specification.
- with tf.device(config.optimizer_device()):
- learning_rate = train_utils.get_model_learning_rate(
- FLAGS.learning_policy,
- FLAGS.base_learning_rate,
- FLAGS.learning_rate_decay_step,
- FLAGS.learning_rate_decay_factor,
- FLAGS.training_number_of_steps,
- FLAGS.learning_power,
- FLAGS.slow_start_step,
- FLAGS.slow_start_learning_rate)
- optimizer = tf.train.MomentumOptimizer(learning_rate, FLAGS.momentum)
- summaries.add(tf.summary.scalar('learning_rate', learning_rate))
-
- startup_delay_steps = FLAGS.task * FLAGS.startup_delay_steps
-
- with tf.device(config.variables_device()):
- total_loss, grads_and_vars = model_deploy.optimize_clones(
- clones, optimizer)
- total_loss = tf.check_numerics(total_loss, 'Loss is inf or nan.')
- summaries.add(tf.summary.scalar('total_loss', total_loss))
-
- # Modify the gradients for biases and last layer variables.
- last_layers = model.get_extra_layer_scopes(
- FLAGS.last_layers_contain_logits_only)
- grad_mult = train_utils.get_model_gradient_multipliers(
- last_layers, FLAGS.last_layer_gradient_multiplier)
- if grad_mult:
- grads_and_vars = slim.learning.multiply_gradients(grads_and_vars,
- grad_mult)
-
- with tf.name_scope('grad_clipping'):
- grads_and_vars = slim.learning.clip_gradient_norms(grads_and_vars, 5.0)
-
- # Create histogram summaries for the gradients.
- # We have too many summaries for mldash, so disable this one for now.
- # for grad, var in grads_and_vars:
- # summaries.add(tf.summary.histogram(
- # var.name.replace(':0', '_0') + '/gradient', grad))
-
- # Create gradient update op.
- grad_updates = optimizer.apply_gradients(grads_and_vars,
- global_step=global_step)
- update_ops.append(grad_updates)
- update_op = tf.group(*update_ops)
- with tf.control_dependencies([update_op]):
- train_tensor = tf.identity(total_loss, name='train_op')
-
- # Add the summaries from the first clone. These contain the summaries
- # created by model_fn and either optimize_clones() or _gather_clone_loss().
- summaries |= set(tf.get_collection(tf.GraphKeys.SUMMARIES,
- first_clone_scope))
-
- # Merge all summaries together.
- summary_op = tf.summary.merge(list(summaries))
-
- # Soft placement allows placing on CPU ops without GPU implementation.
- session_config = tf.ConfigProto(allow_soft_placement=True,
- log_device_placement=False)
-
- # Start the training.
- slim.learning.train(
- train_tensor,
- logdir=FLAGS.train_logdir,
- log_every_n_steps=FLAGS.log_steps,
- master=FLAGS.master,
- number_of_steps=FLAGS.training_number_of_steps,
- is_chief=(FLAGS.task == 0),
- session_config=session_config,
- startup_delay_steps=startup_delay_steps,
- init_fn=train_utils.get_model_init_fn(FLAGS.train_logdir,
- FLAGS.tf_initial_checkpoint,
- FLAGS.initialize_last_layer,
- last_layers,
- ignore_missing_vars=True),
- summary_op=summary_op,
- save_summaries_secs=FLAGS.save_summaries_secs,
- save_interval_secs=FLAGS.save_interval_secs)
-
-
-def _get_dataset_and_samples(config, train_crop_size, dataset_name,
- dataset_dir, first_frame_finetuning,
- three_frame_dataset):
- """Creates dataset object and samples dict of tensor.
-
- Args:
- config: A DeploymentConfig.
- train_crop_size: Integer, the crop size used for training.
- dataset_name: String, the name of the dataset.
- dataset_dir: String, the directory of the dataset.
- first_frame_finetuning: Boolean, whether the used dataset is a dataset
- for first frame fine-tuning.
- three_frame_dataset: Boolean, whether the dataset has exactly three frames
- per video of which the first is to be used as reference and the two
- others are consecutive frames to be used as query frames.
-
- Returns:
- dataset: An instance of slim Dataset.
- samples: A dictionary of tensors for semantic segmentation.
- """
-
- # Split the batch across GPUs.
- assert FLAGS.train_batch_size % config.num_clones == 0, (
- 'Training batch size not divisble by number of clones (GPUs).')
-
- clone_batch_size = FLAGS.train_batch_size / config.num_clones
-
- if first_frame_finetuning:
- train_split = 'val'
- else:
- train_split = FLAGS.train_split
-
- data_type = 'tf_sequence_example'
- # Get dataset-dependent information.
- dataset = video_dataset.get_dataset(
- dataset_name,
- train_split,
- dataset_dir=dataset_dir,
- data_type=data_type)
-
- tf.gfile.MakeDirs(FLAGS.train_logdir)
- tf.logging.info('Training on %s set', train_split)
-
- samples = video_input_generator.get(
- dataset,
- FLAGS.train_num_frames_per_video,
- train_crop_size,
- clone_batch_size,
- num_readers=FLAGS.num_readers,
- num_threads=FLAGS.batch_num_threads,
- min_resize_value=FLAGS.min_resize_value,
- max_resize_value=FLAGS.max_resize_value,
- resize_factor=FLAGS.resize_factor,
- min_scale_factor=FLAGS.min_scale_factor,
- max_scale_factor=FLAGS.max_scale_factor,
- scale_factor_step_size=FLAGS.scale_factor_step_size,
- dataset_split=FLAGS.train_split,
- is_training=True,
- model_variant=FLAGS.model_variant,
- batch_capacity_factor=FLAGS.batch_capacity_factor,
- decoder_output_stride=common.parse_decoder_output_stride(),
- first_frame_finetuning=first_frame_finetuning,
- sample_only_first_frame_for_finetuning=
- FLAGS.sample_only_first_frame_for_finetuning,
- sample_adjacent_and_consistent_query_frames=
- FLAGS.sample_adjacent_and_consistent_query_frames or
- FLAGS.use_softmax_feedback,
- remap_labels_to_reference_frame=True,
- three_frame_dataset=three_frame_dataset,
- add_prev_frame_label=not FLAGS.also_attend_to_previous_frame
- )
- return dataset, samples
-
-
-if __name__ == '__main__':
- flags.mark_flag_as_required('train_logdir')
- tf.logging.set_verbosity(tf.logging.INFO)
- tf.app.run()
diff --git a/research/feelvos/train.sh b/research/feelvos/train.sh
deleted file mode 100755
index 63b7ea19d4c53dea932322c3885abb9a95237e0c..0000000000000000000000000000000000000000
--- a/research/feelvos/train.sh
+++ /dev/null
@@ -1,92 +0,0 @@
-#!/bin/bash
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-#
-# This script is used to run local training on DAVIS 2017. Users could also
-# modify from this script for their use case. See eval.sh for an example of
-# local inference with a pre-trained model.
-#
-# Note that this script runs local training with a single GPU and a smaller crop
-# and batch size, while in the paper, we trained our models with 16 GPUS with
-# --num_clones=2, --train_batch_size=6, --num_replicas=8,
-# --training_number_of_steps=200000, --train_crop_size=465,
-# --train_crop_size=465.
-#
-# Usage:
-# # From the tensorflow/models/research/feelvos directory.
-# sh ./train.sh
-#
-#
-
-# Exit immediately if a command exits with a non-zero status.
-set -e
-
-# Move one-level up to tensorflow/models/research directory.
-cd ..
-
-# Update PYTHONPATH.
-export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim:`pwd`/feelvos
-
-# Set up the working environment.
-CURRENT_DIR=$(pwd)
-WORK_DIR="${CURRENT_DIR}/feelvos"
-
-# Set up the working directories.
-DATASET_DIR="datasets"
-DAVIS_FOLDER="davis17"
-DAVIS_DATASET="${WORK_DIR}/${DATASET_DIR}/${DAVIS_FOLDER}/tfrecord"
-EXP_FOLDER="exp/train"
-TRAIN_LOGDIR="${WORK_DIR}/${DATASET_DIR}/${DAVIS_FOLDER}/${EXP_FOLDER}/train"
-mkdir -p ${TRAIN_LOGDIR}
-
-# Go to datasets folder and download and convert the DAVIS 2017 dataset.
-DATASET_DIR="datasets"
-cd "${WORK_DIR}/${DATASET_DIR}"
-sh download_and_convert_davis17.sh
-
-# Go to models folder and download and unpack the COCO pre-trained model.
-MODELS_DIR="models"
-mkdir -p "${WORK_DIR}/${MODELS_DIR}"
-cd "${WORK_DIR}/${MODELS_DIR}"
-if [ ! -d "xception_65_coco_pretrained" ]; then
- wget http://download.tensorflow.org/models/xception_65_coco_pretrained_2018_10_02.tar.gz
- tar -xvf xception_65_coco_pretrained_2018_10_02.tar.gz
- rm xception_65_coco_pretrained_2018_10_02.tar.gz
-fi
-INIT_CKPT="${WORK_DIR}/${MODELS_DIR}/xception_65_coco_pretrained/x65-b2u1s2p-d48-2-3x256-sc-cr300k_init.ckpt"
-
-# Go back to orignal directory.
-cd "${CURRENT_DIR}"
-
-python "${WORK_DIR}"/train.py \
- --dataset=davis_2017 \
- --dataset_dir="${DAVIS_DATASET}" \
- --train_logdir="${TRAIN_LOGDIR}" \
- --tf_initial_checkpoint="${INIT_CKPT}" \
- --logtostderr \
- --atrous_rates=6 \
- --atrous_rates=12 \
- --atrous_rates=18 \
- --decoder_output_stride=4 \
- --model_variant=xception_65 \
- --multi_grid=1 \
- --multi_grid=1 \
- --multi_grid=1 \
- --output_stride=16 \
- --weight_decay=0.00004 \
- --num_clones=1 \
- --train_batch_size=1 \
- --train_crop_size=300 \
- --train_crop_size=300
diff --git a/research/feelvos/utils/__init__.py b/research/feelvos/utils/__init__.py
deleted file mode 100644
index 6f1373443d0ff84fd90714e41dade400ab41a22c..0000000000000000000000000000000000000000
--- a/research/feelvos/utils/__init__.py
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
diff --git a/research/feelvos/utils/embedding_utils.py b/research/feelvos/utils/embedding_utils.py
deleted file mode 100644
index 233c70d9327d08251537c58821dd8405b42f0fe7..0000000000000000000000000000000000000000
--- a/research/feelvos/utils/embedding_utils.py
+++ /dev/null
@@ -1,1082 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Utilities for the instance embedding for segmentation."""
-
-import numpy as np
-import tensorflow as tf
-from deeplab import model
-from deeplab.core import preprocess_utils
-from feelvos.utils import mask_damaging
-
-slim = tf.contrib.slim
-resolve_shape = preprocess_utils.resolve_shape
-WRONG_LABEL_PADDING_DISTANCE = 1e20
-
-# With correlation_cost local matching will be much faster. But we provide a
-# slow fallback for convenience.
-USE_CORRELATION_COST = False
-if USE_CORRELATION_COST:
- # pylint: disable=g-import-not-at-top
- from correlation_cost.python.ops import correlation_cost_op
-
-
-def pairwise_distances(x, y):
- """Computes pairwise squared l2 distances between tensors x and y.
-
- Args:
- x: Tensor of shape [n, feature_dim].
- y: Tensor of shape [m, feature_dim].
-
- Returns:
- Float32 distances tensor of shape [n, m].
- """
- # d[i,j] = (x[i] - y[j]) * (x[i] - y[j])'
- # = sum(x[i]^2, 1) + sum(y[j]^2, 1) - 2 * x[i] * y[j]'
- xs = tf.reduce_sum(x * x, axis=1)[:, tf.newaxis]
- ys = tf.reduce_sum(y * y, axis=1)[tf.newaxis, :]
- d = xs + ys - 2 * tf.matmul(x, y, transpose_b=True)
- return d
-
-
-def pairwise_distances2(x, y):
- """Computes pairwise squared l2 distances between tensors x and y.
-
- Naive implementation, high memory use. Could be useful to test the more
- efficient implementation.
-
- Args:
- x: Tensor of shape [n, feature_dim].
- y: Tensor of shape [m, feature_dim].
-
- Returns:
- distances of shape [n, m].
- """
- return tf.reduce_sum(tf.squared_difference(
- x[:, tf.newaxis], y[tf.newaxis, :]), axis=-1)
-
-
-def cross_correlate(x, y, max_distance=9):
- """Efficiently computes the cross correlation of x and y.
-
- Optimized implementation using correlation_cost.
- Note that we do not normalize by the feature dimension.
-
- Args:
- x: Float32 tensor of shape [height, width, feature_dim].
- y: Float32 tensor of shape [height, width, feature_dim].
- max_distance: Integer, the maximum distance in pixel coordinates
- per dimension which is considered to be in the search window.
-
- Returns:
- Float32 tensor of shape [height, width, (2 * max_distance + 1) ** 2].
- """
- with tf.name_scope('cross_correlation'):
- corr = correlation_cost_op.correlation_cost(
- x[tf.newaxis], y[tf.newaxis], kernel_size=1,
- max_displacement=max_distance, stride_1=1, stride_2=1,
- pad=max_distance)
- corr = tf.squeeze(corr, axis=0)
- # This correlation implementation takes the mean over the feature_dim,
- # but we want sum here, so multiply by feature_dim.
- feature_dim = resolve_shape(x)[-1]
- corr *= feature_dim
- return corr
-
-
-def local_pairwise_distances(x, y, max_distance=9):
- """Computes pairwise squared l2 distances using a local search window.
-
- Optimized implementation using correlation_cost.
-
- Args:
- x: Float32 tensor of shape [height, width, feature_dim].
- y: Float32 tensor of shape [height, width, feature_dim].
- max_distance: Integer, the maximum distance in pixel coordinates
- per dimension which is considered to be in the search window.
-
- Returns:
- Float32 distances tensor of shape
- [height, width, (2 * max_distance + 1) ** 2].
- """
- with tf.name_scope('local_pairwise_distances'):
- # d[i,j] = (x[i] - y[j]) * (x[i] - y[j])'
- # = sum(x[i]^2, -1) + sum(y[j]^2, -1) - 2 * x[i] * y[j]'
- corr = cross_correlate(x, y, max_distance=max_distance)
- xs = tf.reduce_sum(x * x, axis=2)[..., tf.newaxis]
- ys = tf.reduce_sum(y * y, axis=2)[..., tf.newaxis]
- ones_ys = tf.ones_like(ys)
- ys = cross_correlate(ones_ys, ys, max_distance=max_distance)
- d = xs + ys - 2 * corr
- # Boundary should be set to Inf.
- boundary = tf.equal(
- cross_correlate(ones_ys, ones_ys, max_distance=max_distance), 0)
- d = tf.where(boundary, tf.fill(tf.shape(d), tf.constant(np.float('inf'))),
- d)
- return d
-
-
-def local_pairwise_distances2(x, y, max_distance=9):
- """Computes pairwise squared l2 distances using a local search window.
-
- Naive implementation using map_fn.
- Used as a slow fallback for when correlation_cost is not available.
-
- Args:
- x: Float32 tensor of shape [height, width, feature_dim].
- y: Float32 tensor of shape [height, width, feature_dim].
- max_distance: Integer, the maximum distance in pixel coordinates
- per dimension which is considered to be in the search window.
-
- Returns:
- Float32 distances tensor of shape
- [height, width, (2 * max_distance + 1) ** 2].
- """
- with tf.name_scope('local_pairwise_distances2'):
- padding_val = 1e20
- padded_y = tf.pad(y, [[max_distance, max_distance],
- [max_distance, max_distance], [0, 0]],
- constant_values=padding_val)
- height, width, _ = resolve_shape(x)
- dists = []
- for y_start in range(2 * max_distance + 1):
- y_end = y_start + height
- y_slice = padded_y[y_start:y_end]
- for x_start in range(2 * max_distance + 1):
- x_end = x_start + width
- offset_y = y_slice[:, x_start:x_end]
- dist = tf.reduce_sum(tf.squared_difference(x, offset_y), axis=2)
- dists.append(dist)
- dists = tf.stack(dists, axis=2)
- return dists
-
-
-def majority_vote(labels):
- """Performs a label majority vote along axis 1.
-
- Second try, hopefully this time more efficient.
- We assume that the labels are contiguous starting from 0.
- It will also work for non-contiguous labels, but be inefficient.
-
- Args:
- labels: Int tensor of shape [n, k]
-
- Returns:
- The majority of labels along axis 1
- """
- max_label = tf.reduce_max(labels)
- one_hot = tf.one_hot(labels, depth=max_label + 1)
- summed = tf.reduce_sum(one_hot, axis=1)
- majority = tf.argmax(summed, axis=1)
- return majority
-
-
-def assign_labels_by_nearest_neighbors(reference_embeddings, query_embeddings,
- reference_labels, k=1):
- """Segments by nearest neighbor query wrt the reference frame.
-
- Args:
- reference_embeddings: Tensor of shape [height, width, embedding_dim],
- the embedding vectors for the reference frame
- query_embeddings: Tensor of shape [n_query_images, height, width,
- embedding_dim], the embedding vectors for the query frames
- reference_labels: Tensor of shape [height, width, 1], the class labels of
- the reference frame
- k: Integer, the number of nearest neighbors to use
-
- Returns:
- The labels of the nearest neighbors as [n_query_frames, height, width, 1]
- tensor
-
- Raises:
- ValueError: If k < 1.
- """
- if k < 1:
- raise ValueError('k must be at least 1')
- dists = flattened_pairwise_distances(reference_embeddings, query_embeddings)
- if k == 1:
- nn_indices = tf.argmin(dists, axis=1)[..., tf.newaxis]
- else:
- _, nn_indices = tf.nn.top_k(-dists, k, sorted=False)
- reference_labels = tf.reshape(reference_labels, [-1])
- nn_labels = tf.gather(reference_labels, nn_indices)
- if k == 1:
- nn_labels = tf.squeeze(nn_labels, axis=1)
- else:
- nn_labels = majority_vote(nn_labels)
- height = tf.shape(reference_embeddings)[0]
- width = tf.shape(reference_embeddings)[1]
- n_query_frames = query_embeddings.shape[0]
- nn_labels = tf.reshape(nn_labels, [n_query_frames, height, width, 1])
- return nn_labels
-
-
-def flattened_pairwise_distances(reference_embeddings, query_embeddings):
- """Calculates flattened tensor of pairwise distances between ref and query.
-
- Args:
- reference_embeddings: Tensor of shape [..., embedding_dim],
- the embedding vectors for the reference frame
- query_embeddings: Tensor of shape [n_query_images, height, width,
- embedding_dim], the embedding vectors for the query frames.
-
- Returns:
- A distance tensor of shape [reference_embeddings.size / embedding_dim,
- query_embeddings.size / embedding_dim]
- """
- embedding_dim = resolve_shape(query_embeddings)[-1]
- reference_embeddings = tf.reshape(reference_embeddings, [-1, embedding_dim])
- first_dim = -1
- query_embeddings = tf.reshape(query_embeddings, [first_dim, embedding_dim])
- dists = pairwise_distances(query_embeddings, reference_embeddings)
- return dists
-
-
-def nearest_neighbor_features_per_object(
- reference_embeddings, query_embeddings, reference_labels,
- max_neighbors_per_object, k_nearest_neighbors, gt_ids=None, n_chunks=100):
- """Calculates the distance to the nearest neighbor per object.
-
- For every pixel of query_embeddings calculate the distance to the
- nearest neighbor in the (possibly subsampled) reference_embeddings per object.
-
- Args:
- reference_embeddings: Tensor of shape [height, width, embedding_dim],
- the embedding vectors for the reference frame.
- query_embeddings: Tensor of shape [n_query_images, height, width,
- embedding_dim], the embedding vectors for the query frames.
- reference_labels: Tensor of shape [height, width, 1], the class labels of
- the reference frame.
- max_neighbors_per_object: Integer, the maximum number of candidates
- for the nearest neighbor query per object after subsampling,
- or 0 for no subsampling.
- k_nearest_neighbors: Integer, the number of nearest neighbors to use.
- gt_ids: Int tensor of shape [n_objs] of the sorted unique ground truth
- ids in the first frame. If None, it will be derived from
- reference_labels.
- n_chunks: Integer, the number of chunks to use to save memory
- (set to 1 for no chunking).
-
- Returns:
- nn_features: A float32 tensor of nearest neighbor features of shape
- [n_query_images, height, width, n_objects, feature_dim].
- gt_ids: An int32 tensor of the unique sorted object ids present
- in the reference labels.
- """
- with tf.name_scope('nn_features_per_object'):
- reference_labels_flat = tf.reshape(reference_labels, [-1])
- if gt_ids is None:
- ref_obj_ids, _ = tf.unique(reference_labels_flat)
- ref_obj_ids = tf.contrib.framework.sort(ref_obj_ids)
- gt_ids = ref_obj_ids
- embedding_dim = resolve_shape(reference_embeddings)[-1]
- reference_embeddings_flat = tf.reshape(reference_embeddings,
- [-1, embedding_dim])
-
- reference_embeddings_flat, reference_labels_flat = (
- subsample_reference_embeddings_and_labels(reference_embeddings_flat,
- reference_labels_flat,
- gt_ids,
- max_neighbors_per_object))
- shape = resolve_shape(query_embeddings)
- query_embeddings_flat = tf.reshape(query_embeddings, [-1, embedding_dim])
- nn_features = _nearest_neighbor_features_per_object_in_chunks(
- reference_embeddings_flat, query_embeddings_flat, reference_labels_flat,
- gt_ids, k_nearest_neighbors, n_chunks)
- nn_features_dim = resolve_shape(nn_features)[-1]
- nn_features_reshaped = tf.reshape(nn_features,
- tf.stack(shape[:3] + [tf.size(gt_ids),
- nn_features_dim]))
- return nn_features_reshaped, gt_ids
-
-
-def _nearest_neighbor_features_per_object_in_chunks(
- reference_embeddings_flat, query_embeddings_flat, reference_labels_flat,
- ref_obj_ids, k_nearest_neighbors, n_chunks):
- """Calculates the nearest neighbor features per object in chunks to save mem.
-
- Uses chunking to bound the memory use.
-
- Args:
- reference_embeddings_flat: Tensor of shape [n, embedding_dim],
- the embedding vectors for the reference frame.
- query_embeddings_flat: Tensor of shape [m, embedding_dim], the embedding
- vectors for the query frames.
- reference_labels_flat: Tensor of shape [n], the class labels of the
- reference frame.
- ref_obj_ids: int tensor of unique object ids in the reference labels.
- k_nearest_neighbors: Integer, the number of nearest neighbors to use.
- n_chunks: Integer, the number of chunks to use to save memory
- (set to 1 for no chunking).
-
- Returns:
- nn_features: A float32 tensor of nearest neighbor features of shape
- [m, n_objects, feature_dim].
- """
- chunk_size = tf.cast(tf.ceil(tf.cast(tf.shape(query_embeddings_flat)[0],
- tf.float32) / n_chunks), tf.int32)
- wrong_label_mask = tf.not_equal(reference_labels_flat,
- ref_obj_ids[:, tf.newaxis])
- all_features = []
- for n in range(n_chunks):
- if n_chunks == 1:
- query_embeddings_flat_chunk = query_embeddings_flat
- else:
- chunk_start = n * chunk_size
- chunk_end = (n + 1) * chunk_size
- query_embeddings_flat_chunk = query_embeddings_flat[chunk_start:chunk_end]
- # Use control dependencies to make sure that the chunks are not processed
- # in parallel which would prevent any peak memory savings.
- with tf.control_dependencies(all_features):
- features = _nn_features_per_object_for_chunk(
- reference_embeddings_flat, query_embeddings_flat_chunk,
- wrong_label_mask, k_nearest_neighbors
- )
- all_features.append(features)
- if n_chunks == 1:
- nn_features = all_features[0]
- else:
- nn_features = tf.concat(all_features, axis=0)
- return nn_features
-
-
-def _nn_features_per_object_for_chunk(
- reference_embeddings, query_embeddings, wrong_label_mask,
- k_nearest_neighbors):
- """Extracts features for each object using nearest neighbor attention.
-
- Args:
- reference_embeddings: Tensor of shape [n_chunk, embedding_dim],
- the embedding vectors for the reference frame.
- query_embeddings: Tensor of shape [m_chunk, embedding_dim], the embedding
- vectors for the query frames.
- wrong_label_mask:
- k_nearest_neighbors: Integer, the number of nearest neighbors to use.
-
- Returns:
- nn_features: A float32 tensor of nearest neighbor features of shape
- [m_chunk, n_objects, feature_dim].
- """
- reference_embeddings_key = reference_embeddings
- query_embeddings_key = query_embeddings
- dists = flattened_pairwise_distances(reference_embeddings_key,
- query_embeddings_key)
- dists = (dists[:, tf.newaxis, :] +
- tf.cast(wrong_label_mask[tf.newaxis, :, :], tf.float32) *
- WRONG_LABEL_PADDING_DISTANCE)
- if k_nearest_neighbors == 1:
- features = tf.reduce_min(dists, axis=2, keepdims=True)
- else:
- # Find the closest k and combine them according to attention_feature_type
- dists, _ = tf.nn.top_k(-dists, k=k_nearest_neighbors)
- dists = -dists
- # If not enough real neighbors were found, pad with the farthest real
- # neighbor.
- valid_mask = tf.less(dists, WRONG_LABEL_PADDING_DISTANCE)
- masked_dists = dists * tf.cast(valid_mask, tf.float32)
- pad_dist = tf.tile(tf.reduce_max(masked_dists, axis=2)[..., tf.newaxis],
- multiples=[1, 1, k_nearest_neighbors])
- dists = tf.where(valid_mask, dists, pad_dist)
- # take mean of distances
- features = tf.reduce_mean(dists, axis=2, keepdims=True)
- return features
-
-
-def create_embedding_segmentation_features(features, feature_dimension,
- n_layers, kernel_size, reuse,
- atrous_rates=None):
- """Extracts features which can be used to estimate the final segmentation.
-
- Args:
- features: input features of shape [batch, height, width, features]
- feature_dimension: Integer, the dimensionality used in the segmentation
- head layers.
- n_layers: Integer, the number of layers in the segmentation head.
- kernel_size: Integer, the kernel size used in the segmentation head.
- reuse: reuse mode for the variable_scope.
- atrous_rates: List of integers of length n_layers, the atrous rates to use.
-
- Returns:
- Features to be used to estimate the segmentation labels of shape
- [batch, height, width, embedding_seg_feat_dim].
- """
- if atrous_rates is None or not atrous_rates:
- atrous_rates = [1 for _ in range(n_layers)]
- assert len(atrous_rates) == n_layers
- with tf.variable_scope('embedding_seg', reuse=reuse):
- for n in range(n_layers):
- features = model.split_separable_conv2d(
- features, feature_dimension, kernel_size=kernel_size,
- rate=atrous_rates[n], scope='split_separable_conv2d_{}'.format(n))
- return features
-
-
-def add_image_summaries(images, nn_features, logits, batch_size,
- prev_frame_nn_features=None):
- """Adds image summaries of input images, attention features and logits.
-
- Args:
- images: Image tensor of shape [batch, height, width, channels].
- nn_features: Nearest neighbor attention features of shape
- [batch_size, height, width, n_objects, 1].
- logits: Float32 tensor of logits.
- batch_size: Integer, the number of videos per clone per mini-batch.
- prev_frame_nn_features: Nearest neighbor attention features wrt. the
- last frame of shape [batch_size, height, width, n_objects, 1].
- Can be None.
- """
- # Separate reference and query images.
- reshaped_images = tf.reshape(images, tf.stack(
- [batch_size, -1] + resolve_shape(images)[1:]))
- reference_images = reshaped_images[:, 0]
- query_images = reshaped_images[:, 1:]
- query_images_reshaped = tf.reshape(query_images, tf.stack(
- [-1] + resolve_shape(images)[1:]))
- tf.summary.image('ref_images', reference_images, max_outputs=batch_size)
- tf.summary.image('query_images', query_images_reshaped, max_outputs=10)
- predictions = tf.cast(
- tf.argmax(logits, axis=-1), tf.uint8)[..., tf.newaxis]
- # Scale up so that we can actually see something.
- tf.summary.image('predictions', predictions * 32, max_outputs=10)
- # We currently only show the first dimension of the features for background
- # and the first foreground object.
- tf.summary.image('nn_fg_features', nn_features[..., 0:1, 0],
- max_outputs=batch_size)
- if prev_frame_nn_features is not None:
- tf.summary.image('nn_fg_features_prev', prev_frame_nn_features[..., 0:1, 0],
- max_outputs=batch_size)
- tf.summary.image('nn_bg_features', nn_features[..., 1:2, 0],
- max_outputs=batch_size)
- if prev_frame_nn_features is not None:
- tf.summary.image('nn_bg_features_prev',
- prev_frame_nn_features[..., 1:2, 0],
- max_outputs=batch_size)
-
-
-def get_embeddings(images, model_options, embedding_dimension):
- """Extracts embedding vectors for images. Should only be used for inference.
-
- Args:
- images: A tensor of shape [batch, height, width, channels].
- model_options: A ModelOptions instance to configure models.
- embedding_dimension: Integer, the dimension of the embedding.
-
- Returns:
- embeddings: A tensor of shape [batch, height, width, embedding_dimension].
- """
- features, end_points = model.extract_features(
- images,
- model_options,
- is_training=False)
-
- if model_options.decoder_output_stride is not None:
- decoder_output_stride = min(model_options.decoder_output_stride)
- if model_options.crop_size is None:
- height = tf.shape(images)[1]
- width = tf.shape(images)[2]
- else:
- height, width = model_options.crop_size
- features = model.refine_by_decoder(
- features,
- end_points,
- crop_size=[height, width],
- decoder_output_stride=[decoder_output_stride],
- decoder_use_separable_conv=model_options.decoder_use_separable_conv,
- model_variant=model_options.model_variant,
- is_training=False)
-
- with tf.variable_scope('embedding'):
- embeddings = split_separable_conv2d_with_identity_initializer(
- features, embedding_dimension, scope='split_separable_conv2d')
- return embeddings
-
-
-def get_logits_with_matching(images,
- model_options,
- weight_decay=0.0001,
- reuse=None,
- is_training=False,
- fine_tune_batch_norm=False,
- reference_labels=None,
- batch_size=None,
- num_frames_per_video=None,
- embedding_dimension=None,
- max_neighbors_per_object=0,
- k_nearest_neighbors=1,
- use_softmax_feedback=True,
- initial_softmax_feedback=None,
- embedding_seg_feature_dimension=256,
- embedding_seg_n_layers=4,
- embedding_seg_kernel_size=7,
- embedding_seg_atrous_rates=None,
- normalize_nearest_neighbor_distances=True,
- also_attend_to_previous_frame=True,
- damage_initial_previous_frame_mask=False,
- use_local_previous_frame_attention=True,
- previous_frame_attention_window_size=15,
- use_first_frame_matching=True,
- also_return_embeddings=False,
- ref_embeddings=None):
- """Gets the logits by atrous/image spatial pyramid pooling using attention.
-
- Args:
- images: A tensor of size [batch, height, width, channels].
- model_options: A ModelOptions instance to configure models.
- weight_decay: The weight decay for model variables.
- reuse: Reuse the model variables or not.
- is_training: Is training or not.
- fine_tune_batch_norm: Fine-tune the batch norm parameters or not.
- reference_labels: The segmentation labels of the reference frame on which
- attention is applied.
- batch_size: Integer, the number of videos on a batch
- num_frames_per_video: Integer, the number of frames per video
- embedding_dimension: Integer, the dimension of the embedding
- max_neighbors_per_object: Integer, the maximum number of candidates
- for the nearest neighbor query per object after subsampling.
- Can be 0 for no subsampling.
- k_nearest_neighbors: Integer, the number of nearest neighbors to use.
- use_softmax_feedback: Boolean, whether to give the softmax predictions of
- the last frame as additional input to the segmentation head.
- initial_softmax_feedback: List of Float32 tensors, or None. Can be used to
- initialize the softmax predictions used for the feedback loop.
- Only has an effect if use_softmax_feedback is True.
- embedding_seg_feature_dimension: Integer, the dimensionality used in the
- segmentation head layers.
- embedding_seg_n_layers: Integer, the number of layers in the segmentation
- head.
- embedding_seg_kernel_size: Integer, the kernel size used in the
- segmentation head.
- embedding_seg_atrous_rates: List of integers of length
- embedding_seg_n_layers, the atrous rates to use for the segmentation head.
- normalize_nearest_neighbor_distances: Boolean, whether to normalize the
- nearest neighbor distances to [0,1] using sigmoid, scale and shift.
- also_attend_to_previous_frame: Boolean, whether to also use nearest
- neighbor attention with respect to the previous frame.
- damage_initial_previous_frame_mask: Boolean, whether to artificially damage
- the initial previous frame mask. Only has an effect if
- also_attend_to_previous_frame is True.
- use_local_previous_frame_attention: Boolean, whether to restrict the
- previous frame attention to a local search window.
- Only has an effect, if also_attend_to_previous_frame is True.
- previous_frame_attention_window_size: Integer, the window size used for
- local previous frame attention, if use_local_previous_frame_attention
- is True.
- use_first_frame_matching: Boolean, whether to extract features by matching
- to the reference frame. This should always be true except for ablation
- experiments.
- also_return_embeddings: Boolean, whether to return the embeddings as well.
- ref_embeddings: Tuple of
- (first_frame_embeddings, previous_frame_embeddings),
- each of shape [batch, height, width, embedding_dimension], or None.
- Returns:
- outputs_to_logits: A map from output_type to logits.
- If also_return_embeddings is True, it will also return an embeddings
- tensor of shape [batch, height, width, embedding_dimension].
- """
- features, end_points = model.extract_features(
- images,
- model_options,
- weight_decay=weight_decay,
- reuse=reuse,
- is_training=is_training,
- fine_tune_batch_norm=fine_tune_batch_norm)
-
- if model_options.decoder_output_stride:
- decoder_output_stride = min(model_options.decoder_output_stride)
- if model_options.crop_size is None:
- height = tf.shape(images)[1]
- width = tf.shape(images)[2]
- else:
- height, width = model_options.crop_size
- decoder_height = model.scale_dimension(height, 1.0 / decoder_output_stride)
- decoder_width = model.scale_dimension(width, 1.0 / decoder_output_stride)
- features = model.refine_by_decoder(
- features,
- end_points,
- crop_size=[height, width],
- decoder_output_stride=[decoder_output_stride],
- decoder_use_separable_conv=model_options.decoder_use_separable_conv,
- model_variant=model_options.model_variant,
- weight_decay=weight_decay,
- reuse=reuse,
- is_training=is_training,
- fine_tune_batch_norm=fine_tune_batch_norm)
-
- with tf.variable_scope('embedding', reuse=reuse):
- embeddings = split_separable_conv2d_with_identity_initializer(
- features, embedding_dimension, scope='split_separable_conv2d')
- embeddings = tf.identity(embeddings, name='embeddings')
- scaled_reference_labels = tf.image.resize_nearest_neighbor(
- reference_labels,
- resolve_shape(embeddings, 4)[1:3],
- align_corners=True)
- h, w = decoder_height, decoder_width
- if num_frames_per_video is None:
- num_frames_per_video = tf.size(embeddings) // (
- batch_size * h * w * embedding_dimension)
- new_labels_shape = tf.stack([batch_size, -1, h, w, 1])
- reshaped_reference_labels = tf.reshape(scaled_reference_labels,
- new_labels_shape)
- new_embeddings_shape = tf.stack([batch_size,
- num_frames_per_video, h, w,
- embedding_dimension])
- reshaped_embeddings = tf.reshape(embeddings, new_embeddings_shape)
- all_nn_features = []
- all_ref_obj_ids = []
- # To keep things simple, we do all this separate for each sequence for now.
- for n in range(batch_size):
- embedding = reshaped_embeddings[n]
- if ref_embeddings is None:
- n_chunks = 100
- reference_embedding = embedding[0]
- if also_attend_to_previous_frame or use_softmax_feedback:
- queries_embedding = embedding[2:]
- else:
- queries_embedding = embedding[1:]
- else:
- if USE_CORRELATION_COST:
- n_chunks = 20
- else:
- n_chunks = 500
- reference_embedding = ref_embeddings[0][n]
- queries_embedding = embedding
- reference_labels = reshaped_reference_labels[n][0]
- nn_features_n, ref_obj_ids = nearest_neighbor_features_per_object(
- reference_embedding, queries_embedding, reference_labels,
- max_neighbors_per_object, k_nearest_neighbors, n_chunks=n_chunks)
- if normalize_nearest_neighbor_distances:
- nn_features_n = (tf.nn.sigmoid(nn_features_n) - 0.5) * 2
- all_nn_features.append(nn_features_n)
- all_ref_obj_ids.append(ref_obj_ids)
-
- feat_dim = resolve_shape(features)[-1]
- features = tf.reshape(features, tf.stack(
- [batch_size, num_frames_per_video, h, w, feat_dim]))
- if ref_embeddings is None:
- # Strip the features for the reference frame.
- if also_attend_to_previous_frame or use_softmax_feedback:
- features = features[:, 2:]
- else:
- features = features[:, 1:]
-
- # To keep things simple, we do all this separate for each sequence for now.
- outputs_to_logits = {output: [] for
- output in model_options.outputs_to_num_classes}
- for n in range(batch_size):
- features_n = features[n]
- nn_features_n = all_nn_features[n]
- nn_features_n_tr = tf.transpose(nn_features_n, [3, 0, 1, 2, 4])
- n_objs = tf.shape(nn_features_n_tr)[0]
- # Repeat features for every object.
- features_n_tiled = tf.tile(features_n[tf.newaxis],
- multiples=[n_objs, 1, 1, 1, 1])
- prev_frame_labels = None
- if also_attend_to_previous_frame:
- prev_frame_labels = reshaped_reference_labels[n, 1]
- if is_training and damage_initial_previous_frame_mask:
- # Damage the previous frame masks.
- prev_frame_labels = mask_damaging.damage_masks(prev_frame_labels,
- dilate=False)
- tf.summary.image('prev_frame_labels',
- tf.cast(prev_frame_labels[tf.newaxis],
- tf.uint8) * 32)
- initial_softmax_feedback_n = create_initial_softmax_from_labels(
- prev_frame_labels, reshaped_reference_labels[n][0],
- decoder_output_stride=None, reduce_labels=True)
- elif initial_softmax_feedback is not None:
- initial_softmax_feedback_n = initial_softmax_feedback[n]
- else:
- initial_softmax_feedback_n = None
- if initial_softmax_feedback_n is None:
- last_softmax = tf.zeros((n_objs, h, w, 1), dtype=tf.float32)
- else:
- last_softmax = tf.transpose(initial_softmax_feedback_n, [2, 0, 1])[
- ..., tf.newaxis]
- assert len(model_options.outputs_to_num_classes) == 1
- output = model_options.outputs_to_num_classes.keys()[0]
- logits = []
- n_ref_frames = 1
- prev_frame_nn_features_n = None
- if also_attend_to_previous_frame or use_softmax_feedback:
- n_ref_frames += 1
- if ref_embeddings is not None:
- n_ref_frames = 0
- for t in range(num_frames_per_video - n_ref_frames):
- to_concat = [features_n_tiled[:, t]]
- if use_first_frame_matching:
- to_concat.append(nn_features_n_tr[:, t])
- if use_softmax_feedback:
- to_concat.append(last_softmax)
- if also_attend_to_previous_frame:
- assert normalize_nearest_neighbor_distances, (
- 'previous frame attention currently only works when normalized '
- 'distances are used')
- embedding = reshaped_embeddings[n]
- if ref_embeddings is None:
- last_frame_embedding = embedding[t + 1]
- query_embeddings = embedding[t + 2, tf.newaxis]
- else:
- last_frame_embedding = ref_embeddings[1][0]
- query_embeddings = embedding
- if use_local_previous_frame_attention:
- assert query_embeddings.shape[0] == 1
- prev_frame_nn_features_n = (
- local_previous_frame_nearest_neighbor_features_per_object(
- last_frame_embedding,
- query_embeddings[0],
- prev_frame_labels,
- all_ref_obj_ids[n],
- max_distance=previous_frame_attention_window_size)
- )
- else:
- prev_frame_nn_features_n, _ = (
- nearest_neighbor_features_per_object(
- last_frame_embedding, query_embeddings, prev_frame_labels,
- max_neighbors_per_object, k_nearest_neighbors,
- gt_ids=all_ref_obj_ids[n]))
- prev_frame_nn_features_n = (tf.nn.sigmoid(
- prev_frame_nn_features_n) - 0.5) * 2
- prev_frame_nn_features_n_sq = tf.squeeze(prev_frame_nn_features_n,
- axis=0)
- prev_frame_nn_features_n_tr = tf.transpose(
- prev_frame_nn_features_n_sq, [2, 0, 1, 3])
- to_concat.append(prev_frame_nn_features_n_tr)
- features_n_concat_t = tf.concat(to_concat, axis=-1)
- embedding_seg_features_n_t = (
- create_embedding_segmentation_features(
- features_n_concat_t, embedding_seg_feature_dimension,
- embedding_seg_n_layers, embedding_seg_kernel_size,
- reuse or n > 0, atrous_rates=embedding_seg_atrous_rates))
- logits_t = model.get_branch_logits(
- embedding_seg_features_n_t,
- 1,
- model_options.atrous_rates,
- aspp_with_batch_norm=model_options.aspp_with_batch_norm,
- kernel_size=model_options.logits_kernel_size,
- weight_decay=weight_decay,
- reuse=reuse or n > 0 or t > 0,
- scope_suffix=output
- )
- logits.append(logits_t)
- prev_frame_labels = tf.transpose(tf.argmax(logits_t, axis=0),
- [2, 0, 1])
- last_softmax = tf.nn.softmax(logits_t, axis=0)
- logits = tf.stack(logits, axis=1)
- logits_shape = tf.stack(
- [n_objs, num_frames_per_video - n_ref_frames] +
- resolve_shape(logits)[2:-1])
- logits_reshaped = tf.reshape(logits, logits_shape)
- logits_transposed = tf.transpose(logits_reshaped, [1, 2, 3, 0])
- outputs_to_logits[output].append(logits_transposed)
-
- add_image_summaries(
- images[n * num_frames_per_video: (n+1) * num_frames_per_video],
- nn_features_n,
- logits_transposed,
- batch_size=1,
- prev_frame_nn_features=prev_frame_nn_features_n)
- if also_return_embeddings:
- return outputs_to_logits, embeddings
- else:
- return outputs_to_logits
-
-
-def subsample_reference_embeddings_and_labels(
- reference_embeddings_flat, reference_labels_flat, ref_obj_ids,
- max_neighbors_per_object):
- """Subsamples the reference embedding vectors and labels.
-
- After subsampling, at most max_neighbors_per_object items will remain per
- class.
-
- Args:
- reference_embeddings_flat: Tensor of shape [n, embedding_dim],
- the embedding vectors for the reference frame.
- reference_labels_flat: Tensor of shape [n, 1],
- the class labels of the reference frame.
- ref_obj_ids: An int32 tensor of the unique object ids present
- in the reference labels.
- max_neighbors_per_object: Integer, the maximum number of candidates
- for the nearest neighbor query per object after subsampling,
- or 0 for no subsampling.
-
- Returns:
- reference_embeddings_flat: Tensor of shape [n_sub, embedding_dim],
- the subsampled embedding vectors for the reference frame.
- reference_labels_flat: Tensor of shape [n_sub, 1],
- the class labels of the reference frame.
- """
- if max_neighbors_per_object == 0:
- return reference_embeddings_flat, reference_labels_flat
- same_label_mask = tf.equal(reference_labels_flat[tf.newaxis, :],
- ref_obj_ids[:, tf.newaxis])
- max_neighbors_per_object_repeated = tf.tile(
- tf.constant(max_neighbors_per_object)[tf.newaxis],
- multiples=[tf.size(ref_obj_ids)])
- # Somehow map_fn on GPU caused trouble sometimes, so let's put it on CPU
- # for now.
- with tf.device('cpu:0'):
- subsampled_indices = tf.map_fn(_create_subsampling_mask,
- (same_label_mask,
- max_neighbors_per_object_repeated),
- dtype=tf.int64,
- name='subsample_labels_map_fn',
- parallel_iterations=1)
- mask = tf.not_equal(subsampled_indices, tf.constant(-1, dtype=tf.int64))
- masked_indices = tf.boolean_mask(subsampled_indices, mask)
- reference_embeddings_flat = tf.gather(reference_embeddings_flat,
- masked_indices)
- reference_labels_flat = tf.gather(reference_labels_flat, masked_indices)
- return reference_embeddings_flat, reference_labels_flat
-
-
-def _create_subsampling_mask(args):
- """Creates boolean mask which can be used to subsample the labels.
-
- Args:
- args: tuple of (label_mask, max_neighbors_per_object), where label_mask
- is the mask to be subsampled and max_neighbors_per_object is a int scalar,
- the maximum number of neighbors to be retained after subsampling.
-
- Returns:
- The boolean mask for subsampling the labels.
- """
- label_mask, max_neighbors_per_object = args
- indices = tf.squeeze(tf.where(label_mask), axis=1)
- shuffled_indices = tf.random_shuffle(indices)
- subsampled_indices = shuffled_indices[:max_neighbors_per_object]
- n_pad = max_neighbors_per_object - tf.size(subsampled_indices)
- padded_label = -1
- padding = tf.fill((n_pad,), tf.constant(padded_label, dtype=tf.int64))
- padded = tf.concat([subsampled_indices, padding], axis=0)
- return padded
-
-
-def conv2d_identity_initializer(scale=1.0, mean=0, stddev=3e-2):
- """Creates an identity initializer for TensorFlow conv2d.
-
- We add a small amount of normal noise to the initialization matrix.
- Code copied from lcchen@.
-
- Args:
- scale: The scale coefficient for the identity weight matrix.
- mean: A 0-D Tensor or Python value of type `dtype`. The mean of the
- truncated normal distribution.
- stddev: A 0-D Tensor or Python value of type `dtype`. The standard deviation
- of the truncated normal distribution.
-
- Returns:
- An identity initializer function for TensorFlow conv2d.
- """
- def _initializer(shape, dtype=tf.float32, partition_info=None):
- """Returns the identity matrix scaled by `scale`.
-
- Args:
- shape: A tuple of int32 numbers indicating the shape of the initializing
- matrix.
- dtype: The data type of the initializing matrix.
- partition_info: (Optional) variable_scope._PartitionInfo object holding
- additional information about how the variable is partitioned. This input
- is not used in our case, but is required by TensorFlow.
-
- Returns:
- A identity matrix.
-
- Raises:
- ValueError: If len(shape) != 4, or shape[0] != shape[1], or shape[0] is
- not odd, or shape[1] is not odd..
- """
- del partition_info
- if len(shape) != 4:
- raise ValueError('Expect shape length to be 4.')
- if shape[0] != shape[1]:
- raise ValueError('Expect shape[0] = shape[1].')
- if shape[0] % 2 != 1:
- raise ValueError('Expect shape[0] to be odd value.')
- if shape[1] % 2 != 1:
- raise ValueError('Expect shape[1] to be odd value.')
- weights = np.zeros(shape, dtype=np.float32)
- center_y = shape[0] / 2
- center_x = shape[1] / 2
- min_channel = min(shape[2], shape[3])
- for i in range(min_channel):
- weights[center_y, center_x, i, i] = scale
- return tf.constant(weights, dtype=dtype) + tf.truncated_normal(
- shape, mean=mean, stddev=stddev, dtype=dtype)
-
- return _initializer
-
-
-def split_separable_conv2d_with_identity_initializer(
- inputs,
- filters,
- kernel_size=3,
- rate=1,
- weight_decay=0.00004,
- scope=None):
- """Splits a separable conv2d into depthwise and pointwise conv2d.
-
- This operation differs from `tf.layers.separable_conv2d` as this operation
- applies activation function between depthwise and pointwise conv2d.
-
- Args:
- inputs: Input tensor with shape [batch, height, width, channels].
- filters: Number of filters in the 1x1 pointwise convolution.
- kernel_size: A list of length 2: [kernel_height, kernel_width] of
- of the filters. Can be an int if both values are the same.
- rate: Atrous convolution rate for the depthwise convolution.
- weight_decay: The weight decay to use for regularizing the model.
- scope: Optional scope for the operation.
-
- Returns:
- Computed features after split separable conv2d.
- """
- initializer = conv2d_identity_initializer()
- outputs = slim.separable_conv2d(
- inputs,
- None,
- kernel_size=kernel_size,
- depth_multiplier=1,
- rate=rate,
- weights_initializer=initializer,
- weights_regularizer=None,
- scope=scope + '_depthwise')
- return slim.conv2d(
- outputs,
- filters,
- 1,
- weights_initializer=initializer,
- weights_regularizer=slim.l2_regularizer(weight_decay),
- scope=scope + '_pointwise')
-
-
-def create_initial_softmax_from_labels(last_frame_labels, reference_labels,
- decoder_output_stride, reduce_labels):
- """Creates initial softmax predictions from last frame labels.
-
- Args:
- last_frame_labels: last frame labels of shape [1, height, width, 1].
- reference_labels: reference frame labels of shape [1, height, width, 1].
- decoder_output_stride: Integer, the stride of the decoder. Can be None, in
- this case it's assumed that the last_frame_labels and reference_labels
- are already scaled to the decoder output resolution.
- reduce_labels: Boolean, whether to reduce the depth of the softmax one_hot
- encoding to the actual number of labels present in the reference frame
- (otherwise the depth will be the highest label index + 1).
-
- Returns:
- init_softmax: the initial softmax predictions.
- """
- if decoder_output_stride is None:
- labels_output_size = last_frame_labels
- reference_labels_output_size = reference_labels
- else:
- h = tf.shape(last_frame_labels)[1]
- w = tf.shape(last_frame_labels)[2]
- h_sub = model.scale_dimension(h, 1.0 / decoder_output_stride)
- w_sub = model.scale_dimension(w, 1.0 / decoder_output_stride)
- labels_output_size = tf.image.resize_nearest_neighbor(
- last_frame_labels, [h_sub, w_sub], align_corners=True)
- reference_labels_output_size = tf.image.resize_nearest_neighbor(
- reference_labels, [h_sub, w_sub], align_corners=True)
- if reduce_labels:
- unique_labels, _ = tf.unique(tf.reshape(reference_labels_output_size, [-1]))
- depth = tf.size(unique_labels)
- else:
- depth = tf.reduce_max(reference_labels_output_size) + 1
- one_hot_assertion = tf.assert_less(tf.reduce_max(labels_output_size), depth)
- with tf.control_dependencies([one_hot_assertion]):
- init_softmax = tf.one_hot(tf.squeeze(labels_output_size,
- axis=-1),
- depth=depth,
- dtype=tf.float32)
- return init_softmax
-
-
-def local_previous_frame_nearest_neighbor_features_per_object(
- prev_frame_embedding, query_embedding, prev_frame_labels,
- gt_ids, max_distance=9):
- """Computes nearest neighbor features while only allowing local matches.
-
- Args:
- prev_frame_embedding: Tensor of shape [height, width, embedding_dim],
- the embedding vectors for the last frame.
- query_embedding: Tensor of shape [height, width, embedding_dim],
- the embedding vectors for the query frames.
- prev_frame_labels: Tensor of shape [height, width, 1], the class labels of
- the previous frame.
- gt_ids: Int Tensor of shape [n_objs] of the sorted unique ground truth
- ids in the first frame.
- max_distance: Integer, the maximum distance allowed for local matching.
-
- Returns:
- nn_features: A float32 np.array of nearest neighbor features of shape
- [1, height, width, n_objects, 1].
- """
- with tf.name_scope(
- 'local_previous_frame_nearest_neighbor_features_per_object'):
- if USE_CORRELATION_COST:
- tf.logging.info('Using correlation_cost.')
- d = local_pairwise_distances(query_embedding, prev_frame_embedding,
- max_distance=max_distance)
- else:
- # Slow fallback in case correlation_cost is not available.
- tf.logging.warn('correlation cost is not available, using slow fallback '
- 'implementation.')
- d = local_pairwise_distances2(query_embedding, prev_frame_embedding,
- max_distance=max_distance)
- d = (tf.nn.sigmoid(d) - 0.5) * 2
- height = tf.shape(prev_frame_embedding)[0]
- width = tf.shape(prev_frame_embedding)[1]
-
- # Create offset versions of the mask.
- if USE_CORRELATION_COST:
- # New, faster code with cross-correlation via correlation_cost.
- # Due to padding we have to add 1 to the labels.
- offset_labels = correlation_cost_op.correlation_cost(
- tf.ones((1, height, width, 1)),
- tf.cast(prev_frame_labels + 1, tf.float32)[tf.newaxis],
- kernel_size=1,
- max_displacement=max_distance, stride_1=1, stride_2=1,
- pad=max_distance)
- offset_labels = tf.squeeze(offset_labels, axis=0)[..., tf.newaxis]
- # Subtract the 1 again and round.
- offset_labels = tf.round(offset_labels - 1)
- offset_masks = tf.equal(
- offset_labels,
- tf.cast(gt_ids, tf.float32)[tf.newaxis, tf.newaxis, tf.newaxis, :])
- else:
- # Slower code, without dependency to correlation_cost
- masks = tf.equal(prev_frame_labels, gt_ids[tf.newaxis, tf.newaxis])
- padded_masks = tf.pad(masks,
- [[max_distance, max_distance],
- [max_distance, max_distance],
- [0, 0]])
- offset_masks = []
- for y_start in range(2 * max_distance + 1):
- y_end = y_start + height
- masks_slice = padded_masks[y_start:y_end]
- for x_start in range(2 * max_distance + 1):
- x_end = x_start + width
- offset_mask = masks_slice[:, x_start:x_end]
- offset_masks.append(offset_mask)
- offset_masks = tf.stack(offset_masks, axis=2)
-
- pad = tf.ones((height, width, (2 * max_distance + 1) ** 2, tf.size(gt_ids)))
- d_tiled = tf.tile(d[..., tf.newaxis], multiples=(1, 1, 1, tf.size(gt_ids)))
- d_masked = tf.where(offset_masks, d_tiled, pad)
- dists = tf.reduce_min(d_masked, axis=2)
- dists = tf.reshape(dists, (1, height, width, tf.size(gt_ids), 1))
- return dists
diff --git a/research/feelvos/utils/embedding_utils_test.py b/research/feelvos/utils/embedding_utils_test.py
deleted file mode 100644
index ddebd7b4e7fcc9402887ebf59d247fea815d6cda..0000000000000000000000000000000000000000
--- a/research/feelvos/utils/embedding_utils_test.py
+++ /dev/null
@@ -1,213 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests for embedding utils."""
-
-import unittest
-import numpy as np
-import tensorflow as tf
-from feelvos.utils import embedding_utils
-
-if embedding_utils.USE_CORRELATION_COST:
- # pylint: disable=g-import-not-at-top
- from correlation_cost.python.ops import correlation_cost_op
-
-
-class EmbeddingUtilsTest(tf.test.TestCase):
-
- def test_pairwise_distances(self):
- x = np.arange(100, dtype=np.float32).reshape(20, 5)
- y = np.arange(100, 200, dtype=np.float32).reshape(20, 5)
- g = tf.Graph()
- with g.as_default():
- with self.test_session(graph=g) as sess:
- x = tf.constant(x)
- y = tf.constant(y)
- d1 = embedding_utils.pairwise_distances(x, y)
- d2 = embedding_utils.pairwise_distances2(x, y)
- d1_val, d2_val = sess.run([d1, d2])
- self.assertAllClose(d1_val, d2_val)
-
- @unittest.skipIf(not embedding_utils.USE_CORRELATION_COST,
- 'depends on correlation_cost')
- def test_correlation_cost_one_dimensional(self):
- a = np.array([[[[1.0], [2.0]], [[3.0], [4.0]]]])
- b = np.array([[[[2.0], [1.0]], [[4.0], [3.0]]]])
- g = tf.Graph()
- with g.as_default():
- with self.test_session(graph=g) as sess:
- c = correlation_cost_op.correlation_cost(
- a, b, kernel_size=1, max_displacement=1, stride_1=1, stride_2=1,
- pad=1)
- c = tf.squeeze(c, axis=0)
- c_val = sess.run(c)
- self.assertAllEqual(c_val.shape, (2, 2, 9))
- for y in range(2):
- for x in range(2):
- for dy in range(-1, 2):
- for dx in range(-1, 2):
- a_slice = a[0, y, x, 0]
- if y + dy < 0 or y + dy > 1 or x + dx < 0 or x + dx > 1:
- b_slice = 0
- else:
- b_slice = b[0, y + dy, x + dx, 0]
- expected = a_slice * b_slice
- dy0 = dy + 1
- dx0 = dx + 1
- self.assertAlmostEqual(c_val[y, x, 3 * dy0 + dx0], expected)
-
- @unittest.skipIf(not embedding_utils.USE_CORRELATION_COST,
- 'depends on correlation_cost')
- def test_correlation_cost_two_dimensional(self):
- a = np.array([[[[1.0, -5.0], [7.0, 2.0]], [[1.0, 3.0], [3.0, 4.0]]]])
- b = np.array([[[[2.0, 1.0], [0.0, -9.0]], [[4.0, 3.0], [3.0, 1.0]]]])
- g = tf.Graph()
- with g.as_default():
- with self.test_session(graph=g) as sess:
- c = correlation_cost_op.correlation_cost(
- a, b, kernel_size=1, max_displacement=1, stride_1=1, stride_2=1,
- pad=1)
- c = tf.squeeze(c, axis=0)
- c_val = sess.run(c)
- self.assertAllEqual(c_val.shape, (2, 2, 9))
- for y in range(2):
- for x in range(2):
- for dy in range(-1, 2):
- for dx in range(-1, 2):
- a_slice = a[0, y, x, :]
- if y + dy < 0 or y + dy > 1 or x + dx < 0 or x + dx > 1:
- b_slice = 0
- else:
- b_slice = b[0, y + dy, x + dx, :]
- expected = (a_slice * b_slice).mean()
- dy0 = dy + 1
- dx0 = dx + 1
- self.assertAlmostEqual(c_val[y, x, 3 * dy0 + dx0], expected)
-
- @unittest.skipIf(not embedding_utils.USE_CORRELATION_COST,
- 'depends on correlation_cost')
- def test_local_pairwise_distances_one_dimensional(self):
- a = np.array([[[1.0], [2.0]], [[3.0], [4.0]]])
- b = np.array([[[2.0], [1.0]], [[4.0], [3.0]]])
- g = tf.Graph()
- with g.as_default():
- with self.test_session(graph=g) as sess:
- a_tf = tf.constant(a, dtype=tf.float32)
- b_tf = tf.constant(b, dtype=tf.float32)
- d = embedding_utils.local_pairwise_distances(a_tf, b_tf,
- max_distance=1)
- d_val = sess.run(d)
- for y in range(2):
- for x in range(2):
- for dy in range(-1, 2):
- for dx in range(-1, 2):
- a_slice = a[y, x, 0]
- if y + dy < 0 or y + dy > 1 or x + dx < 0 or x + dx > 1:
- expected = np.float('inf')
- else:
- b_slice = b[y + dy, x + dx, 0]
- expected = (a_slice - b_slice) ** 2
- dy0 = dy + 1
- dx0 = dx + 1
- self.assertAlmostEqual(d_val[y, x, 3 * dy0 + dx0], expected)
-
- @unittest.skipIf(not embedding_utils.USE_CORRELATION_COST,
- 'depends on correlation_cost')
- def test_local_pairwise_distances_shape(self):
- a = np.zeros((4, 5, 2))
- b = np.zeros((4, 5, 2))
- g = tf.Graph()
- with g.as_default():
- with self.test_session(graph=g) as sess:
- a_tf = tf.constant(a, dtype=tf.float32)
- b_tf = tf.constant(b, dtype=tf.float32)
- d = embedding_utils.local_pairwise_distances(a_tf, b_tf, max_distance=4)
- d_val = sess.run(d)
- self.assertAllEqual(d_val.shape, (4, 5, 81))
-
- @unittest.skipIf(not embedding_utils.USE_CORRELATION_COST,
- 'depends on correlation_cost')
- def test_local_pairwise_distances_two_dimensional(self):
- a = np.array([[[1.0, -5.0], [7.0, 2.0]], [[1.0, 3.0], [3.0, 4.0]]])
- b = np.array([[[2.0, 1.0], [0.0, -9.0]], [[4.0, 3.0], [3.0, 1.0]]])
- g = tf.Graph()
- with g.as_default():
- with self.test_session(graph=g) as sess:
- a_tf = tf.constant(a, dtype=tf.float32)
- b_tf = tf.constant(b, dtype=tf.float32)
- d = embedding_utils.local_pairwise_distances(a_tf, b_tf,
- max_distance=1)
- d_val = sess.run(d)
- for y in range(2):
- for x in range(2):
- for dy in range(-1, 2):
- for dx in range(-1, 2):
- a_slice = a[y, x, :]
- if y + dy < 0 or y + dy > 1 or x + dx < 0 or x + dx > 1:
- expected = np.float('inf')
- else:
- b_slice = b[y + dy, x + dx, :]
- expected = ((a_slice - b_slice) ** 2).sum()
- dy0 = dy + 1
- dx0 = dx + 1
- self.assertAlmostEqual(d_val[y, x, 3 * dy0 + dx0], expected)
-
- @unittest.skipIf(not embedding_utils.USE_CORRELATION_COST,
- 'depends on correlation_cost')
- def test_local_previous_frame_nearest_neighbor_features_per_object(self):
- prev_frame_embedding = np.array([[[1.0, -5.0], [7.0, 2.0]],
- [[1.0, 3.0], [3.0, 4.0]]]) / 10
- query_embedding = np.array([[[2.0, 1.0], [0.0, -9.0]],
- [[4.0, 3.0], [3.0, 1.0]]]) / 10
- prev_frame_labels = np.array([[[0], [1]], [[1], [0]]])
- gt_ids = np.array([0, 1])
- g = tf.Graph()
- with g.as_default():
- with self.test_session(graph=g) as sess:
- prev_frame_embedding_tf = tf.constant(prev_frame_embedding,
- dtype=tf.float32)
- query_embedding_tf = tf.constant(query_embedding, dtype=tf.float32)
- embu = embedding_utils
- dists = (
- embu.local_previous_frame_nearest_neighbor_features_per_object(
- prev_frame_embedding_tf, query_embedding_tf,
- prev_frame_labels, gt_ids, max_distance=1))
- dists = tf.squeeze(dists, axis=4)
- dists = tf.squeeze(dists, axis=0)
- dists_val = sess.run(dists)
- for obj_id in gt_ids:
- for y in range(2):
- for x in range(2):
- curr_min = 1.0
- for dy in range(-1, 2):
- for dx in range(-1, 2):
- # Attention: here we shift the prev frame embedding,
- # not the query.
- if y + dy < 0 or y + dy > 1 or x + dx < 0 or x + dx > 1:
- continue
- if prev_frame_labels[y + dy, x + dx, 0] != obj_id:
- continue
- prev_frame_slice = prev_frame_embedding[y + dy, x + dx, :]
- query_frame_slice = query_embedding[y, x, :]
- v_unnorm = ((prev_frame_slice - query_frame_slice) ** 2).sum()
- v = ((1.0 / (1.0 + np.exp(-v_unnorm))) - 0.5) * 2
- curr_min = min(curr_min, v)
- expected = curr_min
- self.assertAlmostEqual(dists_val[y, x, obj_id], expected,
- places=5)
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/feelvos/utils/eval_utils.py b/research/feelvos/utils/eval_utils.py
deleted file mode 100644
index 517ec0d788eb3a6ec48246e10920dd4b55332bf5..0000000000000000000000000000000000000000
--- a/research/feelvos/utils/eval_utils.py
+++ /dev/null
@@ -1,153 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Utility functions for evaluations."""
-
-import numpy as np
-import PIL
-import tensorflow as tf
-
-pascal_colormap = [
- 0, 0, 0,
- 0.5020, 0, 0,
- 0, 0.5020, 0,
- 0.5020, 0.5020, 0,
- 0, 0, 0.5020,
- 0.5020, 0, 0.5020,
- 0, 0.5020, 0.5020,
- 0.5020, 0.5020, 0.5020,
- 0.2510, 0, 0,
- 0.7529, 0, 0,
- 0.2510, 0.5020, 0,
- 0.7529, 0.5020, 0,
- 0.2510, 0, 0.5020,
- 0.7529, 0, 0.5020,
- 0.2510, 0.5020, 0.5020,
- 0.7529, 0.5020, 0.5020,
- 0, 0.2510, 0,
- 0.5020, 0.2510, 0,
- 0, 0.7529, 0,
- 0.5020, 0.7529, 0,
- 0, 0.2510, 0.5020,
- 0.5020, 0.2510, 0.5020,
- 0, 0.7529, 0.5020,
- 0.5020, 0.7529, 0.5020,
- 0.2510, 0.2510, 0]
-
-
-def save_segmentation_with_colormap(filename, img):
- """Saves a segmentation with the pascal colormap as expected for DAVIS eval.
-
- Args:
- filename: Where to store the segmentation.
- img: A numpy array of the segmentation to be saved.
- """
- if img.shape[-1] == 1:
- img = img[..., 0]
-
- # Save with colormap.
- colormap = (np.array(pascal_colormap) * 255).round().astype('uint8')
- colormap_image = PIL.Image.new('P', (16, 16))
- colormap_image.putpalette(colormap)
- pil_image = PIL.Image.fromarray(img.astype('uint8'))
- pil_image_with_colormap = pil_image.quantize(palette=colormap_image)
- with tf.gfile.GFile(filename, 'w') as f:
- pil_image_with_colormap.save(f)
-
-
-def save_embeddings(filename, embeddings):
- with tf.gfile.GFile(filename, 'w') as f:
- np.save(f, embeddings)
-
-
-def calculate_iou(pred_labels, ref_labels):
- """Calculates the intersection over union for binary segmentation.
-
- Args:
- pred_labels: predicted segmentation labels.
- ref_labels: reference segmentation labels.
-
- Returns:
- The IoU between pred_labels and ref_labels
- """
- if ref_labels.any():
- i = np.logical_and(pred_labels, ref_labels).sum()
- u = np.logical_or(pred_labels, ref_labels).sum()
- return i.astype('float') / u
- else:
- if pred_labels.any():
- return 0.0
- else:
- return 1.0
-
-
-def calculate_multi_object_miou_tf(pred_labels, ref_labels):
- """Calculates the mIoU for a batch of predicted and reference labels.
-
- Args:
- pred_labels: Int32 tensor of shape [batch, height, width, 1].
- ref_labels: Int32 tensor of shape [batch, height, width, 1].
-
- Returns:
- The mIoU between pred_labels and ref_labels as float32 scalar tensor.
- """
-
- def calculate_multi_object_miou(pred_labels_, ref_labels_):
- """Calculates the mIoU for predicted and reference labels in numpy.
-
- Args:
- pred_labels_: int32 np.array of shape [batch, height, width, 1].
- ref_labels_: int32 np.array of shape [batch, height, width, 1].
-
- Returns:
- The mIoU between pred_labels_ and ref_labels_.
- """
- assert len(pred_labels_.shape) == 4
- assert pred_labels_.shape[3] == 1
- assert pred_labels_.shape == ref_labels_.shape
- ious = []
- for pred_label, ref_label in zip(pred_labels_, ref_labels_):
- ids = np.setdiff1d(np.unique(ref_label), [0])
- if ids.size == 0:
- continue
- for id_ in ids:
- iou = calculate_iou(pred_label == id_, ref_label == id_)
- ious.append(iou)
- if ious:
- return np.cast['float32'](np.mean(ious))
- else:
- return np.cast['float32'](1.0)
-
- miou = tf.py_func(calculate_multi_object_miou, [pred_labels, ref_labels],
- tf.float32, name='calculate_multi_object_miou')
- miou.set_shape(())
- return miou
-
-
-def calculate_multi_object_ious(pred_labels, ref_labels, label_set):
- """Calculates the intersection over union for binary segmentation.
-
- Args:
- pred_labels: predicted segmentation labels.
- ref_labels: reference segmentation labels.
- label_set: int np.array of object ids.
-
- Returns:
- float np.array of IoUs between pred_labels and ref_labels
- for each object in label_set.
- """
- # Background should not be included as object label.
- return np.array([calculate_iou(pred_labels == label, ref_labels == label)
- for label in label_set if label != 0])
diff --git a/research/feelvos/utils/mask_damaging.py b/research/feelvos/utils/mask_damaging.py
deleted file mode 100644
index 74f3cdab5a0e4374f0cd238544a9a582fd0eef92..0000000000000000000000000000000000000000
--- a/research/feelvos/utils/mask_damaging.py
+++ /dev/null
@@ -1,176 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Utilities for artificially damaging segmentation masks."""
-
-import numpy as np
-from scipy.ndimage import interpolation
-from skimage import morphology
-from skimage import transform
-import tensorflow as tf
-
-
-def damage_masks(labels, shift=True, scale=True, rotate=True, dilate=True):
- """Damages segmentation masks by random transformations.
-
- Args:
- labels: Int32 labels tensor of shape (height, width, 1).
- shift: Boolean, whether to damage the masks by shifting.
- scale: Boolean, whether to damage the masks by scaling.
- rotate: Boolean, whether to damage the masks by rotation.
- dilate: Boolean, whether to damage the masks by dilation.
-
- Returns:
- The damaged version of labels.
- """
- def _damage_masks_np(labels_):
- return damage_masks_np(labels_, shift, scale, rotate, dilate)
- damaged_masks = tf.py_func(_damage_masks_np, [labels], tf.int32,
- name='damage_masks')
- damaged_masks.set_shape(labels.get_shape())
- return damaged_masks
-
-
-def damage_masks_np(labels, shift=True, scale=True, rotate=True, dilate=True):
- """Performs the actual mask damaging in numpy.
-
- Args:
- labels: Int32 numpy array of shape (height, width, 1).
- shift: Boolean, whether to damage the masks by shifting.
- scale: Boolean, whether to damage the masks by scaling.
- rotate: Boolean, whether to damage the masks by rotation.
- dilate: Boolean, whether to damage the masks by dilation.
-
- Returns:
- The damaged version of labels.
- """
- unique_labels = np.unique(labels)
- unique_labels = np.setdiff1d(unique_labels, [0])
- # Shuffle to get random depth ordering when combining together.
- np.random.shuffle(unique_labels)
- damaged_labels = np.zeros_like(labels)
- for l in unique_labels:
- obj_mask = (labels == l)
- damaged_obj_mask = _damage_single_object_mask(obj_mask, shift, scale,
- rotate, dilate)
- damaged_labels[damaged_obj_mask] = l
- return damaged_labels
-
-
-def _damage_single_object_mask(mask, shift, scale, rotate, dilate):
- """Performs mask damaging in numpy for a single object.
-
- Args:
- mask: Boolean numpy array of shape(height, width, 1).
- shift: Boolean, whether to damage the masks by shifting.
- scale: Boolean, whether to damage the masks by scaling.
- rotate: Boolean, whether to damage the masks by rotation.
- dilate: Boolean, whether to damage the masks by dilation.
-
- Returns:
- The damaged version of mask.
- """
- # For now we just do shifting and scaling. Better would be Affine or thin
- # spline plate transformations.
- if shift:
- mask = _shift_mask(mask)
- if scale:
- mask = _scale_mask(mask)
- if rotate:
- mask = _rotate_mask(mask)
- if dilate:
- mask = _dilate_mask(mask)
- return mask
-
-
-def _shift_mask(mask, max_shift_factor=0.05):
- """Damages a mask for a single object by randomly shifting it in numpy.
-
- Args:
- mask: Boolean numpy array of shape(height, width, 1).
- max_shift_factor: Float scalar, the maximum factor for random shifting.
-
- Returns:
- The shifted version of mask.
- """
- nzy, nzx, _ = mask.nonzero()
- h = nzy.max() - nzy.min()
- w = nzx.max() - nzx.min()
- size = np.sqrt(h * w)
- offset = np.random.uniform(-size * max_shift_factor, size * max_shift_factor,
- 2)
- shifted_mask = interpolation.shift(np.squeeze(mask, axis=2),
- offset, order=0).astype('bool')[...,
- np.newaxis]
- return shifted_mask
-
-
-def _scale_mask(mask, scale_amount=0.025):
- """Damages a mask for a single object by randomly scaling it in numpy.
-
- Args:
- mask: Boolean numpy array of shape(height, width, 1).
- scale_amount: Float scalar, the maximum factor for random scaling.
-
- Returns:
- The scaled version of mask.
- """
- nzy, nzx, _ = mask.nonzero()
- cy = 0.5 * (nzy.max() - nzy.min())
- cx = 0.5 * (nzx.max() - nzx.min())
- scale_factor = np.random.uniform(1.0 - scale_amount, 1.0 + scale_amount)
- shift = transform.SimilarityTransform(translation=[-cx, -cy])
- inv_shift = transform.SimilarityTransform(translation=[cx, cy])
- s = transform.SimilarityTransform(scale=[scale_factor, scale_factor])
- m = (shift + (s + inv_shift)).inverse
- scaled_mask = transform.warp(mask, m) > 0.5
- return scaled_mask
-
-
-def _rotate_mask(mask, max_rot_degrees=3.0):
- """Damages a mask for a single object by randomly rotating it in numpy.
-
- Args:
- mask: Boolean numpy array of shape(height, width, 1).
- max_rot_degrees: Float scalar, the maximum number of degrees to rotate.
-
- Returns:
- The scaled version of mask.
- """
- cy = 0.5 * mask.shape[0]
- cx = 0.5 * mask.shape[1]
- rot_degrees = np.random.uniform(-max_rot_degrees, max_rot_degrees)
- shift = transform.SimilarityTransform(translation=[-cx, -cy])
- inv_shift = transform.SimilarityTransform(translation=[cx, cy])
- r = transform.SimilarityTransform(rotation=np.deg2rad(rot_degrees))
- m = (shift + (r + inv_shift)).inverse
- scaled_mask = transform.warp(mask, m) > 0.5
- return scaled_mask
-
-
-def _dilate_mask(mask, dilation_radius=5):
- """Damages a mask for a single object by dilating it in numpy.
-
- Args:
- mask: Boolean numpy array of shape(height, width, 1).
- dilation_radius: Integer, the radius of the used disk structure element.
-
- Returns:
- The dilated version of mask.
- """
- disk = morphology.disk(dilation_radius, dtype=np.bool)
- dilated_mask = morphology.binary_dilation(
- np.squeeze(mask, axis=2), selem=disk)[..., np.newaxis]
- return dilated_mask
diff --git a/research/feelvos/utils/train_utils.py b/research/feelvos/utils/train_utils.py
deleted file mode 100644
index 02a04cd33645931c5c795bef8559c0d3f5c4c23c..0000000000000000000000000000000000000000
--- a/research/feelvos/utils/train_utils.py
+++ /dev/null
@@ -1,269 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Utility functions for training."""
-import collections
-import six
-import tensorflow as tf
-
-from deeplab.core import preprocess_utils
-from deeplab.utils import train_utils
-from feelvos.utils import embedding_utils
-from feelvos.utils import eval_utils
-
-slim = tf.contrib.slim
-add_softmax_cross_entropy_loss_for_each_scale = (
- train_utils.add_softmax_cross_entropy_loss_for_each_scale)
-get_model_gradient_multipliers = train_utils.get_model_gradient_multipliers
-get_model_learning_rate = train_utils.get_model_learning_rate
-resolve_shape = preprocess_utils.resolve_shape
-
-
-def add_triplet_loss_for_each_scale(batch_size, num_frames_per_video,
- embedding_dim, scales_to_embeddings,
- labels, scope):
- """Adds triplet loss for logits of each scale.
-
- Args:
- batch_size: Int, the number of video chunks sampled per batch
- num_frames_per_video: Int, the number of frames per video.
- embedding_dim: Int, the dimension of the learned embedding
- scales_to_embeddings: A map from embedding names for different scales to
- embeddings. The embeddings have shape [batch, embeddings_height,
- embeddings_width, embedding_dim].
- labels: Groundtruth labels with shape [batch, image_height, image_width, 1].
- scope: String, the scope for the loss.
-
- Raises:
- ValueError: labels is None.
- """
- if labels is None:
- raise ValueError('No label for triplet loss.')
- for scale, embeddings in scales_to_embeddings.iteritems():
- loss_scope = None
- if scope:
- loss_scope = '%s_%s' % (scope, scale)
- # Label is downsampled to the same size as logits.
- scaled_labels = tf.image.resize_nearest_neighbor(
- labels,
- resolve_shape(embeddings, 4)[1:3],
- align_corners=True)
- # Reshape from [batch * num_frames, ...] to [batch, num_frames, ...].
- h = tf.shape(embeddings)[1]
- w = tf.shape(embeddings)[2]
- new_labels_shape = tf.stack([batch_size, num_frames_per_video, h, w, 1])
- reshaped_labels = tf.reshape(scaled_labels, new_labels_shape)
- new_embeddings_shape = tf.stack([batch_size, num_frames_per_video, h, w,
- -1])
- reshaped_embeddings = tf.reshape(embeddings, new_embeddings_shape)
-
- with tf.name_scope(loss_scope):
- total_loss = tf.constant(0, dtype=tf.float32)
- for n in range(batch_size):
- embedding = reshaped_embeddings[n]
- label = reshaped_labels[n]
- n_pixels = h * w
- n_anchors_used = 256
- sampled_anchor_indices = tf.random_shuffle(tf.range(n_pixels))[
- :n_anchors_used]
- anchors_pool = tf.reshape(embedding[0], [-1, embedding_dim])
- anchors_pool_classes = tf.reshape(label[0], [-1])
- anchors = tf.gather(anchors_pool, sampled_anchor_indices)
- anchor_classes = tf.gather(anchors_pool_classes, sampled_anchor_indices)
-
- pos_neg_pool = tf.reshape(embedding[1:], [-1, embedding_dim])
- pos_neg_pool_classes = tf.reshape(label[1:], [-1])
- dists = embedding_utils.pairwise_distances(anchors, pos_neg_pool)
- pos_mask = tf.equal(anchor_classes[:, tf.newaxis],
- pos_neg_pool_classes[tf.newaxis, :])
- neg_mask = tf.logical_not(pos_mask)
- pos_mask_f = tf.cast(pos_mask, tf.float32)
- neg_mask_f = tf.cast(neg_mask, tf.float32)
- pos_dists = pos_mask_f * dists + 1e20 * neg_mask_f
- neg_dists = neg_mask_f * dists + 1e20 * pos_mask_f
- pos_dists_min = tf.reduce_min(pos_dists, axis=1)
- neg_dists_min = tf.reduce_min(neg_dists, axis=1)
- margin = 1.0
- loss = tf.nn.relu(pos_dists_min - neg_dists_min + margin)
- # Handle case that no positive is present (per anchor).
- any_pos = tf.reduce_any(pos_mask, axis=1)
- loss *= tf.cast(any_pos, tf.float32)
- # Average over anchors
- loss = tf.reduce_mean(loss, axis=0)
- total_loss += loss
- total_loss /= batch_size
- # Scale the loss up a bit.
- total_loss *= 3.0
- tf.add_to_collection(tf.GraphKeys.LOSSES, total_loss)
-
-
-def add_dynamic_softmax_cross_entropy_loss_for_each_scale(
- scales_to_logits, labels, ignore_label, loss_weight=1.0,
- upsample_logits=True, scope=None, top_k_percent_pixels=1.0,
- hard_example_mining_step=100000):
- """Adds softmax cross entropy loss per scale for logits with varying classes.
-
- Also adds summaries for mIoU.
-
- Args:
- scales_to_logits: A map from logits names for different scales to logits.
- The logits are a list of length batch_size of tensors of shape
- [time, logits_height, logits_width, num_classes].
- labels: Groundtruth labels with shape [batch_size * time, image_height,
- image_width, 1].
- ignore_label: Integer, label to ignore.
- loss_weight: Float, loss weight.
- upsample_logits: Boolean, upsample logits or not.
- scope: String, the scope for the loss.
- top_k_percent_pixels: A float, the value lies in [0.0, 1.0]. When its
- value < 1.0, only compute the loss for the top k percent pixels (e.g.,
- the top 20% pixels). This is useful for hard pixel mining.
- hard_example_mining_step: An integer, the training step in which the
- hard exampling mining kicks off. Note that we gradually reduce the
- mining percent to the top_k_percent_pixels. For example, if
- hard_example_mining_step=100K and top_k_percent_pixels=0.25, then
- mining percent will gradually reduce from 100% to 25% until 100K steps
- after which we only mine top 25% pixels.
-
- Raises:
- ValueError: Label or logits is None.
- """
- if labels is None:
- raise ValueError('No label for softmax cross entropy loss.')
-
- if top_k_percent_pixels < 0 or top_k_percent_pixels > 1:
- raise ValueError('Unexpected value of top_k_percent_pixels.')
-
- for scale, logits in six.iteritems(scales_to_logits):
- loss_scope = None
- if scope:
- loss_scope = '%s_%s' % (scope, scale)
-
- if upsample_logits:
- # Label is not downsampled, and instead we upsample logits.
- assert isinstance(logits, collections.Sequence)
- logits = [tf.image.resize_bilinear(
- x,
- preprocess_utils.resolve_shape(labels, 4)[1:3],
- align_corners=True) for x in logits]
- scaled_labels = labels
- else:
- # Label is downsampled to the same size as logits.
- assert isinstance(logits, collections.Sequence)
- scaled_labels = tf.image.resize_nearest_neighbor(
- labels,
- preprocess_utils.resolve_shape(logits[0], 4)[1:3],
- align_corners=True)
-
- batch_size = len(logits)
- num_time = preprocess_utils.resolve_shape(logits[0])[0]
- reshaped_labels = tf.reshape(
- scaled_labels, ([batch_size, num_time] +
- preprocess_utils.resolve_shape(scaled_labels)[1:]))
- for n, logits_n in enumerate(logits):
- labels_n = reshaped_labels[n]
- labels_n = tf.reshape(labels_n, shape=[-1])
- not_ignore_mask = tf.to_float(tf.not_equal(labels_n,
- ignore_label)) * loss_weight
- num_classes_n = tf.shape(logits_n)[-1]
- one_hot_labels = slim.one_hot_encoding(
- labels_n, num_classes_n, on_value=1.0, off_value=0.0)
- logits_n_flat = tf.reshape(logits_n, shape=[-1, num_classes_n])
- if top_k_percent_pixels == 1.0:
- tf.losses.softmax_cross_entropy(
- one_hot_labels,
- logits_n_flat,
- weights=not_ignore_mask,
- scope=loss_scope)
- else:
- # Only compute the loss for top k percent pixels.
- # First, compute the loss for all pixels. Note we do not put the loss
- # to loss_collection and set reduction = None to keep the shape.
- num_pixels = tf.to_float(tf.shape(logits_n_flat)[0])
- pixel_losses = tf.losses.softmax_cross_entropy(
- one_hot_labels,
- logits_n_flat,
- weights=not_ignore_mask,
- scope='pixel_losses',
- loss_collection=None,
- reduction=tf.losses.Reduction.NONE)
- # Compute the top_k_percent pixels based on current training step.
- if hard_example_mining_step == 0:
- # Directly focus on the top_k pixels.
- top_k_pixels = tf.to_int32(top_k_percent_pixels * num_pixels)
- else:
- # Gradually reduce the mining percent to top_k_percent_pixels.
- global_step = tf.to_float(tf.train.get_or_create_global_step())
- ratio = tf.minimum(1.0, global_step / hard_example_mining_step)
- top_k_pixels = tf.to_int32(
- (ratio * top_k_percent_pixels + (1.0 - ratio)) * num_pixels)
- _, top_k_indices = tf.nn.top_k(pixel_losses,
- k=top_k_pixels,
- sorted=True,
- name='top_k_percent_pixels')
- # Compute the loss for the top k percent pixels.
- tf.losses.softmax_cross_entropy(
- tf.gather(one_hot_labels, top_k_indices),
- tf.gather(logits_n_flat, top_k_indices),
- weights=tf.gather(not_ignore_mask, top_k_indices),
- scope=loss_scope)
-
- pred_n = tf.argmax(logits_n, axis=-1, output_type=tf.int32)[
- ..., tf.newaxis]
- labels_n = labels[n * num_time: (n + 1) * num_time]
- miou = eval_utils.calculate_multi_object_miou_tf(pred_n, labels_n)
- tf.summary.scalar('miou', miou)
-
-
-def get_model_init_fn(train_logdir,
- tf_initial_checkpoint,
- initialize_last_layer,
- last_layers,
- ignore_missing_vars=False):
- """Gets the function initializing model variables from a checkpoint.
-
- Args:
- train_logdir: Log directory for training.
- tf_initial_checkpoint: TensorFlow checkpoint for initialization.
- initialize_last_layer: Initialize last layer or not.
- last_layers: Last layers of the model.
- ignore_missing_vars: Ignore missing variables in the checkpoint.
-
- Returns:
- Initialization function.
- """
- if tf_initial_checkpoint is None:
- tf.logging.info('Not initializing the model from a checkpoint.')
- return None
-
- if tf.train.latest_checkpoint(train_logdir):
- tf.logging.info('Ignoring initialization; other checkpoint exists')
- return None
-
- tf.logging.info('Initializing model from path: %s', tf_initial_checkpoint)
-
- # Variables that will not be restored.
- exclude_list = ['global_step']
- if not initialize_last_layer:
- exclude_list.extend(last_layers)
-
- variables_to_restore = slim.get_variables_to_restore(exclude=exclude_list)
-
- if variables_to_restore:
- return slim.assign_from_checkpoint_fn(
- tf_initial_checkpoint,
- variables_to_restore,
- ignore_missing_vars=ignore_missing_vars)
- return None
diff --git a/research/feelvos/utils/video_input_generator.py b/research/feelvos/utils/video_input_generator.py
deleted file mode 100644
index c0135e50110c677865217c8a3f13d1d1d891f0b2..0000000000000000000000000000000000000000
--- a/research/feelvos/utils/video_input_generator.py
+++ /dev/null
@@ -1,558 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Wrapper for providing semantic segmentation video data."""
-
-import tensorflow as tf
-from feelvos import input_preprocess
-from feelvos import model
-from feelvos.utils import mask_damaging
-from feelvos.utils import train_utils
-
-slim = tf.contrib.slim
-dataset_data_provider = slim.dataset_data_provider
-
-
-MIN_LABEL_COUNT = 10
-
-
-def decode_image_sequence(tensor, image_format='jpeg', shape=None,
- channels=3, raw_dtype=tf.uint8):
- """Decodes a sequence of images.
-
- Args:
- tensor: the tensor of strings to decode, shape: [num_images]
- image_format: a string (possibly tensor) with the format of the image.
- Options include 'jpeg', 'png', and 'raw'.
- shape: a list or tensor of the decoded image shape for a single image.
- channels: if 'shape' is None, the third dimension of the image is set to
- this value.
- raw_dtype: if the image is encoded as raw bytes, this is the method of
- decoding the bytes into values.
- Returns:
- The decoded images with shape [time, height, width, channels].
- """
- handler = slim.tfexample_decoder.Image(
- shape=shape, channels=channels, dtype=raw_dtype, repeated=True)
- return handler.tensors_to_item({'image/encoded': tensor,
- 'image/format': image_format})
-
-
-def _get_data(data_provider, dataset_split, video_frames_are_decoded):
- """Gets data from data provider.
-
- Args:
- data_provider: An object of slim.data_provider.
- dataset_split: Dataset split.
- video_frames_are_decoded: Boolean, whether the video frames are already
- decoded
-
- Returns:
- image: Image Tensor.
- label: Label Tensor storing segmentation annotations.
- object_label: An integer refers to object_label according to labelmap. If
- the example has more than one object_label, take the first one.
- image_name: Image name.
- height: Image height.
- width: Image width.
- video_id: String tensor representing the name of the video.
-
- Raises:
- ValueError: Failed to find label.
- """
-
- if video_frames_are_decoded:
- image, = data_provider.get(['image'])
- else:
- image, = data_provider.get(['image/encoded'])
-
- # Some datasets do not contain image_name.
- if 'image_name' in data_provider.list_items():
- image_name, = data_provider.get(['image_name'])
- else:
- image_name = tf.constant('')
-
- height, width = data_provider.get(['height', 'width'])
-
- label = None
- if dataset_split != 'test':
- if video_frames_are_decoded:
- if 'labels_class' not in data_provider.list_items():
- raise ValueError('Failed to find labels.')
- label, = data_provider.get(['labels_class'])
- else:
- key = 'segmentation/object/encoded'
- if key not in data_provider.list_items():
- raise ValueError('Failed to find labels.')
- label, = data_provider.get([key])
-
- object_label = None
- video_id, = data_provider.get(['video_id'])
-
- return image, label, object_label, image_name, height, width, video_id
-
-
-def _has_foreground_and_background_in_first_frame(label, subsampling_factor):
- """Checks if the labels have foreground and background in the first frame.
-
- Args:
- label: Label tensor of shape [num_frames, height, width, 1].
- subsampling_factor: Integer, the subsampling factor.
-
- Returns:
- Boolean, whether the labels have foreground and background in the first
- frame.
- """
- h, w = train_utils.resolve_shape(label)[1:3]
- label_downscaled = tf.squeeze(
- tf.image.resize_nearest_neighbor(label[0, tf.newaxis],
- [h // subsampling_factor,
- w // subsampling_factor],
- align_corners=True),
- axis=0)
- is_bg = tf.equal(label_downscaled, 0)
- is_fg = tf.logical_not(is_bg)
- # Just using reduce_any was not robust enough, so lets make sure the count
- # is above MIN_LABEL_COUNT.
- fg_count = tf.reduce_sum(tf.cast(is_fg, tf.int32))
- bg_count = tf.reduce_sum(tf.cast(is_bg, tf.int32))
- has_bg = tf.greater_equal(fg_count, MIN_LABEL_COUNT)
- has_fg = tf.greater_equal(bg_count, MIN_LABEL_COUNT)
- return tf.logical_and(has_bg, has_fg)
-
-
-def _has_foreground_and_background_in_first_frame_2(label,
- decoder_output_stride):
- """Checks if the labels have foreground and background in the first frame.
-
- Second attempt, this time we use the actual output dimension for resizing.
-
- Args:
- label: Label tensor of shape [num_frames, height, width, 1].
- decoder_output_stride: Integer, the stride of the decoder output.
-
- Returns:
- Boolean, whether the labels have foreground and background in the first
- frame.
- """
- h, w = train_utils.resolve_shape(label)[1:3]
- h_sub = model.scale_dimension(h, 1.0 / decoder_output_stride)
- w_sub = model.scale_dimension(w, 1.0 / decoder_output_stride)
- label_downscaled = tf.squeeze(
- tf.image.resize_nearest_neighbor(label[0, tf.newaxis], [h_sub, w_sub],
- align_corners=True), axis=0)
- is_bg = tf.equal(label_downscaled, 0)
- is_fg = tf.logical_not(is_bg)
- # Just using reduce_any was not robust enough, so lets make sure the count
- # is above MIN_LABEL_COUNT.
- fg_count = tf.reduce_sum(tf.cast(is_fg, tf.int32))
- bg_count = tf.reduce_sum(tf.cast(is_bg, tf.int32))
- has_bg = tf.greater_equal(fg_count, MIN_LABEL_COUNT)
- has_fg = tf.greater_equal(bg_count, MIN_LABEL_COUNT)
- return tf.logical_and(has_bg, has_fg)
-
-
-def _has_enough_pixels_of_each_object_in_first_frame(
- label, decoder_output_stride):
- """Checks if for each object (incl. background) enough pixels are visible.
-
- During test time, we will usually not see a reference frame in which only
- very few pixels of one object are visible. These cases can be problematic
- during training, especially if more than the 1-nearest neighbor is used.
- That's why this function can be used to detect and filter these cases.
-
- Args:
- label: Label tensor of shape [num_frames, height, width, 1].
- decoder_output_stride: Integer, the stride of the decoder output.
-
- Returns:
- Boolean, whether the labels have enough pixels of each object in the first
- frame.
- """
- h, w = train_utils.resolve_shape(label)[1:3]
- h_sub = model.scale_dimension(h, 1.0 / decoder_output_stride)
- w_sub = model.scale_dimension(w, 1.0 / decoder_output_stride)
- label_downscaled = tf.squeeze(
- tf.image.resize_nearest_neighbor(label[0, tf.newaxis], [h_sub, w_sub],
- align_corners=True), axis=0)
- _, _, counts = tf.unique_with_counts(
- tf.reshape(label_downscaled, [-1]))
- has_enough_pixels_per_object = tf.reduce_all(
- tf.greater_equal(counts, MIN_LABEL_COUNT))
- return has_enough_pixels_per_object
-
-
-def get(dataset,
- num_frames_per_video,
- crop_size,
- batch_size,
- min_resize_value=None,
- max_resize_value=None,
- resize_factor=None,
- min_scale_factor=1.,
- max_scale_factor=1.,
- scale_factor_step_size=0,
- preprocess_image_and_label=True,
- num_readers=1,
- num_threads=1,
- dataset_split=None,
- is_training=True,
- model_variant=None,
- batch_capacity_factor=32,
- video_frames_are_decoded=False,
- decoder_output_stride=None,
- first_frame_finetuning=False,
- sample_only_first_frame_for_finetuning=False,
- sample_adjacent_and_consistent_query_frames=False,
- remap_labels_to_reference_frame=True,
- generate_prev_frame_mask_by_mask_damaging=False,
- three_frame_dataset=False,
- add_prev_frame_label=True):
- """Gets the dataset split for semantic segmentation.
-
- This functions gets the dataset split for semantic segmentation. In
- particular, it is a wrapper of (1) dataset_data_provider which returns the raw
- dataset split, (2) input_preprcess which preprocess the raw data, and (3) the
- Tensorflow operation of batching the preprocessed data. Then, the output could
- be directly used by training, evaluation or visualization.
-
- Args:
- dataset: An instance of slim Dataset.
- num_frames_per_video: The number of frames used per video
- crop_size: Image crop size [height, width].
- batch_size: Batch size.
- min_resize_value: Desired size of the smaller image side.
- max_resize_value: Maximum allowed size of the larger image side.
- resize_factor: Resized dimensions are multiple of factor plus one.
- min_scale_factor: Minimum scale factor value.
- max_scale_factor: Maximum scale factor value.
- scale_factor_step_size: The step size from min scale factor to max scale
- factor. The input is randomly scaled based on the value of
- (min_scale_factor, max_scale_factor, scale_factor_step_size).
- preprocess_image_and_label: Boolean variable specifies if preprocessing of
- image and label will be performed or not.
- num_readers: Number of readers for data provider.
- num_threads: Number of threads for batching data.
- dataset_split: Dataset split.
- is_training: Is training or not.
- model_variant: Model variant (string) for choosing how to mean-subtract the
- images. See feature_extractor.network_map for supported model variants.
- batch_capacity_factor: Batch capacity factor affecting the training queue
- batch capacity.
- video_frames_are_decoded: Boolean, whether the video frames are already
- decoded
- decoder_output_stride: Integer, the stride of the decoder output.
- first_frame_finetuning: Boolean, whether to only sample the first frame
- for fine-tuning.
- sample_only_first_frame_for_finetuning: Boolean, whether to only sample the
- first frame during fine-tuning. This should be False when using lucid or
- wonderland data, but true when fine-tuning on the first frame only.
- Only has an effect if first_frame_finetuning is True.
- sample_adjacent_and_consistent_query_frames: Boolean, if true, the query
- frames (all but the first frame which is the reference frame) will be
- sampled such that they are adjacent video frames and have the same
- crop coordinates and flip augmentation.
- remap_labels_to_reference_frame: Boolean, whether to remap the labels of
- the query frames to match the labels of the (downscaled) reference frame.
- If a query frame contains a label which is not present in the reference,
- it will be mapped to background.
- generate_prev_frame_mask_by_mask_damaging: Boolean, whether to generate
- the masks used as guidance from the previous frame by damaging the
- ground truth mask.
- three_frame_dataset: Boolean, whether the dataset has exactly three frames
- per video of which the first is to be used as reference and the two
- others are consecutive frames to be used as query frames.
- add_prev_frame_label: Boolean, whether to sample one more frame before the
- first query frame to obtain a previous frame label. Only has an effect,
- if sample_adjacent_and_consistent_query_frames is True and
- generate_prev_frame_mask_by_mask_damaging is False.
-
- Returns:
- A dictionary of batched Tensors for semantic segmentation.
-
- Raises:
- ValueError: dataset_split is None, or Failed to find labels.
- """
- if dataset_split is None:
- raise ValueError('Unknown dataset split.')
- if model_variant is None:
- tf.logging.warning('Please specify a model_variant. See '
- 'feature_extractor.network_map for supported model '
- 'variants.')
-
- data_provider = dataset_data_provider.DatasetDataProvider(
- dataset,
- num_readers=num_readers,
- num_epochs=None if is_training else 1,
- shuffle=is_training)
- image, label, object_label, image_name, height, width, video_id = _get_data(
- data_provider, dataset_split, video_frames_are_decoded)
-
- sampling_is_valid = tf.constant(True)
- if num_frames_per_video is not None:
- total_num_frames = tf.shape(image)[0]
- if first_frame_finetuning or three_frame_dataset:
- if sample_only_first_frame_for_finetuning:
- assert not sample_adjacent_and_consistent_query_frames, (
- 'this option does not make sense for sampling only first frame.')
- # Sample the first frame num_frames_per_video times.
- sel_indices = tf.tile(tf.constant(0, dtype=tf.int32)[tf.newaxis],
- multiples=[num_frames_per_video])
- else:
- if sample_adjacent_and_consistent_query_frames:
- if add_prev_frame_label:
- num_frames_per_video += 1
- # Since this is first frame fine-tuning, we'll for now assume that
- # each sequence has exactly 3 images: the ref frame and 2 adjacent
- # query frames.
- assert num_frames_per_video == 3
- with tf.control_dependencies([tf.assert_equal(total_num_frames, 3)]):
- sel_indices = tf.constant([1, 2], dtype=tf.int32)
- else:
- # Sample num_frames_per_video - 1 query frames which are not the
- # first frame.
- sel_indices = tf.random_shuffle(
- tf.range(1, total_num_frames))[:(num_frames_per_video - 1)]
- # Concat first frame as reference frame to the front.
- sel_indices = tf.concat([tf.constant(0, dtype=tf.int32)[tf.newaxis],
- sel_indices], axis=0)
- else:
- if sample_adjacent_and_consistent_query_frames:
- if add_prev_frame_label:
- # Sample one more frame which we can use to provide initial softmax
- # feedback.
- num_frames_per_video += 1
- ref_idx = tf.random_shuffle(tf.range(total_num_frames))[0]
- sampling_is_valid = tf.greater_equal(total_num_frames,
- num_frames_per_video)
- def sample_query_start_idx():
- return tf.random_shuffle(
- tf.range(total_num_frames - num_frames_per_video + 1))[0]
- query_start_idx = tf.cond(sampling_is_valid, sample_query_start_idx,
- lambda: tf.constant(0, dtype=tf.int32))
- def sample_sel_indices():
- return tf.concat(
- [ref_idx[tf.newaxis],
- tf.range(
- query_start_idx,
- query_start_idx + (num_frames_per_video - 1))], axis=0)
- sel_indices = tf.cond(
- sampling_is_valid, sample_sel_indices,
- lambda: tf.zeros((num_frames_per_video,), dtype=tf.int32))
- else:
- # Randomly sample some frames from the video.
- sel_indices = tf.random_shuffle(
- tf.range(total_num_frames))[:num_frames_per_video]
- image = tf.gather(image, sel_indices, axis=0)
- if not video_frames_are_decoded:
- image = decode_image_sequence(image)
-
- if label is not None:
- if num_frames_per_video is not None:
- label = tf.gather(label, sel_indices, axis=0)
- if not video_frames_are_decoded:
- label = decode_image_sequence(label, image_format='png', channels=1)
-
- # Sometimes, label is saved as [num_frames_per_video, height, width] or
- # [num_frames_per_video, height, width, 1]. We change it to be
- # [num_frames_per_video, height, width, 1].
- if label.shape.ndims == 3:
- label = tf.expand_dims(label, 3)
- elif label.shape.ndims == 4 and label.shape.dims[3] == 1:
- pass
- else:
- raise ValueError('Input label shape must be '
- '[num_frames_per_video, height, width],'
- ' or [num_frames, height, width, 1]. '
- 'Got {}'.format(label.shape.ndims))
- label.set_shape([None, None, None, 1])
-
- # Add size of first dimension since tf can't figure it out automatically.
- image.set_shape((num_frames_per_video, None, None, None))
- if label is not None:
- label.set_shape((num_frames_per_video, None, None, None))
-
- preceding_frame_label = None
- if preprocess_image_and_label:
- if num_frames_per_video is None:
- raise ValueError('num_frame_per_video must be specified for preproc.')
- original_images = []
- images = []
- labels = []
- if sample_adjacent_and_consistent_query_frames:
- num_frames_individual_preproc = 1
- else:
- num_frames_individual_preproc = num_frames_per_video
- for frame_idx in range(num_frames_individual_preproc):
- original_image_t, image_t, label_t = (
- input_preprocess.preprocess_image_and_label(
- image[frame_idx],
- label[frame_idx],
- crop_height=crop_size[0] if crop_size is not None else None,
- crop_width=crop_size[1] if crop_size is not None else None,
- min_resize_value=min_resize_value,
- max_resize_value=max_resize_value,
- resize_factor=resize_factor,
- min_scale_factor=min_scale_factor,
- max_scale_factor=max_scale_factor,
- scale_factor_step_size=scale_factor_step_size,
- ignore_label=dataset.ignore_label,
- is_training=is_training,
- model_variant=model_variant))
- original_images.append(original_image_t)
- images.append(image_t)
- labels.append(label_t)
- if sample_adjacent_and_consistent_query_frames:
- imgs_for_preproc = [image[frame_idx] for frame_idx in
- range(1, num_frames_per_video)]
- labels_for_preproc = [label[frame_idx] for frame_idx in
- range(1, num_frames_per_video)]
- original_image_rest, image_rest, label_rest = (
- input_preprocess.preprocess_images_and_labels_consistently(
- imgs_for_preproc,
- labels_for_preproc,
- crop_height=crop_size[0] if crop_size is not None else None,
- crop_width=crop_size[1] if crop_size is not None else None,
- min_resize_value=min_resize_value,
- max_resize_value=max_resize_value,
- resize_factor=resize_factor,
- min_scale_factor=min_scale_factor,
- max_scale_factor=max_scale_factor,
- scale_factor_step_size=scale_factor_step_size,
- ignore_label=dataset.ignore_label,
- is_training=is_training,
- model_variant=model_variant))
- original_images.extend(original_image_rest)
- images.extend(image_rest)
- labels.extend(label_rest)
- assert len(original_images) == num_frames_per_video
- assert len(images) == num_frames_per_video
- assert len(labels) == num_frames_per_video
-
- if remap_labels_to_reference_frame:
- # Remap labels to indices into the labels of the (downscaled) reference
- # frame, or 0, i.e. background, for labels which are not present
- # in the reference.
- reference_labels = labels[0][tf.newaxis]
- h, w = train_utils.resolve_shape(reference_labels)[1:3]
- embedding_height = model.scale_dimension(
- h, 1.0 / decoder_output_stride)
- embedding_width = model.scale_dimension(
- w, 1.0 / decoder_output_stride)
- reference_labels_embedding_size = tf.squeeze(
- tf.image.resize_nearest_neighbor(
- reference_labels, tf.stack([embedding_height, embedding_width]),
- align_corners=True),
- axis=0)
- # Get sorted unique labels in the reference frame.
- labels_in_ref_frame, _ = tf.unique(
- tf.reshape(reference_labels_embedding_size, [-1]))
- labels_in_ref_frame = tf.contrib.framework.sort(labels_in_ref_frame)
- for idx in range(1, len(labels)):
- ref_label_mask = tf.equal(
- labels[idx],
- labels_in_ref_frame[tf.newaxis, tf.newaxis, :])
- remapped = tf.argmax(tf.cast(ref_label_mask, tf.uint8), axis=-1,
- output_type=tf.int32)
- # Set to 0 if label is not present
- is_in_ref = tf.reduce_any(ref_label_mask, axis=-1)
- remapped *= tf.cast(is_in_ref, tf.int32)
- labels[idx] = remapped[..., tf.newaxis]
-
- if sample_adjacent_and_consistent_query_frames:
- if first_frame_finetuning and generate_prev_frame_mask_by_mask_damaging:
- preceding_frame_label = mask_damaging.damage_masks(labels[1])
- elif add_prev_frame_label:
- # Discard the image of the additional frame and take the label as
- # initialization for softmax feedback.
- original_images = [original_images[0]] + original_images[2:]
- preceding_frame_label = labels[1]
- images = [images[0]] + images[2:]
- labels = [labels[0]] + labels[2:]
- num_frames_per_video -= 1
-
- original_image = tf.stack(original_images, axis=0)
- image = tf.stack(images, axis=0)
- label = tf.stack(labels, axis=0)
- else:
- if label is not None:
- # Need to set label shape due to batching.
- label.set_shape([num_frames_per_video,
- None if crop_size is None else crop_size[0],
- None if crop_size is None else crop_size[1],
- 1])
- original_image = tf.to_float(tf.zeros_like(label))
- if crop_size is None:
- height = tf.shape(image)[1]
- width = tf.shape(image)[2]
- else:
- height = crop_size[0]
- width = crop_size[1]
-
- sample = {'image': image,
- 'image_name': image_name,
- 'height': height,
- 'width': width,
- 'video_id': video_id}
- if label is not None:
- sample['label'] = label
-
- if object_label is not None:
- sample['object_label'] = object_label
-
- if preceding_frame_label is not None:
- sample['preceding_frame_label'] = preceding_frame_label
-
- if not is_training:
- # Original image is only used during visualization.
- sample['original_image'] = original_image
-
- if is_training:
- if first_frame_finetuning:
- keep_input = tf.constant(True)
- else:
- keep_input = tf.logical_and(sampling_is_valid, tf.logical_and(
- _has_enough_pixels_of_each_object_in_first_frame(
- label, decoder_output_stride),
- _has_foreground_and_background_in_first_frame_2(
- label, decoder_output_stride)))
-
- batched = tf.train.maybe_batch(sample,
- keep_input=keep_input,
- batch_size=batch_size,
- num_threads=num_threads,
- capacity=batch_capacity_factor * batch_size,
- dynamic_pad=True)
- else:
- batched = tf.train.batch(sample,
- batch_size=batch_size,
- num_threads=num_threads,
- capacity=batch_capacity_factor * batch_size,
- dynamic_pad=True)
-
- # Flatten from [batch, num_frames_per_video, ...] to
- # batch * num_frames_per_video, ...].
- cropped_height = train_utils.resolve_shape(batched['image'])[2]
- cropped_width = train_utils.resolve_shape(batched['image'])[3]
- if num_frames_per_video is None:
- first_dim = -1
- else:
- first_dim = batch_size * num_frames_per_video
- batched['image'] = tf.reshape(batched['image'],
- [first_dim, cropped_height, cropped_width, 3])
- if label is not None:
- batched['label'] = tf.reshape(batched['label'],
- [first_dim, cropped_height, cropped_width, 1])
- return batched
diff --git a/research/feelvos/vis_video.py b/research/feelvos/vis_video.py
deleted file mode 100644
index 211bccf52acdef83aca298285fc473748126de02..0000000000000000000000000000000000000000
--- a/research/feelvos/vis_video.py
+++ /dev/null
@@ -1,500 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Segmentation results evaluation and visualization for videos using attention.
-"""
-
-import math
-import os
-import time
-import numpy as np
-
-import tensorflow as tf
-
-from feelvos import common
-from feelvos import model
-from feelvos.datasets import video_dataset
-from feelvos.utils import embedding_utils
-from feelvos.utils import eval_utils
-from feelvos.utils import video_input_generator
-
-
-slim = tf.contrib.slim
-flags = tf.app.flags
-FLAGS = flags.FLAGS
-
-flags.DEFINE_integer('eval_interval_secs', 60 * 5,
- 'How often (in seconds) to run evaluation.')
-
-flags.DEFINE_string('master', '', 'BNS name of the tensorflow server')
-
-flags.DEFINE_integer('vis_batch_size', 1,
- 'The number of images in each batch during evaluation.')
-
-flags.DEFINE_string('vis_logdir', None, 'Where to write the event logs.')
-
-flags.DEFINE_string('checkpoint_dir', None, 'Directory of model checkpoints.')
-
-flags.DEFINE_integer('output_stride', 8,
- 'The ratio of input to output spatial resolution.')
-
-flags.DEFINE_string('dataset', 'davis_2016',
- 'Name of the segmentation dataset.')
-
-flags.DEFINE_string('vis_split', 'val',
- 'Which split of the dataset used for visualizing results')
-
-flags.DEFINE_string(
- 'dataset_dir',
- '/cns/is-d/home/lcchen/data/pascal_voc_seg/example_sstables',
- 'Where the dataset resides.')
-
-flags.DEFINE_integer('num_vis_examples', -1,
- 'Number of examples for visualization. If -1, use all '
- 'samples in the vis data.')
-
-flags.DEFINE_multi_integer('atrous_rates', None,
- 'Atrous rates for atrous spatial pyramid pooling.')
-
-flags.DEFINE_bool('save_segmentations', False, 'Whether to save the '
- 'segmentation masks as '
- 'png images. Might be slow '
- 'on cns.')
-
-flags.DEFINE_bool('save_embeddings', False, 'Whether to save the embeddings as'
- 'pickle. Might be slow on cns.')
-
-flags.DEFINE_bool('eval_once_and_quit', False,
- 'Whether to just run the eval a single time and quit '
- 'afterwards. Otherwise, the eval is run in a loop with '
- 'new checkpoints.')
-
-flags.DEFINE_boolean('first_frame_finetuning', False,
- 'Whether to only sample the first frame for fine-tuning.')
-
-# the folder where segmentations are saved.
-_SEGMENTATION_SAVE_FOLDER = 'segmentation'
-_EMBEDDINGS_SAVE_FOLDER = 'embeddings'
-
-
-def _process_seq_data(segmentation_dir, embeddings_dir, seq_name,
- predicted_labels, gt_labels, embeddings):
- """Calculates the sequence IoU and optionally save the segmentation masks.
-
- Args:
- segmentation_dir: Directory in which the segmentation results are stored.
- embeddings_dir: Directory in which the embeddings are stored.
- seq_name: String, the name of the sequence.
- predicted_labels: Int64 np.array of shape [n_frames, height, width].
- gt_labels: Ground truth labels, Int64 np.array of shape
- [n_frames, height, width].
- embeddings: Float32 np.array of embeddings of shape
- [n_frames, decoder_height, decoder_width, embedding_dim], or None.
-
- Returns:
- The IoU for the sequence (float).
- """
- sequence_dir = os.path.join(segmentation_dir, seq_name)
- tf.gfile.MakeDirs(sequence_dir)
- embeddings_seq_dir = os.path.join(embeddings_dir, seq_name)
- tf.gfile.MakeDirs(embeddings_seq_dir)
- label_set = np.unique(gt_labels[0])
- ious = []
- assert len(predicted_labels) == len(gt_labels)
- if embeddings is not None:
- assert len(predicted_labels) == len(embeddings)
- for t, (predicted_label, gt_label) in enumerate(
- zip(predicted_labels, gt_labels)):
- if FLAGS.save_segmentations:
- seg_filename = os.path.join(segmentation_dir, seq_name, '%05d.png' % t)
- eval_utils.save_segmentation_with_colormap(seg_filename, predicted_label)
- if FLAGS.save_embeddings:
- embedding_filename = os.path.join(embeddings_dir, seq_name,
- '%05d.npy' % t)
- assert embeddings is not None
- eval_utils.save_embeddings(embedding_filename, embeddings[t])
- object_ious_t = eval_utils.calculate_multi_object_ious(
- predicted_label, gt_label, label_set)
- ious.append(object_ious_t)
- # First and last frame are excluded in DAVIS eval.
- seq_ious = np.mean(ious[1:-1], axis=0)
- tf.logging.info('seq ious: %s %s', seq_name, seq_ious)
- return seq_ious
-
-
-def create_predictions(samples, reference_labels, first_frame_img,
- model_options):
- """Predicts segmentation labels for each frame of the video.
-
- Slower version than create_predictions_fast, but does support more options.
-
- Args:
- samples: Dictionary of input samples.
- reference_labels: Int tensor of shape [1, height, width, 1].
- first_frame_img: Float32 tensor of shape [height, width, 3].
- model_options: An InternalModelOptions instance to configure models.
-
- Returns:
- predicted_labels: Int tensor of shape [time, height, width] of
- predicted labels for each frame.
- all_embeddings: Float32 tensor of shape
- [time, height, width, embedding_dim], or None.
- """
-
- def predict(args, imgs):
- """Predicts segmentation labels and softmax probabilities for each image.
-
- Args:
- args: A tuple of (predictions, softmax_probabilities), where predictions
- is an int tensor of shape [1, h, w] and softmax_probabilities is a
- float32 tensor of shape [1, h_decoder, w_decoder, n_objects].
- imgs: Either a one-tuple of the image to predict labels for of shape
- [h, w, 3], or pair of previous frame and current frame image.
-
- Returns:
- predictions: The predicted labels as int tensor of shape [1, h, w].
- softmax_probabilities: The softmax probabilities of shape
- [1, h_decoder, w_decoder, n_objects].
- """
- if FLAGS.save_embeddings:
- last_frame_predictions, last_softmax_probabilities, _ = args
- else:
- last_frame_predictions, last_softmax_probabilities = args
-
- if FLAGS.also_attend_to_previous_frame or FLAGS.use_softmax_feedback:
- ref_labels_to_use = tf.concat(
- [reference_labels, last_frame_predictions[..., tf.newaxis]],
- axis=0)
- else:
- ref_labels_to_use = reference_labels
-
- predictions, softmax_probabilities = model.predict_labels(
- tf.stack((first_frame_img,) + imgs),
- model_options=model_options,
- image_pyramid=FLAGS.image_pyramid,
- embedding_dimension=FLAGS.embedding_dimension,
- reference_labels=ref_labels_to_use,
- k_nearest_neighbors=FLAGS.k_nearest_neighbors,
- use_softmax_feedback=FLAGS.use_softmax_feedback,
- initial_softmax_feedback=last_softmax_probabilities,
- embedding_seg_feature_dimension=
- FLAGS.embedding_seg_feature_dimension,
- embedding_seg_n_layers=FLAGS.embedding_seg_n_layers,
- embedding_seg_kernel_size=FLAGS.embedding_seg_kernel_size,
- embedding_seg_atrous_rates=FLAGS.embedding_seg_atrous_rates,
- also_return_softmax_probabilities=True,
- num_frames_per_video=
- (3 if FLAGS.also_attend_to_previous_frame or
- FLAGS.use_softmax_feedback else 2),
- normalize_nearest_neighbor_distances=
- FLAGS.normalize_nearest_neighbor_distances,
- also_attend_to_previous_frame=FLAGS.also_attend_to_previous_frame,
- use_local_previous_frame_attention=
- FLAGS.use_local_previous_frame_attention,
- previous_frame_attention_window_size=
- FLAGS.previous_frame_attention_window_size,
- use_first_frame_matching=FLAGS.use_first_frame_matching
- )
- predictions = tf.cast(predictions[common.OUTPUT_TYPE], tf.int32)
-
- if FLAGS.save_embeddings:
- names = [n.name for n in tf.get_default_graph().as_graph_def().node]
- embedding_names = [x for x in names if 'embeddings' in x]
- # This will crash when multi-scale inference is used.
- assert len(embedding_names) == 1, len(embedding_names)
- embedding_name = embedding_names[0] + ':0'
- embeddings = tf.get_default_graph().get_tensor_by_name(embedding_name)
- return predictions, softmax_probabilities, embeddings
- else:
- return predictions, softmax_probabilities
-
- init_labels = tf.squeeze(reference_labels, axis=-1)
- init_softmax = embedding_utils.create_initial_softmax_from_labels(
- reference_labels, reference_labels, common.parse_decoder_output_stride(),
- reduce_labels=False)
- if FLAGS.save_embeddings:
- decoder_height = tf.shape(init_softmax)[1]
- decoder_width = tf.shape(init_softmax)[2]
- n_frames = (3 if FLAGS.also_attend_to_previous_frame
- or FLAGS.use_softmax_feedback else 2)
- embeddings_init = tf.zeros((n_frames, decoder_height, decoder_width,
- FLAGS.embedding_dimension))
- init = (init_labels, init_softmax, embeddings_init)
- else:
- init = (init_labels, init_softmax)
- # Do not eval the first frame again but concat the first frame ground
- # truth instead.
- if FLAGS.also_attend_to_previous_frame or FLAGS.use_softmax_feedback:
- elems = (samples[common.IMAGE][:-1], samples[common.IMAGE][1:])
- else:
- elems = (samples[common.IMAGE][1:],)
- res = tf.scan(predict, elems,
- initializer=init,
- parallel_iterations=1,
- swap_memory=True)
- if FLAGS.save_embeddings:
- predicted_labels, _, all_embeddings = res
- first_frame_embeddings = all_embeddings[0, 0, tf.newaxis]
- other_frame_embeddings = all_embeddings[:, -1]
- all_embeddings = tf.concat(
- [first_frame_embeddings, other_frame_embeddings], axis=0)
- else:
- predicted_labels, _ = res
- all_embeddings = None
- predicted_labels = tf.concat([reference_labels[..., 0],
- tf.squeeze(predicted_labels, axis=1)],
- axis=0)
- return predicted_labels, all_embeddings
-
-
-def create_predictions_fast(samples, reference_labels, first_frame_img,
- model_options):
- """Predicts segmentation labels for each frame of the video.
-
- Faster version than create_predictions, but does not support all options.
-
- Args:
- samples: Dictionary of input samples.
- reference_labels: Int tensor of shape [1, height, width, 1].
- first_frame_img: Float32 tensor of shape [height, width, 3].
- model_options: An InternalModelOptions instance to configure models.
-
- Returns:
- predicted_labels: Int tensor of shape [time, height, width] of
- predicted labels for each frame.
- all_embeddings: Float32 tensor of shape
- [time, height, width, embedding_dim], or None.
-
- Raises:
- ValueError: If FLAGS.save_embeddings is True, FLAGS.use_softmax_feedback is
- False, or FLAGS.also_attend_to_previous_frame is False.
- """
- if FLAGS.save_embeddings:
- raise ValueError('save_embeddings does not work with '
- 'create_predictions_fast. Use the slower '
- 'create_predictions instead.')
- if not FLAGS.use_softmax_feedback:
- raise ValueError('use_softmax_feedback must be True for '
- 'create_predictions_fast. Use the slower '
- 'create_predictions instead.')
- if not FLAGS.also_attend_to_previous_frame:
- raise ValueError('also_attend_to_previous_frame must be True for '
- 'create_predictions_fast. Use the slower '
- 'create_predictions instead.')
- # Extract embeddings for first frame and prepare initial predictions.
- first_frame_embeddings = embedding_utils.get_embeddings(
- first_frame_img[tf.newaxis], model_options, FLAGS.embedding_dimension)
- init_labels = tf.squeeze(reference_labels, axis=-1)
- init_softmax = embedding_utils.create_initial_softmax_from_labels(
- reference_labels, reference_labels, common.parse_decoder_output_stride(),
- reduce_labels=False)
- init = (init_labels, init_softmax, first_frame_embeddings)
-
- def predict(args, img):
- """Predicts segmentation labels and softmax probabilities for each image.
-
- Args:
- args: tuple of
- (predictions, softmax_probabilities, last_frame_embeddings), where
- predictions is an int tensor of shape [1, h, w],
- softmax_probabilities is a float32 tensor of shape
- [1, h_decoder, w_decoder, n_objects],
- and last_frame_embeddings is a float32 tensor of shape
- [h_decoder, w_decoder, embedding_dimension].
- img: Image to predict labels for of shape [h, w, 3].
-
- Returns:
- predictions: The predicted labels as int tensor of shape [1, h, w].
- softmax_probabilities: The softmax probabilities of shape
- [1, h_decoder, w_decoder, n_objects].
- """
- (last_frame_predictions, last_softmax_probabilities,
- prev_frame_embeddings) = args
- ref_labels_to_use = tf.concat(
- [reference_labels, last_frame_predictions[..., tf.newaxis]],
- axis=0)
-
- predictions, softmax_probabilities, embeddings = model.predict_labels(
- img[tf.newaxis],
- model_options=model_options,
- image_pyramid=FLAGS.image_pyramid,
- embedding_dimension=FLAGS.embedding_dimension,
- reference_labels=ref_labels_to_use,
- k_nearest_neighbors=FLAGS.k_nearest_neighbors,
- use_softmax_feedback=FLAGS.use_softmax_feedback,
- initial_softmax_feedback=last_softmax_probabilities,
- embedding_seg_feature_dimension=
- FLAGS.embedding_seg_feature_dimension,
- embedding_seg_n_layers=FLAGS.embedding_seg_n_layers,
- embedding_seg_kernel_size=FLAGS.embedding_seg_kernel_size,
- embedding_seg_atrous_rates=FLAGS.embedding_seg_atrous_rates,
- also_return_softmax_probabilities=True,
- num_frames_per_video=1,
- normalize_nearest_neighbor_distances=
- FLAGS.normalize_nearest_neighbor_distances,
- also_attend_to_previous_frame=FLAGS.also_attend_to_previous_frame,
- use_local_previous_frame_attention=
- FLAGS.use_local_previous_frame_attention,
- previous_frame_attention_window_size=
- FLAGS.previous_frame_attention_window_size,
- use_first_frame_matching=FLAGS.use_first_frame_matching,
- also_return_embeddings=True,
- ref_embeddings=(first_frame_embeddings, prev_frame_embeddings)
- )
- predictions = tf.cast(predictions[common.OUTPUT_TYPE], tf.int32)
- return predictions, softmax_probabilities, embeddings
-
- # Do not eval the first frame again but concat the first frame ground
- # truth instead.
- # If you have a lot of GPU memory, you can try to set swap_memory=False,
- # and/or parallel_iterations=2.
- elems = samples[common.IMAGE][1:]
- res = tf.scan(predict, elems,
- initializer=init,
- parallel_iterations=1,
- swap_memory=True)
- predicted_labels, _, _ = res
- predicted_labels = tf.concat([reference_labels[..., 0],
- tf.squeeze(predicted_labels, axis=1)],
- axis=0)
- return predicted_labels
-
-
-def main(unused_argv):
- if FLAGS.vis_batch_size != 1:
- raise ValueError('Only batch size 1 is supported for now')
-
- data_type = 'tf_sequence_example'
- # Get dataset-dependent information.
- dataset = video_dataset.get_dataset(
- FLAGS.dataset,
- FLAGS.vis_split,
- dataset_dir=FLAGS.dataset_dir,
- data_type=data_type)
-
- # Prepare for visualization.
- tf.gfile.MakeDirs(FLAGS.vis_logdir)
- segmentation_dir = os.path.join(FLAGS.vis_logdir, _SEGMENTATION_SAVE_FOLDER)
- tf.gfile.MakeDirs(segmentation_dir)
- embeddings_dir = os.path.join(FLAGS.vis_logdir, _EMBEDDINGS_SAVE_FOLDER)
- tf.gfile.MakeDirs(embeddings_dir)
- num_vis_examples = (dataset.num_videos if (FLAGS.num_vis_examples < 0)
- else FLAGS.num_vis_examples)
- if FLAGS.first_frame_finetuning:
- num_vis_examples = 1
-
- tf.logging.info('Visualizing on %s set', FLAGS.vis_split)
- g = tf.Graph()
- with g.as_default():
- # Without setting device to CPU we run out of memory.
- with tf.device('cpu:0'):
- samples = video_input_generator.get(
- dataset,
- None,
- None,
- FLAGS.vis_batch_size,
- min_resize_value=FLAGS.min_resize_value,
- max_resize_value=FLAGS.max_resize_value,
- resize_factor=FLAGS.resize_factor,
- dataset_split=FLAGS.vis_split,
- is_training=False,
- model_variant=FLAGS.model_variant,
- preprocess_image_and_label=False,
- remap_labels_to_reference_frame=False)
- samples[common.IMAGE] = tf.cast(samples[common.IMAGE], tf.float32)
- samples[common.LABEL] = tf.cast(samples[common.LABEL], tf.int32)
- first_frame_img = samples[common.IMAGE][0]
- reference_labels = samples[common.LABEL][0, tf.newaxis]
- gt_labels = tf.squeeze(samples[common.LABEL], axis=-1)
- seq_name = samples[common.VIDEO_ID][0]
-
- model_options = common.VideoModelOptions(
- outputs_to_num_classes={common.OUTPUT_TYPE: dataset.num_classes},
- crop_size=None,
- atrous_rates=FLAGS.atrous_rates,
- output_stride=FLAGS.output_stride)
-
- all_embeddings = None
- predicted_labels = create_predictions_fast(
- samples, reference_labels, first_frame_img, model_options)
- # If you need more options like saving embeddings, replace the call to
- # create_predictions_fast with create_predictions.
-
- tf.train.get_or_create_global_step()
- saver = tf.train.Saver(slim.get_variables_to_restore())
- sv = tf.train.Supervisor(graph=g,
- logdir=FLAGS.vis_logdir,
- init_op=tf.global_variables_initializer(),
- summary_op=None,
- summary_writer=None,
- global_step=None,
- saver=saver)
- num_batches = int(
- math.ceil(num_vis_examples / float(FLAGS.vis_batch_size)))
- last_checkpoint = None
-
- # Infinite loop to visualize the results when new checkpoint is created.
- while True:
- last_checkpoint = slim.evaluation.wait_for_new_checkpoint(
- FLAGS.checkpoint_dir, last_checkpoint)
- start = time.time()
- tf.logging.info(
- 'Starting visualization at ' + time.strftime('%Y-%m-%d-%H:%M:%S',
- time.gmtime()))
- tf.logging.info('Visualizing with model %s', last_checkpoint)
-
- all_ious = []
- with sv.managed_session(FLAGS.master,
- start_standard_services=False) as sess:
- sv.start_queue_runners(sess)
- sv.saver.restore(sess, last_checkpoint)
-
- for batch in range(num_batches):
- ops = [predicted_labels, gt_labels, seq_name]
- if FLAGS.save_embeddings:
- ops.append(all_embeddings)
- tf.logging.info('Visualizing batch %d / %d', batch + 1, num_batches)
- res = sess.run(ops)
- tf.logging.info('Forwarding done')
- pred_labels_val, gt_labels_val, seq_name_val = res[:3]
- if FLAGS.save_embeddings:
- all_embeddings_val = res[3]
- else:
- all_embeddings_val = None
- seq_ious = _process_seq_data(segmentation_dir, embeddings_dir,
- seq_name_val, pred_labels_val,
- gt_labels_val, all_embeddings_val)
- all_ious.append(seq_ious)
- all_ious = np.concatenate(all_ious, axis=0)
- tf.logging.info('n_seqs %s, mIoU %f', all_ious.shape, all_ious.mean())
- tf.logging.info(
- 'Finished visualization at ' + time.strftime('%Y-%m-%d-%H:%M:%S',
- time.gmtime()))
- result_dir = FLAGS.vis_logdir + '/results/'
- tf.gfile.MakeDirs(result_dir)
- with tf.gfile.GFile(result_dir + seq_name_val + '.txt', 'w') as f:
- f.write(str(all_ious))
- if FLAGS.first_frame_finetuning or FLAGS.eval_once_and_quit:
- break
- time_to_next_eval = start + FLAGS.eval_interval_secs - time.time()
- if time_to_next_eval > 0:
- time.sleep(time_to_next_eval)
-
-
-if __name__ == '__main__':
- flags.mark_flag_as_required('checkpoint_dir')
- flags.mark_flag_as_required('vis_logdir')
- tf.logging.set_verbosity(tf.logging.INFO)
- tf.app.run()
diff --git a/research/fivo/.gitattributes b/research/fivo/.gitattributes
deleted file mode 100644
index f706c0421d718f8af8e62d96d69101fe383d2b4f..0000000000000000000000000000000000000000
--- a/research/fivo/.gitattributes
+++ /dev/null
@@ -1,2 +0,0 @@
-*.pkl binary
-*.tfrecord binary
diff --git a/research/fivo/.gitignore b/research/fivo/.gitignore
deleted file mode 100644
index af2f537516daf33fdaf579436dfa33fdd9044f49..0000000000000000000000000000000000000000
--- a/research/fivo/.gitignore
+++ /dev/null
@@ -1,104 +0,0 @@
-# Byte-compiled / optimized / DLL files
-__pycache__/
-*.py[cod]
-*$py.class
-
-# C extensions
-*.so
-
-# Distribution / packaging
-.Python
-build/
-develop-eggs/
-dist/
-downloads/
-eggs/
-.eggs/
-lib/
-lib64/
-parts/
-sdist/
-var/
-wheels/
-*.egg-info/
-.installed.cfg
-*.egg
-MANIFEST
-
-# PyInstaller
-# Usually these files are written by a python script from a template
-# before PyInstaller builds the exe, so as to inject date/other infos into it.
-*.manifest
-*.spec
-
-# Installer logs
-pip-log.txt
-pip-delete-this-directory.txt
-
-# Unit test / coverage reports
-htmlcov/
-.tox/
-.coverage
-.coverage.*
-.cache
-nosetests.xml
-coverage.xml
-*.cover
-.hypothesis/
-
-# Translations
-*.mo
-*.pot
-
-# Django stuff:
-*.log
-.static_storage/
-.media/
-local_settings.py
-
-# Flask stuff:
-instance/
-.webassets-cache
-
-# Scrapy stuff:
-.scrapy
-
-# Sphinx documentation
-docs/_build/
-
-# PyBuilder
-target/
-
-# Jupyter Notebook
-.ipynb_checkpoints
-
-# pyenv
-.python-version
-
-# celery beat schedule file
-celerybeat-schedule
-
-# SageMath parsed files
-*.sage.py
-
-# Environments
-.env
-.venv
-env/
-venv/
-ENV/
-env.bak/
-venv.bak/
-
-# Spyder project settings
-.spyderproject
-.spyproject
-
-# Rope project settings
-.ropeproject
-
-# mkdocs documentation
-/site
-
-# mypy
-.mypy_cache/
diff --git a/research/fivo/README.md b/research/fivo/README.md
deleted file mode 100644
index 36d355b1b2961f2c8c8b721b5ce13c0c3eab1e8b..0000000000000000000000000000000000000000
--- a/research/fivo/README.md
+++ /dev/null
@@ -1,215 +0,0 @@
-
-
-
-
-# Filtering Variational Objectives
-
-This folder contains a TensorFlow implementation of the algorithms from
-
-Chris J. Maddison\*, Dieterich Lawson\*, George Tucker\*, Nicolas Heess, Mohammad Norouzi, Andriy Mnih, Arnaud Doucet, and Yee Whye Teh. "Filtering Variational Objectives." NIPS 2017.
-
-[https://arxiv.org/abs/1705.09279](https://arxiv.org/abs/1705.09279)
-
-This code implements 3 different bounds for training sequential latent variable models: the evidence lower bound (ELBO), the importance weighted auto-encoder bound (IWAE), and our bound, the filtering variational objective (FIVO).
-
-Additionally it contains several sequential latent variable model implementations:
-
-* Variational recurrent neural network (VRNN)
-* Stochastic recurrent neural network (SRNN)
-* Gaussian hidden Markov model with linear conditionals (GHMM)
-
-The VRNN and SRNN can be trained for sequence modeling of pianoroll and speech data. The GHMM is trainable on a synthetic dataset, useful as a simple example of an analytically tractable model.
-
-#### Directory Structure
-The important parts of the code are organized as follows.
-
-```
-run_fivo.py # main script, contains flag definitions
-fivo
-├─smc.py # a sequential Monte Carlo implementation
-├─bounds.py # code for computing each bound, uses smc.py
-├─runners.py # code for VRNN and SRNN training and evaluation
-├─ghmm_runners.py # code for GHMM training and evaluation
-├─data
-| ├─datasets.py # readers for pianoroll and speech datasets
-| ├─calculate_pianoroll_mean.py # preprocesses the pianoroll datasets
-| └─create_timit_dataset.py # preprocesses the TIMIT dataset
-└─models
- ├─base.py # base classes used in other models
- ├─vrnn.py # VRNN implementation
- ├─srnn.py # SRNN implementation
- └─ghmm.py # Gaussian hidden Markov model (GHMM) implementation
-bin
-├─run_train.sh # an example script that runs training
-├─run_eval.sh # an example script that runs evaluation
-├─run_sample.sh # an example script that runs sampling
-├─run_tests.sh # a script that runs all tests
-└─download_pianorolls.sh # a script that downloads pianoroll files
-```
-
-### Pianorolls
-
-Requirements before we start:
-
-* TensorFlow (see [tensorflow.org](http://tensorflow.org) for how to install)
-* [scipy](https://www.scipy.org/)
-* [sonnet](https://github.com/deepmind/sonnet)
-
-
-#### Download the Data
-
-The pianoroll datasets are encoded as pickled sparse arrays and are available at [http://www-etud.iro.umontreal.ca/~boulanni/icml2012](http://www-etud.iro.umontreal.ca/~boulanni/icml2012). You can use the script `bin/download_pianorolls.sh` to download the files into a directory of your choosing.
-```
-export PIANOROLL_DIR=~/pianorolls
-mkdir $PIANOROLL_DIR
-sh bin/download_pianorolls.sh $PIANOROLL_DIR
-```
-
-#### Preprocess the Data
-
-The script `calculate_pianoroll_mean.py` loads a pianoroll pickle file, calculates the mean, updates the pickle file to include the mean under the key `train_mean`, and writes the file back to disk in-place. You should do this for all pianoroll datasets you wish to train on.
-
-```
-python data/calculate_pianoroll_mean.py --in_file=$PIANOROLL_DIR/piano-midi.de.pkl
-python data/calculate_pianoroll_mean.py --in_file=$PIANOROLL_DIR/nottingham.de.pkl
-python data/calculate_pianoroll_mean.py --in_file=$PIANOROLL_DIR/musedata.pkl
-python data/calculate_pianoroll_mean.py --in_file=$PIANOROLL_DIR/jsb.pkl
-```
-
-#### Training
-
-Now we can train a model. Here is the command for a standard training run, taken from `bin/run_train.sh`:
-```
-python run_fivo.py \
- --mode=train \
- --logdir=/tmp/fivo \
- --model=vrnn \
- --bound=fivo \
- --summarize_every=100 \
- --batch_size=4 \
- --num_samples=4 \
- --learning_rate=0.0001 \
- --dataset_path="$PIANOROLL_DIR/jsb.pkl" \
- --dataset_type="pianoroll"
-```
-
-You should see output that looks something like this (with extra logging cruft):
-
-```
-Saving checkpoints for 0 into /tmp/fivo/model.ckpt.
-Step 1, fivo bound per timestep: -11.322491
-global_step/sec: 7.49971
-Step 101, fivo bound per timestep: -11.399275
-global_step/sec: 8.04498
-Step 201, fivo bound per timestep: -11.174991
-global_step/sec: 8.03989
-Step 301, fivo bound per timestep: -11.073008
-```
-#### Evaluation
-
-You can also evaluate saved checkpoints. The `eval` mode loads a model checkpoint, tests its performance on all items in a dataset, and reports the log-likelihood averaged over the dataset. For example here is a command, taken from `bin/run_eval.sh`, that will evaluate a JSB model on the test set:
-
-```
-python run_fivo.py \
- --mode=eval \
- --split=test \
- --alsologtostderr \
- --logdir=/tmp/fivo \
- --model=vrnn \
- --batch_size=4 \
- --num_samples=4 \
- --dataset_path="$PIANOROLL_DIR/jsb.pkl" \
- --dataset_type="pianoroll"
-```
-
-You should see output like this:
-```
-Restoring parameters from /tmp/fivo/model.ckpt-0
-Model restored from step 0, evaluating.
-test elbo ll/t: -12.198834, iwae ll/t: -11.981187 fivo ll/t: -11.579776
-test elbo ll/seq: -748.564789, iwae ll/seq: -735.209206 fivo ll/seq: -710.577141
-```
-The evaluation script prints log-likelihood in both nats per timestep (ll/t) and nats per sequence (ll/seq) for all three bounds.
-
-#### Sampling
-
-You can also sample from trained models. The `sample` mode loads a model checkpoint, conditions the model on a prefix of a randomly chosen datapoint, samples a sequence of outputs from the conditioned model, and writes out the samples and prefix to a `.npz` file in `logdir`. For example here is a command that samples from a model trained on JSB, taken from `bin/run_sample.sh`:
-```
-python run_fivo.py \
- --mode=sample \
- --alsologtostderr \
- --logdir="/tmp/fivo" \
- --model=vrnn \
- --bound=fivo \
- --batch_size=4 \
- --num_samples=4 \
- --split=test \
- --dataset_path="$PIANOROLL_DIR/jsb.pkl" \
- --dataset_type="pianoroll" \
- --prefix_length=25 \
- --sample_length=50
-```
-
-Here `num_samples` denotes the number of samples used when conditioning the model as well as the number of trajectories to sample for each prefix.
-
-You should see very little output.
-```
-Restoring parameters from /tmp/fivo/model.ckpt-0
-Running local_init_op.
-Done running local_init_op.
-```
-
-Loading the samples with `np.load` confirms that we conditioned the model on 4
-prefixes of length 25 and sampled 4 sequences of length 50 for each prefix.
-```
->>> import numpy as np
->>> x = np.load("/tmp/fivo/samples.npz")
->>> x[()]['prefixes'].shape
-(25, 4, 88)
->>> x[()]['samples'].shape
-(50, 4, 4, 88)
-```
-
-### Training on TIMIT
-
-The TIMIT speech dataset is available at the [Linguistic Data Consortium website](https://catalog.ldc.upenn.edu/LDC93S1), but is unfortunately not free. These instructions will proceed assuming you have downloaded the TIMIT archive and extracted it into the directory `$RAW_TIMIT_DIR`.
-
-#### Preprocess TIMIT
-
-We preprocess TIMIT (as described in our paper) and write it out to a series of TFRecord files. To prepare the TIMIT dataset use the script `create_timit_dataset.py`
-```
-export $TIMIT_DIR=~/timit_dataset
-mkdir $TIMIT_DIR
-python data/create_timit_dataset.py \
- --raw_timit_dir=$RAW_TIMIT_DIR \
- --out_dir=$TIMIT_DIR
-```
-You should see this exact output:
-```
-4389 train / 231 valid / 1680 test
-train mean: 0.006060 train std: 548.136169
-```
-
-#### Training on TIMIT
-This is very similar to training on pianoroll datasets, with just a few flags switched.
-```
-python run_fivo.py \
- --mode=train \
- --logdir=/tmp/fivo \
- --model=vrnn \
- --bound=fivo \
- --summarize_every=100 \
- --batch_size=4 \
- --num_samples=4 \
- --learning_rate=0.0001 \
- --dataset_path="$TIMIT_DIR/train" \
- --dataset_type="speech"
-```
-Evaluation and sampling are similar.
-
-### Tests
-This codebase comes with a number of tests to verify correctness, runnable via `bin/run_tests.sh`. The tests are also useful to look at for examples of how to use the code.
-
-### Contact
-
-This codebase is maintained by Dieterich Lawson. For questions and issues please open an issue on the tensorflow/models issues tracker and assign it to @dieterichlawson.
diff --git a/research/fivo/bin/download_pianorolls.sh b/research/fivo/bin/download_pianorolls.sh
deleted file mode 100644
index ef7050b4df5fb9815be04d133e659fa31d8d055e..0000000000000000000000000000000000000000
--- a/research/fivo/bin/download_pianorolls.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-# A script to download the pianoroll datasets.
-# Accepts one argument, the directory to put the files in
-
-if [ -z "$1" ]
- then
- echo "Error, must provide a directory to download the files to."
- exit
-fi
-
-echo "Downloading datasets into $1"
-curl -s "http://www-etud.iro.umontreal.ca/~boulanni/Piano-midi.de.pickle" > $1/piano-midi.de.pkl
-curl -s "http://www-etud.iro.umontreal.ca/~boulanni/Nottingham.pickle" > $1/nottingham.pkl
-curl -s "http://www-etud.iro.umontreal.ca/~boulanni/MuseData.pickle" > $1/musedata.pkl
-curl -s "http://www-etud.iro.umontreal.ca/~boulanni/JSB%20Chorales.pickle" > $1/jsb.pkl
diff --git a/research/fivo/bin/run_eval.sh b/research/fivo/bin/run_eval.sh
deleted file mode 100644
index b30bcedc2d16e5bdd681386100ecca23612a139a..0000000000000000000000000000000000000000
--- a/research/fivo/bin/run_eval.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-# An example of running evaluation.
-
-PIANOROLL_DIR=$HOME/pianorolls
-
-python run_fivo.py \
- --mode=eval \
- --logdir=/tmp/fivo \
- --model=vrnn \
- --batch_size=4 \
- --num_samples=4 \
- --split=test \
- --dataset_path="$PIANOROLL_DIR/jsb.pkl" \
- --dataset_type="pianoroll"
diff --git a/research/fivo/bin/run_sample.sh b/research/fivo/bin/run_sample.sh
deleted file mode 100644
index e0c82a0cb137822e85035a23081ecf6408b7cca1..0000000000000000000000000000000000000000
--- a/research/fivo/bin/run_sample.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/bash
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-# An example of sampling from the model.
-
-PIANOROLL_DIR=$HOME/pianorolls
-
-python run_fivo.py \
- --mode=sample \
- --alsologtostderr \
- --logdir="/tmp/fivo" \
- --model=vrnn \
- --bound=fivo \
- --batch_size=4 \
- --num_samples=4 \
- --split=test \
- --dataset_path="$PIANOROLL_DIR/jsb.pkl" \
- --dataset_type="pianoroll" \
- --prefix_length=25 \
- --sample_length=50
diff --git a/research/fivo/bin/run_tests.sh b/research/fivo/bin/run_tests.sh
deleted file mode 100644
index 2ea58f016620db98e258494919c6d339b5fd996e..0000000000000000000000000000000000000000
--- a/research/fivo/bin/run_tests.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/bash
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-python -m fivo.smc_test && \
-python -m fivo.bounds_test && \
-python -m fivo.nested_utils_test && \
-python -m fivo.data.datasets_test && \
-python -m fivo.models.ghmm_test && \
-python -m fivo.models.vrnn_test && \
-python -m fivo.models.srnn_test && \
-python -m fivo.ghmm_runners_test && \
-python -m fivo.runners_test
diff --git a/research/fivo/bin/run_train.sh b/research/fivo/bin/run_train.sh
deleted file mode 100644
index a845959770c77cd99528005e1ee69e4593fcae0c..0000000000000000000000000000000000000000
--- a/research/fivo/bin/run_train.sh
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/bin/bash
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-# An example of running training.
-
-PIANOROLL_DIR=$HOME/pianorolls
-
-python run_fivo.py \
- --mode=train \
- --logdir=/tmp/fivo \
- --model=vrnn \
- --bound=fivo \
- --summarize_every=100 \
- --batch_size=4 \
- --num_samples=4 \
- --learning_rate=0.0001 \
- --dataset_path="$PIANOROLL_DIR/jsb.pkl" \
- --dataset_type="pianoroll"
diff --git a/research/fivo/experimental/README.md b/research/fivo/experimental/README.md
deleted file mode 100644
index 649de0ba95cdee2fa1b101a588dc48903b2ca13b..0000000000000000000000000000000000000000
--- a/research/fivo/experimental/README.md
+++ /dev/null
@@ -1 +0,0 @@
-An experimental codebase for running simple examples.
diff --git a/research/fivo/experimental/bounds.py b/research/fivo/experimental/bounds.py
deleted file mode 100644
index afc970c59a1a86dbe8438b4e8bba791d3c95aa63..0000000000000000000000000000000000000000
--- a/research/fivo/experimental/bounds.py
+++ /dev/null
@@ -1,673 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from collections import namedtuple
-
-import tensorflow as tf
-import summary_utils as summ
-
-Loss = namedtuple("Loss", "name loss vars")
-Loss.__new__.__defaults__ = (tf.GraphKeys.TRAINABLE_VARIABLES,)
-
-
-def iwae(model, observation, num_timesteps, num_samples=1,
- summarize=False):
- """Compute the IWAE evidence lower bound.
-
- Args:
- model: A callable that computes one timestep of the model.
- observation: A shape [batch_size*num_samples, state_size] Tensor
- containing z_n, the observation for each sequence in the batch.
- num_timesteps: The number of timesteps in each sequence, an integer.
- num_samples: The number of samples to use to compute the IWAE bound.
- Returns:
- log_p_hat: The IWAE estimator of the lower bound on the log marginal.
- loss: A tensor that you can perform gradient descent on to optimize the
- bound.
- maintain_ema_op: A no-op included for compatibility with FIVO.
- states: The sequence of states sampled.
- """
- # Initialization
- num_instances = tf.shape(observation)[0]
- batch_size = tf.cast(num_instances / num_samples, tf.int32)
- states = [model.zero_state(num_instances)]
- log_weights = []
- log_weight_acc = tf.zeros([num_samples, batch_size], dtype=observation.dtype)
-
- for t in xrange(num_timesteps):
- # run the model for one timestep
- (zt, log_q_zt, log_p_zt, log_p_x_given_z, _) = model(
- states[-1], observation, t)
- # update accumulators
- states.append(zt)
- log_weight = log_p_zt + log_p_x_given_z - log_q_zt
- log_weight_acc += tf.reshape(log_weight, [num_samples, batch_size])
- if summarize:
- weight_dist = tf.contrib.distributions.Categorical(
- logits=tf.transpose(log_weight_acc, perm=[1, 0]),
- allow_nan_stats=False)
- weight_entropy = weight_dist.entropy()
- weight_entropy = tf.reduce_mean(weight_entropy)
- tf.summary.scalar("weight_entropy/%d" % t, weight_entropy)
- log_weights.append(log_weight_acc)
- # Compute the lower bound on the log evidence.
- log_p_hat = (tf.reduce_logsumexp(log_weight_acc, axis=0) -
- tf.log(tf.cast(num_samples, observation.dtype))) / num_timesteps
- loss = -tf.reduce_mean(log_p_hat)
- losses = [Loss("log_p_hat", loss)]
-
- # we clip off the initial state before returning.
- # there are no emas for iwae, so we return a noop for that
- return log_p_hat, losses, tf.no_op(), states[1:], log_weights
-
-
-def multinomial_resampling(log_weights, states, n, b):
- """Resample states with multinomial resampling.
-
- Args:
- log_weights: A (n x b) Tensor representing a batch of b logits for n-ary
- Categorical distribution.
- states: A list of (b*n x d) Tensors that will be resample in from the groups
- of every n-th row.
-
- Returns:
- resampled_states: A list of (b*n x d) Tensors resampled via stratified sampling.
- log_probs: A (n x b) Tensor of the log probabilities of the ancestry decisions.
- resampling_parameters: The Tensor of parameters of the resampling distribution.
- ancestors: An (n x b) Tensor of integral indices representing the ancestry decisions.
- resampling_dist: The distribution object for resampling.
- """
- log_weights = tf.convert_to_tensor(log_weights)
- states = [tf.convert_to_tensor(state) for state in states]
-
- resampling_parameters = tf.transpose(log_weights, perm=[1,0])
- resampling_dist = tf.contrib.distributions.Categorical(logits=resampling_parameters)
- ancestors = tf.stop_gradient(
- resampling_dist.sample(sample_shape=n))
- log_probs = resampling_dist.log_prob(ancestors)
-
- offset = tf.expand_dims(tf.range(b), 0)
- ancestor_inds = tf.reshape(ancestors * b + offset, [-1])
-
- resampled_states = []
- for state in states:
- resampled_states.append(tf.gather(state, ancestor_inds))
- return resampled_states, log_probs, resampling_parameters, ancestors, resampling_dist
-
-def stratified_resampling(log_weights, states, n, b):
- """Resample states with straitified resampling.
-
- Args:
- log_weights: A (n x b) Tensor representing a batch of b logits for n-ary
- Categorical distribution.
- states: A list of (b*n x d) Tensors that will be resample in from the groups
- of every n-th row.
-
- Returns:
- resampled_states: A list of (b*n x d) Tensors resampled via stratified sampling.
- log_probs: A (n x b) Tensor of the log probabilities of the ancestry decisions.
- resampling_parameters: The Tensor of parameters of the resampling distribution.
- ancestors: An (n x b) Tensor of integral indices representing the ancestry decisions.
- resampling_dist: The distribution object for resampling.
- """
- log_weights = tf.convert_to_tensor(log_weights)
- states = [tf.convert_to_tensor(state) for state in states]
-
- log_weights = tf.transpose(log_weights, perm=[1,0])
-
- probs = tf.nn.softmax(
- tf.tile(tf.expand_dims(log_weights, axis=1),
- [1, n, 1])
- )
-
- cdfs = tf.concat([tf.zeros((b,n,1), dtype=probs.dtype), tf.cumsum(probs, axis=2)], 2)
-
- bins = tf.range(n, dtype=probs.dtype) / n
- bins = tf.tile(tf.reshape(bins, [1,-1,1]), [b,1,n+1])
-
- strat_cdfs = tf.minimum(tf.maximum((cdfs - bins) * n, 0.0), 1.0)
- resampling_parameters = strat_cdfs[:,:,1:] - strat_cdfs[:,:,:-1]
-
- resampling_dist = tf.contrib.distributions.Categorical(
- probs = resampling_parameters,
- allow_nan_stats=False)
-
- ancestors = tf.stop_gradient(
- resampling_dist.sample())
- log_probs = resampling_dist.log_prob(ancestors)
-
- ancestors = tf.transpose(ancestors, perm=[1,0])
- log_probs = tf.transpose(log_probs, perm=[1,0])
-
- offset = tf.expand_dims(tf.range(b), 0)
- ancestor_inds = tf.reshape(ancestors * b + offset, [-1])
-
- resampled_states = []
- for state in states:
- resampled_states.append(tf.gather(state, ancestor_inds))
-
- return resampled_states, log_probs, resampling_parameters, ancestors, resampling_dist
-
-def systematic_resampling(log_weights, states, n, b):
- """Resample states with systematic resampling.
-
- Args:
- log_weights: A (n x b) Tensor representing a batch of b logits for n-ary
- Categorical distribution.
- states: A list of (b*n x d) Tensors that will be resample in from the groups
- of every n-th row.
-
- Returns:
- resampled_states: A list of (b*n x d) Tensors resampled via stratified sampling.
- log_probs: A (n x b) Tensor of the log probabilities of the ancestry decisions.
- resampling_parameters: The Tensor of parameters of the resampling distribution.
- ancestors: An (n x b) Tensor of integral indices representing the ancestry decisions.
- resampling_dist: The distribution object for resampling.
- """
-
- log_weights = tf.convert_to_tensor(log_weights)
- states = [tf.convert_to_tensor(state) for state in states]
-
- log_weights = tf.transpose(log_weights, perm=[1,0])
-
- probs = tf.nn.softmax(
- tf.tile(tf.expand_dims(log_weights, axis=1),
- [1, n, 1])
- )
-
- cdfs = tf.concat([tf.zeros((b,n,1), dtype=probs.dtype), tf.cumsum(probs, axis=2)], 2)
-
- bins = tf.range(n, dtype=probs.dtype) / n
- bins = tf.tile(tf.reshape(bins, [1,-1,1]), [b,1,n+1])
-
- strat_cdfs = tf.minimum(tf.maximum((cdfs - bins) * n, 0.0), 1.0)
- resampling_parameters = strat_cdfs[:,:,1:] - strat_cdfs[:,:,:-1]
-
- resampling_dist = tf.contrib.distributions.Categorical(
- probs=resampling_parameters,
- allow_nan_stats=True)
-
- U = tf.random_uniform((b, 1, 1), dtype=probs.dtype)
-
- ancestors = tf.stop_gradient(tf.reduce_sum(tf.to_float(U > strat_cdfs[:,:,1:]), axis=-1))
- log_probs = resampling_dist.log_prob(ancestors)
-
- ancestors = tf.transpose(ancestors, perm=[1,0])
- log_probs = tf.transpose(log_probs, perm=[1,0])
-
- offset = tf.expand_dims(tf.range(b, dtype=probs.dtype), 0)
- ancestor_inds = tf.reshape(ancestors * b + offset, [-1])
-
- resampled_states = []
- for state in states:
- resampled_states.append(tf.gather(state, ancestor_inds))
-
- return resampled_states, log_probs, resampling_parameters, ancestors, resampling_dist
-
-
-def log_blend(inputs, weights):
- """Blends state in the log space.
-
- Args:
- inputs: A set of scalar states, one for each particle in each particle filter.
- Should be [num_samples, batch_size].
- weights: A set of weights used to blend the state. Each set of weights
- should be of dimension [num_samples] (one weight for each previous particle).
- There should be one set of weights for each new particle in each particle filter.
- Thus the shape should be [num_samples, batch_size, num_samples] where
- the first axis indexes new particle and the last axis indexes old particles.
- Returns:
- blended: The blended states, a tensor of shape [num_samples, batch_size].
- """
- raw_max = tf.reduce_max(inputs, axis=0, keepdims=True)
- my_max = tf.stop_gradient(
- tf.where(tf.is_finite(raw_max), raw_max, tf.zeros_like(raw_max))
- )
- # Don't ask.
- blended = tf.log(tf.einsum("ijk,kj->ij", weights, tf.exp(inputs - raw_max))) + my_max
- return blended
-
-
-def relaxed_resampling(log_weights, states, num_samples, batch_size,
- log_r_x=None, blend_type="log", temperature=0.5,
- straight_through=False):
- """Resample states with relaxed resampling.
-
- Args:
- log_weights: A (n x b) Tensor representing a batch of b logits for n-ary
- Categorical distribution.
- states: A list of (b*n x d) Tensors that will be resample in from the groups
- of every n-th row.
-
- Returns:
- resampled_states: A list of (b*n x d) Tensors resampled via stratified sampling.
- log_probs: A (n x b) Tensor of the log probabilities of the ancestry decisions.
- resampling_parameters: The Tensor of parameters of the resampling distribution.
- ancestors: An (n x b x n) Tensor of relaxed one hot representations of the ancestry decisions.
- resampling_dist: The distribution object for resampling.
- """
- assert blend_type in ["log", "linear"], "Blend type must be 'log' or 'linear'."
- log_weights = tf.convert_to_tensor(log_weights)
- states = [tf.convert_to_tensor(state) for state in states]
- state_dim = states[0].get_shape().as_list()[-1]
- # weights are num_samples by batch_size, so we transpose to get a
- # set of batch_size distributions over [0,num_samples).
- resampling_parameters = tf.transpose(log_weights, perm=[1, 0])
- resampling_dist = tf.contrib.distributions.RelaxedOneHotCategorical(
- temperature,
- logits=resampling_parameters)
-
- # sample num_samples samples from the distribution, resulting in a
- # [num_samples, batch_size, num_samples] Tensor that represents a set of
- # [num_samples, batch_size] blending weights. The dimensions represent
- # [sample index, batch index, blending weight index]
- ancestors = resampling_dist.sample(sample_shape=num_samples)
- if straight_through:
- # Forward pass discrete choices, backwards pass soft choices
- hard_ancestor_indices = tf.argmax(ancestors, axis=-1)
- hard_ancestors = tf.one_hot(hard_ancestor_indices, num_samples,
- dtype=ancestors.dtype)
- ancestors = tf.stop_gradient(hard_ancestors - ancestors) + ancestors
- log_probs = resampling_dist.log_prob(ancestors)
- if log_r_x is not None and blend_type == "log":
- log_r_x = tf.reshape(log_r_x, [num_samples, batch_size])
- log_r_x = log_blend(log_r_x, ancestors)
- log_r_x = tf.reshape(log_r_x, [num_samples*batch_size])
- elif log_r_x is not None and blend_type == "linear":
- # If blend type is linear just add log_r to the states that will be blended
- # linearly.
- states.append(log_r_x)
-
- # transpose the 'indices' to be [batch_index, blending weight index, sample index]
- ancestor_inds = tf.transpose(ancestors, perm=[1, 2, 0])
- resampled_states = []
- for state in states:
- # state is currently [num_samples * batch_size, state_dim] so we reshape
- # to [num_samples, batch_size, state_dim] and then transpose to
- # [batch_size, state_size, num_samples]
- state = tf.transpose(tf.reshape(state, [num_samples, batch_size, -1]), perm=[1, 2, 0])
- # state is now (batch_size, state_size, num_samples)
- # and ancestor is (batch index, blending weight index, sample index)
- # multiplying these gives a matrix of size [batch_size, state_size, num_samples]
- next_state = tf.matmul(state, ancestor_inds)
- # transpose the state to be [num_samples, batch_size, state_size]
- # and then reshape it to match the state format.
- next_state = tf.reshape(tf.transpose(next_state, perm=[2,0,1]), [num_samples*batch_size, state_dim])
- resampled_states.append(next_state)
-
- new_dist = tf.contrib.distributions.Categorical(
- logits=resampling_parameters)
-
- if log_r_x is not None and blend_type == "linear":
- # If blend type is linear pop off log_r that we added to the states.
- log_r_x = tf.squeeze(resampled_states[-1])
- resampled_states = resampled_states[:-1]
- return resampled_states, log_probs, log_r_x, resampling_parameters, ancestors, new_dist
-
-
-def fivo(model,
- observation,
- num_timesteps,
- resampling_schedule,
- num_samples=1,
- use_resampling_grads=True,
- resampling_type="multinomial",
- resampling_temperature=0.5,
- aux=True,
- summarize=False):
- """Compute the FIVO evidence lower bound.
-
- Args:
- model: A callable that computes one timestep of the model.
- observation: A shape [batch_size*num_samples, state_size] Tensor
- containing z_n, the observation for each sequence in the batch.
- num_timesteps: The number of timesteps in each sequence, an integer.
- resampling_schedule: A list of booleans of length num_timesteps, contains
- True if a resampling should occur on a specific timestep.
- num_samples: The number of samples to use to compute the IWAE bound.
- use_resampling_grads: Whether or not to include the resampling gradients
- in loss.
- resampling type: The type of resampling, one of "multinomial", "stratified",
- "relaxed-logblend", "relaxed-linearblend", "relaxed-stateblend", or
- "systematic".
- resampling_temperature: A positive temperature only used for relaxed
- resampling.
- aux: If true, compute the FIVO-AUX bound.
- Returns:
- log_p_hat: The IWAE estimator of the lower bound on the log marginal.
- loss: A tensor that you can perform gradient descent on to optimize the
- bound.
- maintain_ema_op: An op to update the baseline ema used for the resampling
- gradients.
- states: The sequence of states sampled.
- """
- # Initialization
- num_instances = tf.cast(tf.shape(observation)[0], tf.int32)
- batch_size = tf.cast(num_instances / num_samples, tf.int32)
- states = [model.zero_state(num_instances)]
- prev_state = states[0]
- log_weight_acc = tf.zeros(shape=[num_samples, batch_size], dtype=observation.dtype)
- prev_log_r_zt = tf.zeros([num_instances], dtype=observation.dtype)
- log_weights = []
- log_weights_all = []
- log_p_hats = []
- resampling_log_probs = []
- for t in xrange(num_timesteps):
- # run the model for one timestep
- (zt, log_q_zt, log_p_zt, log_p_x_given_z, log_r_zt) = model(
- prev_state, observation, t)
- # update accumulators
- states.append(zt)
- log_weight = log_p_zt + log_p_x_given_z - log_q_zt
- if aux:
- if t == num_timesteps - 1:
- log_weight -= prev_log_r_zt
- else:
- log_weight += log_r_zt - prev_log_r_zt
- prev_log_r_zt = log_r_zt
- log_weight_acc += tf.reshape(log_weight, [num_samples, batch_size])
- log_weights_all.append(log_weight_acc)
- if resampling_schedule[t]:
-
- # These objects will be resampled
- to_resample = [states[-1]]
- if aux and "relaxed" not in resampling_type:
- to_resample.append(prev_log_r_zt)
-
- # do the resampling
- if resampling_type == "multinomial":
- (resampled,
- resampling_log_prob,
- _, _, _) = multinomial_resampling(log_weight_acc,
- to_resample,
- num_samples,
- batch_size)
- elif resampling_type == "stratified":
- (resampled,
- resampling_log_prob,
- _, _, _) = stratified_resampling(log_weight_acc,
- to_resample,
- num_samples,
- batch_size)
- elif resampling_type == "systematic":
- (resampled,
- resampling_log_prob,
- _, _, _) = systematic_resampling(log_weight_acc,
- to_resample,
- num_samples,
- batch_size)
- elif "relaxed" in resampling_type:
- if aux:
- if resampling_type == "relaxed-logblend":
- (resampled,
- resampling_log_prob,
- prev_log_r_zt,
- _, _, _) = relaxed_resampling(log_weight_acc,
- to_resample,
- num_samples,
- batch_size,
- temperature=resampling_temperature,
- log_r_x=prev_log_r_zt,
- blend_type="log")
- elif resampling_type == "relaxed-linearblend":
- (resampled,
- resampling_log_prob,
- prev_log_r_zt,
- _, _, _) = relaxed_resampling(log_weight_acc,
- to_resample,
- num_samples,
- batch_size,
- temperature=resampling_temperature,
- log_r_x=prev_log_r_zt,
- blend_type="linear")
- elif resampling_type == "relaxed-stateblend":
- (resampled,
- resampling_log_prob,
- _, _, _, _) = relaxed_resampling(log_weight_acc,
- to_resample,
- num_samples,
- batch_size,
- temperature=resampling_temperature)
- # Calculate prev_log_r_zt from the post-resampling state
- prev_r_zt = model.r.r_xn(resampled[0], t)
- prev_log_r_zt = tf.reduce_sum(
- prev_r_zt.log_prob(observation), axis=[1])
- elif resampling_type == "relaxed-stateblend-st":
- (resampled,
- resampling_log_prob,
- _, _, _, _) = relaxed_resampling(log_weight_acc,
- to_resample,
- num_samples,
- batch_size,
- temperature=resampling_temperature,
- straight_through=True)
- # Calculate prev_log_r_zt from the post-resampling state
- prev_r_zt = model.r.r_xn(resampled[0], t)
- prev_log_r_zt = tf.reduce_sum(
- prev_r_zt.log_prob(observation), axis=[1])
- else:
- (resampled,
- resampling_log_prob,
- _, _, _, _) = relaxed_resampling(log_weight_acc,
- to_resample,
- num_samples,
- batch_size,
- temperature=resampling_temperature)
- #if summarize:
- # resampling_entropy = resampling_dist.entropy()
- # resampling_entropy = tf.reduce_mean(resampling_entropy)
- # tf.summary.scalar("weight_entropy/%d" % t, resampling_entropy)
-
- resampling_log_probs.append(tf.reduce_sum(resampling_log_prob, axis=0))
- prev_state = resampled[0]
- if aux and "relaxed" not in resampling_type:
- # Squeeze out the extra dim potentially added by resampling.
- # prev_log_r_zt should always be [num_instances]
- prev_log_r_zt = tf.squeeze(resampled[1])
- # Update the log p hat estimate, taking a log sum exp over the sample
- # dimension. The appended tensor is [batch_size].
- log_p_hats.append(
- tf.reduce_logsumexp(log_weight_acc, axis=0) - tf.log(
- tf.cast(num_samples, dtype=observation.dtype)))
- # reset the weights
- log_weights.append(log_weight_acc)
- log_weight_acc = tf.zeros_like(log_weight_acc)
- else:
- prev_state = states[-1]
- # Compute the final weight update. If we just resampled this will be zero.
- final_update = (tf.reduce_logsumexp(log_weight_acc, axis=0) -
- tf.log(tf.cast(num_samples, dtype=observation.dtype)))
- # If we ever resampled, then sum up the previous log p hat terms
- if len(log_p_hats) > 0:
- log_p_hat = tf.reduce_sum(log_p_hats, axis=0) + final_update
- else: # otherwise, log_p_hat only comes from the final update
- log_p_hat = final_update
-
- if use_resampling_grads and any(resampling_schedule):
- # compute the rewards
- # cumsum([a, b, c]) => [a, a+b, a+b+c]
- # learning signal at timestep t is
- # [sum from i=t+1 to T of log_p_hat_i for t=1:T]
- # so we will compute (sum from i=1 to T of log_p_hat_i)
- # and at timestep t will subtract off (sum from i=1 to t of log_p_hat_i)
- # rewards is a [num_resampling_events, batch_size] Tensor
- rewards = tf.stop_gradient(
- tf.expand_dims(log_p_hat, 0) - tf.cumsum(log_p_hats, axis=0))
- batch_avg_rewards = tf.reduce_mean(rewards, axis=1)
- # compute ema baseline.
- # centered_rewards is [num_resampling_events, batch_size]
- baseline_ema = tf.train.ExponentialMovingAverage(decay=0.94)
- maintain_baseline_op = baseline_ema.apply([batch_avg_rewards])
- baseline = tf.expand_dims(baseline_ema.average(batch_avg_rewards), 1)
- centered_rewards = rewards - baseline
- if summarize:
- summ.summarize_learning_signal(rewards, "rewards")
- summ.summarize_learning_signal(centered_rewards, "centered_rewards")
- # compute the loss tensor.
- resampling_grads = tf.reduce_sum(
- tf.stop_gradient(centered_rewards) * resampling_log_probs, axis=0)
- losses = [Loss("log_p_hat", -tf.reduce_mean(log_p_hat)/num_timesteps),
- Loss("resampling_grads", -tf.reduce_mean(resampling_grads)/num_timesteps)]
- else:
- losses = [Loss("log_p_hat", -tf.reduce_mean(log_p_hat)/num_timesteps)]
- maintain_baseline_op = tf.no_op()
-
- log_p_hat /= num_timesteps
- # we clip off the initial state before returning.
- return log_p_hat, losses, maintain_baseline_op, states[1:], log_weights_all
-
-
-def fivo_aux_td(
- model,
- observation,
- num_timesteps,
- resampling_schedule,
- num_samples=1,
- summarize=False):
- """Compute the FIVO_AUX evidence lower bound."""
- # Initialization
- num_instances = tf.cast(tf.shape(observation)[0], tf.int32)
- batch_size = tf.cast(num_instances / num_samples, tf.int32)
- states = [model.zero_state(num_instances)]
- prev_state = states[0]
- log_weight_acc = tf.zeros(shape=[num_samples, batch_size], dtype=observation.dtype)
- prev_log_r = tf.zeros([num_instances], dtype=observation.dtype)
- # must be pre-resampling
- log_rs = []
- # must be post-resampling
- r_tilde_params = [model.r_tilde.r_zt(states[0], observation, 0)]
- log_r_tildes = []
- log_p_xs = []
- # contains the weight at each timestep before resampling only on resampling timesteps
- log_weights = []
- # contains weight at each timestep before resampling
- log_weights_all = []
- log_p_hats = []
- for t in xrange(num_timesteps):
- # run the model for one timestep
- # zt is state, [num_instances, state_dim]
- # log_q_zt, log_p_x_given_z is [num_instances]
- # r_tilde_mu, r_tilde_sigma is [num_instances, state_dim]
- # p_ztplus1 is a normal distribution on [num_instances, state_dim]
- (zt, log_q_zt, log_p_zt, log_p_x_given_z,
- r_tilde_mu, r_tilde_sigma_sq, p_ztplus1) = model(prev_state, observation, t)
-
- # Compute the log weight without log r.
- log_weight = log_p_zt + log_p_x_given_z - log_q_zt
-
- # Compute log r.
- if t == num_timesteps - 1:
- log_r = tf.zeros_like(prev_log_r)
- else:
- p_mu = p_ztplus1.mean()
- p_sigma_sq = p_ztplus1.variance()
- log_r = (tf.log(r_tilde_sigma_sq) -
- tf.log(r_tilde_sigma_sq + p_sigma_sq) -
- tf.square(r_tilde_mu - p_mu)/(r_tilde_sigma_sq + p_sigma_sq))
- log_r = 0.5*tf.reduce_sum(log_r, axis=-1)
-
- #log_weight += tf.stop_gradient(log_r - prev_log_r)
- log_weight += log_r - prev_log_r
- log_weight_acc += tf.reshape(log_weight, [num_samples, batch_size])
-
- # Update accumulators
- states.append(zt)
- log_weights_all.append(log_weight_acc)
- log_p_xs.append(log_p_x_given_z)
- log_rs.append(log_r)
-
- # Compute log_r_tilde as [num_instances] Tensor.
- prev_r_tilde_mu, prev_r_tilde_sigma_sq = r_tilde_params[-1]
- prev_log_r_tilde = -0.5*tf.reduce_sum(
- tf.square(zt - prev_r_tilde_mu)/prev_r_tilde_sigma_sq, axis=-1)
- #tf.square(tf.stop_gradient(zt) - r_tilde_mu)/r_tilde_sigma_sq, axis=-1)
- #tf.square(zt - r_tilde_mu)/r_tilde_sigma_sq, axis=-1)
- log_r_tildes.append(prev_log_r_tilde)
-
- # optionally resample
- if resampling_schedule[t]:
- # These objects will be resampled
- if t < num_timesteps - 1:
- to_resample = [zt, log_r, r_tilde_mu, r_tilde_sigma_sq]
- else:
- to_resample = [zt, log_r]
- (resampled,
- _, _, _, _) = multinomial_resampling(log_weight_acc,
- to_resample,
- num_samples,
- batch_size)
- prev_state = resampled[0]
- # Squeeze out the extra dim potentially added by resampling.
- # prev_log_r_zt and log_r_tilde should always be [num_instances]
- prev_log_r = tf.squeeze(resampled[1])
- if t < num_timesteps -1:
- r_tilde_params.append((resampled[2], resampled[3]))
- # Update the log p hat estimate, taking a log sum exp over the sample
- # dimension. The appended tensor is [batch_size].
- log_p_hats.append(
- tf.reduce_logsumexp(log_weight_acc, axis=0) - tf.log(
- tf.cast(num_samples, dtype=observation.dtype)))
- # reset the weights
- log_weights.append(log_weight_acc)
- log_weight_acc = tf.zeros_like(log_weight_acc)
- else:
- prev_state = zt
- prev_log_r = log_r
- if t < num_timesteps - 1:
- r_tilde_params.append((r_tilde_mu, r_tilde_sigma_sq))
-
- # Compute the final weight update. If we just resampled this will be zero.
- final_update = (tf.reduce_logsumexp(log_weight_acc, axis=0) -
- tf.log(tf.cast(num_samples, dtype=observation.dtype)))
- # If we ever resampled, then sum up the previous log p hat terms
- if len(log_p_hats) > 0:
- log_p_hat = tf.reduce_sum(log_p_hats, axis=0) + final_update
- else: # otherwise, log_p_hat only comes from the final update
- log_p_hat = final_update
-
- # Compute the bellman loss.
- # Will remove the first timestep as it is not used.
- # log p(x_t|z_t) is in row t-1.
- log_p_x = tf.reshape(tf.stack(log_p_xs),
- [num_timesteps, num_samples, batch_size])
- # log r_t is contained in row t-1.
- # last column is zeros (because at timestep T (num_timesteps) r is 1.
- log_r = tf.reshape(tf.stack(log_rs),
- [num_timesteps, num_samples, batch_size])
- # [num_timesteps, num_instances]. log r_tilde_t is in row t-1.
- log_r_tilde = tf.reshape(tf.stack(log_r_tildes),
- [num_timesteps, num_samples, batch_size])
- log_lambda = tf.reduce_mean(log_r_tilde - log_p_x - log_r, axis=1,
- keepdims=True)
- bellman_sos = tf.reduce_mean(tf.square(
- log_r_tilde - tf.stop_gradient(log_lambda + log_p_x + log_r)), axis=[0, 1])
- bellman_loss = tf.reduce_mean(bellman_sos)/num_timesteps
- tf.summary.scalar("bellman_loss", bellman_loss)
-
- if len(tf.get_collection("LOG_P_HAT_VARS")) == 0:
- log_p_hat_collection = list(set(tf.trainable_variables()) -
- set(tf.get_collection("R_TILDE_VARS")))
- for v in log_p_hat_collection:
- tf.add_to_collection("LOG_P_HAT_VARS", v)
-
- log_p_hat /= num_timesteps
- losses = [Loss("log_p_hat", -tf.reduce_mean(log_p_hat), "LOG_P_HAT_VARS"),
- Loss("bellman_loss", bellman_loss, "R_TILDE_VARS")]
-
- return log_p_hat, losses, tf.no_op(), states[1:], log_weights_all
diff --git a/research/fivo/experimental/data.py b/research/fivo/experimental/data.py
deleted file mode 100644
index 0842f212991e1651a12cca239c5b8380fea9d0f8..0000000000000000000000000000000000000000
--- a/research/fivo/experimental/data.py
+++ /dev/null
@@ -1,192 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Datasets."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import tensorflow as tf
-
-import models
-
-
-def make_long_chain_dataset(
- state_size=1,
- num_obs=5,
- steps_per_obs=3,
- variance=1.,
- observation_variance=1.,
- batch_size=4,
- num_samples=1,
- observation_type=models.STANDARD_OBSERVATION,
- transition_type=models.STANDARD_TRANSITION,
- fixed_observation=None,
- dtype="float32"):
- """Creates a long chain data generating process.
-
- Creates a tf.data.Dataset that provides batches of data from a long
- chain.
-
- Args:
- state_size: The dimension of the state space of the process.
- num_obs: The number of observations in the chain.
- steps_per_obs: The number of steps between each observation.
- variance: The variance of the normal distributions used at each timestep.
- batch_size: The number of trajectories to include in each batch.
- num_samples: The number of replicas of each trajectory to include in each
- batch.
- dtype: The datatype of the states and observations.
- Returns:
- dataset: A tf.data.Dataset that can be iterated over.
- """
- num_timesteps = num_obs * steps_per_obs
- def data_generator():
- """An infinite generator of latents and observations from the model."""
- while True:
- states = []
- observations = []
- # z0 ~ Normal(0, sqrt(variance)).
- states.append(
- np.random.normal(size=[state_size],
- scale=np.sqrt(variance)).astype(dtype))
- # start at 1 because we've already generated z0
- # go to num_timesteps+1 because we want to include the num_timesteps-th step
- for t in xrange(1, num_timesteps+1):
- if transition_type == models.ROUND_TRANSITION:
- loc = np.round(states[-1])
- elif transition_type == models.STANDARD_TRANSITION:
- loc = states[-1]
- new_state = np.random.normal(size=[state_size],
- loc=loc,
- scale=np.sqrt(variance))
- states.append(new_state.astype(dtype))
- if t % steps_per_obs == 0:
- if fixed_observation is None:
- if observation_type == models.SQUARED_OBSERVATION:
- loc = np.square(states[-1])
- elif observation_type == models.ABS_OBSERVATION:
- loc = np.abs(states[-1])
- elif observation_type == models.STANDARD_OBSERVATION:
- loc = states[-1]
- new_obs = np.random.normal(size=[state_size],
- loc=loc,
- scale=np.sqrt(observation_variance)).astype(dtype)
- else:
- new_obs = np.ones([state_size])* fixed_observation
-
- observations.append(new_obs)
- yield states, observations
-
- dataset = tf.data.Dataset.from_generator(
- data_generator,
- output_types=(tf.as_dtype(dtype), tf.as_dtype(dtype)),
- output_shapes=([num_timesteps+1, state_size], [num_obs, state_size]))
- dataset = dataset.repeat().batch(batch_size)
-
- def tile_batch(state, observation):
- state = tf.tile(state, [num_samples, 1, 1])
- observation = tf.tile(observation, [num_samples, 1, 1])
- return state, observation
-
- dataset = dataset.map(tile_batch, num_parallel_calls=12).prefetch(1024)
- return dataset
-
-
-def make_dataset(bs=None,
- state_size=1,
- num_timesteps=10,
- variance=1.,
- prior_type="unimodal",
- bimodal_prior_weight=0.5,
- bimodal_prior_mean=1,
- transition_type=models.STANDARD_TRANSITION,
- fixed_observation=None,
- batch_size=4,
- num_samples=1,
- dtype='float32'):
- """Creates a data generating process.
-
- Creates a tf.data.Dataset that provides batches of data.
-
- Args:
- bs: The parameters of the data generating process. If None, new bs are
- randomly generated.
- state_size: The dimension of the state space of the process.
- num_timesteps: The length of the state sequences in the process.
- variance: The variance of the normal distributions used at each timestep.
- batch_size: The number of trajectories to include in each batch.
- num_samples: The number of replicas of each trajectory to include in each
- batch.
- Returns:
- bs: The true bs used to generate the data
- dataset: A tf.data.Dataset that can be iterated over.
- """
-
- if bs is None:
- bs = [np.random.uniform(size=[state_size]).astype(dtype) for _ in xrange(num_timesteps)]
- tf.logging.info("data generating processs bs: %s",
- np.array(bs).reshape(num_timesteps))
-
-
- def data_generator():
- """An infinite generator of latents and observations from the model."""
- while True:
- states = []
- if prior_type == "unimodal" or prior_type == "nonlinear":
- # Prior is Normal(0, sqrt(variance)).
- states.append(np.random.normal(size=[state_size], scale=np.sqrt(variance)).astype(dtype))
- elif prior_type == "bimodal":
- if np.random.uniform() > bimodal_prior_weight:
- loc = bimodal_prior_mean
- else:
- loc = - bimodal_prior_mean
- states.append(np.random.normal(size=[state_size],
- loc=loc,
- scale=np.sqrt(variance)
- ).astype(dtype))
-
- for t in xrange(num_timesteps):
- if transition_type == models.ROUND_TRANSITION:
- loc = np.round(states[-1])
- elif transition_type == models.STANDARD_TRANSITION:
- loc = states[-1]
- loc += bs[t]
- new_state = np.random.normal(size=[state_size],
- loc=loc,
- scale=np.sqrt(variance)).astype(dtype)
- states.append(new_state)
-
- if fixed_observation is None:
- observation = states[-1]
- else:
- observation = np.ones_like(states[-1]) * fixed_observation
- yield np.array(states[:-1]), observation
-
- dataset = tf.data.Dataset.from_generator(
- data_generator,
- output_types=(tf.as_dtype(dtype), tf.as_dtype(dtype)),
- output_shapes=([num_timesteps, state_size], [state_size]))
- dataset = dataset.repeat().batch(batch_size)
-
- def tile_batch(state, observation):
- state = tf.tile(state, [num_samples, 1, 1])
- observation = tf.tile(observation, [num_samples, 1])
- return state, observation
-
- dataset = dataset.map(tile_batch, num_parallel_calls=12).prefetch(1024)
- return np.array(bs), dataset
diff --git a/research/fivo/experimental/models.py b/research/fivo/experimental/models.py
deleted file mode 100644
index 62801ca1ee145e64c80b66e0c83dd7d834ac0847..0000000000000000000000000000000000000000
--- a/research/fivo/experimental/models.py
+++ /dev/null
@@ -1,1227 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Model."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import functools
-import sonnet as snt
-import tensorflow as tf
-import numpy as np
-import math
-
-SQUARED_OBSERVATION = "squared"
-ABS_OBSERVATION = "abs"
-STANDARD_OBSERVATION = "standard"
-OBSERVATION_TYPES = [SQUARED_OBSERVATION, ABS_OBSERVATION, STANDARD_OBSERVATION]
-
-ROUND_TRANSITION = "round"
-STANDARD_TRANSITION = "standard"
-TRANSITION_TYPES = [ROUND_TRANSITION, STANDARD_TRANSITION]
-
-
-class Q(object):
-
- def __init__(self,
- state_size,
- num_timesteps,
- sigma_min=1e-5,
- dtype=tf.float32,
- random_seed=None,
- init_mu0_to_zero=False,
- graph_collection_name="Q_VARS"):
- self.sigma_min = sigma_min
- self.dtype = dtype
- self.graph_collection_name = graph_collection_name
- initializers = []
- for t in xrange(num_timesteps):
- if t == 0 and init_mu0_to_zero:
- initializers.append(
- {"w": tf.zeros_initializer, "b": tf.zeros_initializer})
- else:
- initializers.append(
- {"w": tf.random_uniform_initializer(seed=random_seed),
- "b": tf.zeros_initializer})
-
- def custom_getter(getter, *args, **kwargs):
- out = getter(*args, **kwargs)
- ref = tf.get_collection_ref(self.graph_collection_name)
- if out not in ref:
- ref.append(out)
- return out
-
- self.mus = [
- snt.Linear(output_size=state_size,
- initializers=initializers[t],
- name="q_mu_%d" % t,
- custom_getter=custom_getter
- )
- for t in xrange(num_timesteps)
- ]
- self.sigmas = [
- tf.get_variable(
- shape=[state_size],
- dtype=self.dtype,
- name="q_sigma_%d" % (t + 1),
- collections=[tf.GraphKeys.GLOBAL_VARIABLES, graph_collection_name],
- initializer=tf.random_uniform_initializer(seed=random_seed))
- for t in xrange(num_timesteps)
- ]
-
- def q_zt(self, observation, prev_state, t):
- batch_size = tf.shape(prev_state)[0]
- q_mu = self.mus[t](tf.concat([observation, prev_state], axis=1))
- q_sigma = tf.maximum(tf.nn.softplus(self.sigmas[t]), self.sigma_min)
- q_sigma = tf.tile(q_sigma[tf.newaxis, :], [batch_size, 1])
- q_zt = tf.contrib.distributions.Normal(loc=q_mu, scale=tf.sqrt(q_sigma))
- return q_zt
-
- def summarize_weights(self):
- for t, sigma in enumerate(self.sigmas):
- tf.summary.scalar("q_sigma/%d" % t, sigma[0])
- for t, f in enumerate(self.mus):
- tf.summary.scalar("q_mu/b_%d" % t, f.b[0])
- tf.summary.scalar("q_mu/w_obs_%d" % t, f.w[0,0])
- if t != 0:
- tf.summary.scalar("q_mu/w_prev_state_%d" % t, f.w[1,0])
-
-
-class PreviousStateQ(Q):
-
- def q_zt(self, unused_observation, prev_state, t):
- batch_size = tf.shape(prev_state)[0]
- q_mu = self.mus[t](prev_state)
- q_sigma = tf.maximum(tf.nn.softplus(self.sigmas[t]), self.sigma_min)
- q_sigma = tf.tile(q_sigma[tf.newaxis, :], [batch_size, 1])
- q_zt = tf.contrib.distributions.Normal(loc=q_mu, scale=tf.sqrt(q_sigma))
- return q_zt
-
- def summarize_weights(self):
- for t, sigma in enumerate(self.sigmas):
- tf.summary.scalar("q_sigma/%d" % t, sigma[0])
- for t, f in enumerate(self.mus):
- tf.summary.scalar("q_mu/b_%d" % t, f.b[0])
- tf.summary.scalar("q_mu/w_prev_state_%d" % t, f.w[0,0])
-
-
-class ObservationQ(Q):
-
- def q_zt(self, observation, prev_state, t):
- batch_size = tf.shape(prev_state)[0]
- q_mu = self.mus[t](observation)
- q_sigma = tf.maximum(tf.nn.softplus(self.sigmas[t]), self.sigma_min)
- q_sigma = tf.tile(q_sigma[tf.newaxis, :], [batch_size, 1])
- q_zt = tf.contrib.distributions.Normal(loc=q_mu, scale=tf.sqrt(q_sigma))
- return q_zt
-
- def summarize_weights(self):
- for t, sigma in enumerate(self.sigmas):
- tf.summary.scalar("q_sigma/%d" % t, sigma[0])
- for t, f in enumerate(self.mus):
- tf.summary.scalar("q_mu/b_%d" % t, f.b[0])
- tf.summary.scalar("q_mu/w_obs_%d" % t, f.w[0,0])
-
-
-class SimpleMeanQ(object):
-
- def __init__(self,
- state_size,
- num_timesteps,
- sigma_min=1e-5,
- dtype=tf.float32,
- random_seed=None,
- init_mu0_to_zero=False,
- graph_collection_name="Q_VARS"):
- self.sigma_min = sigma_min
- self.dtype = dtype
- self.graph_collection_name = graph_collection_name
- initializers = []
- for t in xrange(num_timesteps):
- if t == 0 and init_mu0_to_zero:
- initializers.append(tf.zeros_initializer)
- else:
- initializers.append(tf.random_uniform_initializer(seed=random_seed))
-
- self.mus = [
- tf.get_variable(
- shape=[state_size],
- dtype=self.dtype,
- name="q_mu_%d" % (t + 1),
- collections=[tf.GraphKeys.GLOBAL_VARIABLES, graph_collection_name],
- initializer=initializers[t])
- for t in xrange(num_timesteps)
- ]
- self.sigmas = [
- tf.get_variable(
- shape=[state_size],
- dtype=self.dtype,
- name="q_sigma_%d" % (t + 1),
- collections=[tf.GraphKeys.GLOBAL_VARIABLES, graph_collection_name],
- initializer=tf.random_uniform_initializer(seed=random_seed))
- for t in xrange(num_timesteps)
- ]
-
- def q_zt(self, unused_observation, prev_state, t):
- batch_size = tf.shape(prev_state)[0]
- q_mu = tf.tile(self.mus[t][tf.newaxis, :], [batch_size, 1])
- q_sigma = tf.maximum(tf.nn.softplus(self.sigmas[t]), self.sigma_min)
- q_sigma = tf.tile(q_sigma[tf.newaxis, :], [batch_size, 1])
- q_zt = tf.contrib.distributions.Normal(loc=q_mu, scale=tf.sqrt(q_sigma))
- return q_zt
-
- def summarize_weights(self):
- for t, sigma in enumerate(self.sigmas):
- tf.summary.scalar("q_sigma/%d" % t, sigma[0])
- for t, f in enumerate(self.mus):
- tf.summary.scalar("q_mu/%d" % t, f[0])
-
-
-class R(object):
-
- def __init__(self,
- state_size,
- num_timesteps,
- sigma_min=1e-5,
- dtype=tf.float32,
- sigma_init=1.,
- random_seed=None,
- graph_collection_name="R_VARS"):
- self.dtype = dtype
- self.sigma_min = sigma_min
- initializers = {"w": tf.truncated_normal_initializer(seed=random_seed),
- "b": tf.zeros_initializer}
- self.graph_collection_name=graph_collection_name
-
- def custom_getter(getter, *args, **kwargs):
- out = getter(*args, **kwargs)
- ref = tf.get_collection_ref(self.graph_collection_name)
- if out not in ref:
- ref.append(out)
- return out
-
- self.mus= [
- snt.Linear(output_size=state_size,
- initializers=initializers,
- name="r_mu_%d" % t,
- custom_getter=custom_getter)
- for t in xrange(num_timesteps)
- ]
-
- self.sigmas = [
- tf.get_variable(
- shape=[state_size],
- dtype=self.dtype,
- name="r_sigma_%d" % (t + 1),
- collections=[tf.GraphKeys.GLOBAL_VARIABLES, graph_collection_name],
- #initializer=tf.random_uniform_initializer(seed=random_seed, maxval=100))
- initializer=tf.constant_initializer(sigma_init))
- for t in xrange(num_timesteps)
- ]
-
- def r_xn(self, z_t, t):
- batch_size = tf.shape(z_t)[0]
- r_mu = self.mus[t](z_t)
- r_sigma = tf.maximum(tf.nn.softplus(self.sigmas[t]), self.sigma_min)
- r_sigma = tf.tile(r_sigma[tf.newaxis, :], [batch_size, 1])
- return tf.contrib.distributions.Normal(
- loc=r_mu, scale=tf.sqrt(r_sigma))
-
- def summarize_weights(self):
- for t in range(len(self.mus) - 1):
- tf.summary.scalar("r_mu/%d" % t, self.mus[t][0])
- tf.summary.scalar("r_sigma/%d" % t, self.sigmas[t][0])
-
-
-class P(object):
-
- def __init__(self,
- state_size,
- num_timesteps,
- sigma_min=1e-5,
- variance=1.0,
- dtype=tf.float32,
- random_seed=None,
- trainable=True,
- init_bs_to_zero=False,
- graph_collection_name="P_VARS"):
- self.state_size = state_size
- self.num_timesteps = num_timesteps
- self.sigma_min = sigma_min
- self.dtype = dtype
- self.variance = variance
- self.graph_collection_name = graph_collection_name
- if init_bs_to_zero:
- initializers = [tf.zeros_initializer for _ in xrange(num_timesteps)]
- else:
- initializers = [tf.random_uniform_initializer(seed=random_seed) for _ in xrange(num_timesteps)]
-
- self.bs = [
- tf.get_variable(
- shape=[state_size],
- dtype=self.dtype,
- name="p_b_%d" % (t + 1),
- initializer=initializers[t],
- collections=[tf.GraphKeys.GLOBAL_VARIABLES, graph_collection_name],
- trainable=trainable) for t in xrange(num_timesteps)
- ]
- self.Bs = tf.cumsum(self.bs, reverse=True, axis=0)
-
- def posterior(self, observation, prev_state, t):
- """Computes the true posterior p(z_t|z_{t-1}, z_n)."""
- # bs[0] is really b_1
- # Bs[i] is sum from k=i+1^n b_k
- mu = observation - self.Bs[t]
- if t > 0:
- mu += (prev_state + self.bs[t - 1]) * float(self.num_timesteps - t)
- mu /= float(self.num_timesteps - t + 1)
- sigma = tf.ones_like(mu) * self.variance * (
- float(self.num_timesteps - t) / float(self.num_timesteps - t + 1))
- return tf.contrib.distributions.Normal(loc=mu, scale=tf.sqrt(sigma))
-
- def lookahead(self, state, t):
- """Computes the true lookahead distribution p(z_n|z_t)."""
- mu = state + self.Bs[t]
- sigma = tf.ones_like(state) * self.variance * float(self.num_timesteps - t)
- return tf.contrib.distributions.Normal(loc=mu, scale=tf.sqrt(sigma))
-
- def likelihood(self, observation):
- batch_size = tf.shape(observation)[0]
- mu = tf.tile(tf.reduce_sum(self.bs, axis=0)[tf.newaxis, :], [batch_size, 1])
- sigma = tf.ones_like(mu) * self.variance * (self.num_timesteps + 1)
- dist = tf.contrib.distributions.Normal(loc=mu, scale=tf.sqrt(sigma))
- # Average over the batch and take the sum over the state size
- return tf.reduce_mean(tf.reduce_sum(dist.log_prob(observation), axis=1))
-
- def p_zt(self, prev_state, t):
- """Computes the model p(z_t| z_{t-1})."""
- batch_size = tf.shape(prev_state)[0]
- if t > 0:
- z_mu_p = prev_state + self.bs[t - 1]
- else: # p(z_0) is Normal(0,1)
- z_mu_p = tf.zeros([batch_size, self.state_size], dtype=self.dtype)
- p_zt = tf.contrib.distributions.Normal(
- loc=z_mu_p, scale=tf.sqrt(tf.ones_like(z_mu_p) * self.variance))
- return p_zt
-
- def generative(self, unused_observation, z_nm1):
- """Computes the model's generative distribution p(z_n| z_{n-1})."""
- generative_p_mu = z_nm1 + self.bs[-1]
- return tf.contrib.distributions.Normal(
- loc=generative_p_mu, scale=tf.sqrt(tf.ones_like(generative_p_mu) * self.variance))
-
-
-class ShortChainNonlinearP(object):
-
- def __init__(self,
- state_size,
- num_timesteps,
- sigma_min=1e-5,
- variance=1.0,
- observation_variance=1.0,
- transition_type=STANDARD_TRANSITION,
- transition_dist=tf.contrib.distributions.Normal,
- dtype=tf.float32,
- random_seed=None):
- self.state_size = state_size
- self.num_timesteps = num_timesteps
- self.sigma_min = sigma_min
- self.dtype = dtype
- self.variance = variance
- self.observation_variance = observation_variance
- self.transition_type = transition_type
- self.transition_dist = transition_dist
-
- def p_zt(self, prev_state, t):
- """Computes the model p(z_t| z_{t-1})."""
- batch_size = tf.shape(prev_state)[0]
- if t > 0:
- if self.transition_type == ROUND_TRANSITION:
- loc = tf.round(prev_state)
- tf.logging.info("p(z_%d | z_%d) ~ N(round(z_%d), %0.1f)" % (t, t-1, t-1, self.variance))
- elif self.transition_type == STANDARD_TRANSITION:
- loc = prev_state
- tf.logging.info("p(z_%d | z_%d) ~ N(z_%d, %0.1f)" % (t, t-1, t-1, self.variance))
- else: # p(z_0) is Normal(0,1)
- loc = tf.zeros([batch_size, self.state_size], dtype=self.dtype)
- tf.logging.info("p(z_0) ~ N(0,%0.1f)" % self.variance)
-
- p_zt = self.transition_dist(
- loc=loc,
- scale=tf.sqrt(tf.ones_like(loc) * self.variance))
- return p_zt
-
- def generative(self, unused_obs, z_ni):
- """Computes the model's generative distribution p(x_i| z_{ni})."""
- if self.transition_type == ROUND_TRANSITION:
- loc = tf.round(z_ni)
- elif self.transition_type == STANDARD_TRANSITION:
- loc = z_ni
- generative_sigma_sq = tf.ones_like(loc) * self.observation_variance
- return self.transition_dist(
- loc=loc, scale=tf.sqrt(generative_sigma_sq))
-
-
-class BimodalPriorP(object):
-
- def __init__(self,
- state_size,
- num_timesteps,
- mixing_coeff=0.5,
- prior_mode_mean=1,
- sigma_min=1e-5,
- variance=1.0,
- dtype=tf.float32,
- random_seed=None,
- trainable=True,
- init_bs_to_zero=False,
- graph_collection_name="P_VARS"):
- self.state_size = state_size
- self.num_timesteps = num_timesteps
- self.sigma_min = sigma_min
- self.dtype = dtype
- self.variance = variance
- self.mixing_coeff = mixing_coeff
- self.prior_mode_mean = prior_mode_mean
-
- if init_bs_to_zero:
- initializers = [tf.zeros_initializer for _ in xrange(num_timesteps)]
- else:
- initializers = [tf.random_uniform_initializer(seed=random_seed) for _ in xrange(num_timesteps)]
-
- self.bs = [
- tf.get_variable(
- shape=[state_size],
- dtype=self.dtype,
- name="b_%d" % (t + 1),
- initializer=initializers[t],
- collections=[tf.GraphKeys.GLOBAL_VARIABLES, graph_collection_name],
- trainable=trainable) for t in xrange(num_timesteps)
- ]
- self.Bs = tf.cumsum(self.bs, reverse=True, axis=0)
-
- def posterior(self, observation, prev_state, t):
- # NOTE: This is currently wrong, but would require a refactoring of
- # summarize_q to fix as kl is not defined for a mixture
- """Computes the true posterior p(z_t|z_{t-1}, z_n)."""
- # bs[0] is really b_1
- # Bs[i] is sum from k=i+1^n b_k
- mu = observation - self.Bs[t]
- if t > 0:
- mu += (prev_state + self.bs[t - 1]) * float(self.num_timesteps - t)
- mu /= float(self.num_timesteps - t + 1)
- sigma = tf.ones_like(mu) * self.variance * (
- float(self.num_timesteps - t) / float(self.num_timesteps - t + 1))
- return tf.contrib.distributions.Normal(loc=mu, scale=tf.sqrt(sigma))
-
- def lookahead(self, state, t):
- """Computes the true lookahead distribution p(z_n|z_t)."""
- mu = state + self.Bs[t]
- sigma = tf.ones_like(state) * self.variance * float(self.num_timesteps - t)
- return tf.contrib.distributions.Normal(loc=mu, scale=tf.sqrt(sigma))
-
- def likelihood(self, observation):
- batch_size = tf.shape(observation)[0]
- sum_of_bs = tf.tile(tf.reduce_sum(self.bs, axis=0)[tf.newaxis, :], [batch_size, 1])
- sigma = tf.ones_like(sum_of_bs) * self.variance * (self.num_timesteps + 1)
- mu_pos = (tf.ones([batch_size, self.state_size], dtype=self.dtype) * self.prior_mode_mean) + sum_of_bs
- mu_neg = (tf.ones([batch_size, self.state_size], dtype=self.dtype) * -self.prior_mode_mean) + sum_of_bs
- zn_pos = tf.contrib.distributions.Normal(
- loc=mu_pos,
- scale=tf.sqrt(sigma))
- zn_neg = tf.contrib.distributions.Normal(
- loc=mu_neg,
- scale=tf.sqrt(sigma))
- mode_probs = tf.convert_to_tensor([self.mixing_coeff, 1-self.mixing_coeff], dtype=tf.float64)
- mode_probs = tf.tile(mode_probs[tf.newaxis, tf.newaxis, :], [batch_size, 1, 1])
- mode_selection_dist = tf.contrib.distributions.Categorical(probs=mode_probs)
- zn_dist = tf.contrib.distributions.Mixture(
- cat=mode_selection_dist,
- components=[zn_pos, zn_neg],
- validate_args=True)
- # Average over the batch and take the sum over the state size
- return tf.reduce_mean(tf.reduce_sum(zn_dist.log_prob(observation), axis=1))
-
- def p_zt(self, prev_state, t):
- """Computes the model p(z_t| z_{t-1})."""
- batch_size = tf.shape(prev_state)[0]
- if t > 0:
- z_mu_p = prev_state + self.bs[t - 1]
- p_zt = tf.contrib.distributions.Normal(
- loc=z_mu_p, scale=tf.sqrt(tf.ones_like(z_mu_p) * self.variance))
- return p_zt
- else: # p(z_0) is mixture of two Normals
- mu_pos = tf.ones([batch_size, self.state_size], dtype=self.dtype) * self.prior_mode_mean
- mu_neg = tf.ones([batch_size, self.state_size], dtype=self.dtype) * -self.prior_mode_mean
- z0_pos = tf.contrib.distributions.Normal(
- loc=mu_pos,
- scale=tf.sqrt(tf.ones_like(mu_pos) * self.variance))
- z0_neg = tf.contrib.distributions.Normal(
- loc=mu_neg,
- scale=tf.sqrt(tf.ones_like(mu_neg) * self.variance))
- mode_probs = tf.convert_to_tensor([self.mixing_coeff, 1-self.mixing_coeff], dtype=tf.float64)
- mode_probs = tf.tile(mode_probs[tf.newaxis, tf.newaxis, :], [batch_size, 1, 1])
- mode_selection_dist = tf.contrib.distributions.Categorical(probs=mode_probs)
- z0_dist = tf.contrib.distributions.Mixture(
- cat=mode_selection_dist,
- components=[z0_pos, z0_neg],
- validate_args=False)
- return z0_dist
-
- def generative(self, unused_observation, z_nm1):
- """Computes the model's generative distribution p(z_n| z_{n-1})."""
- generative_p_mu = z_nm1 + self.bs[-1]
- return tf.contrib.distributions.Normal(
- loc=generative_p_mu, scale=tf.sqrt(tf.ones_like(generative_p_mu) * self.variance))
-
-class Model(object):
-
- def __init__(self,
- p,
- q,
- r,
- state_size,
- num_timesteps,
- dtype=tf.float32):
- self.p = p
- self.q = q
- self.r = r
- self.state_size = state_size
- self.num_timesteps = num_timesteps
- self.dtype = dtype
-
- def zero_state(self, batch_size):
- return tf.zeros([batch_size, self.state_size], dtype=self.dtype)
-
- def __call__(self, prev_state, observation, t):
- # Compute the q distribution over z, q(z_t|z_n, z_{t-1}).
- q_zt = self.q.q_zt(observation, prev_state, t)
- # Compute the p distribution over z, p(z_t|z_{t-1}).
- p_zt = self.p.p_zt(prev_state, t)
- # sample from q
- zt = q_zt.sample()
- r_xn = self.r.r_xn(zt, t)
- # Calculate the logprobs and sum over the state size.
- log_q_zt = tf.reduce_sum(q_zt.log_prob(zt), axis=1)
- log_p_zt = tf.reduce_sum(p_zt.log_prob(zt), axis=1)
- log_r_xn = tf.reduce_sum(r_xn.log_prob(observation), axis=1)
- # If we're at the last timestep, also calc the logprob of the observation.
- if t == self.num_timesteps - 1:
- generative_dist = self.p.generative(observation, zt)
- log_p_x_given_z = tf.reduce_sum(generative_dist.log_prob(observation), axis=1)
- else:
- log_p_x_given_z = tf.zeros_like(log_q_zt)
- return (zt, log_q_zt, log_p_zt, log_p_x_given_z, log_r_xn)
-
- @staticmethod
- def create(state_size,
- num_timesteps,
- sigma_min=1e-5,
- r_sigma_init=1,
- variance=1.0,
- mixing_coeff=0.5,
- prior_mode_mean=1.0,
- dtype=tf.float32,
- random_seed=None,
- train_p=True,
- p_type="unimodal",
- q_type="normal",
- observation_variance=1.0,
- transition_type=STANDARD_TRANSITION,
- use_bs=True):
- if p_type == "unimodal":
- p = P(state_size,
- num_timesteps,
- sigma_min=sigma_min,
- variance=variance,
- dtype=dtype,
- random_seed=random_seed,
- trainable=train_p,
- init_bs_to_zero=not use_bs)
- elif p_type == "bimodal":
- p = BimodalPriorP(
- state_size,
- num_timesteps,
- mixing_coeff=mixing_coeff,
- prior_mode_mean=prior_mode_mean,
- sigma_min=sigma_min,
- variance=variance,
- dtype=dtype,
- random_seed=random_seed,
- trainable=train_p,
- init_bs_to_zero=not use_bs)
- elif "nonlinear" in p_type:
- if "cauchy" in p_type:
- trans_dist = tf.contrib.distributions.Cauchy
- else:
- trans_dist = tf.contrib.distributions.Normal
- p = ShortChainNonlinearP(
- state_size,
- num_timesteps,
- sigma_min=sigma_min,
- variance=variance,
- observation_variance=observation_variance,
- transition_type=transition_type,
- transition_dist=trans_dist,
- dtype=dtype,
- random_seed=random_seed
- )
-
- if q_type == "normal":
- q_class = Q
- elif q_type == "simple_mean":
- q_class = SimpleMeanQ
- elif q_type == "prev_state":
- q_class = PreviousStateQ
- elif q_type == "observation":
- q_class = ObservationQ
-
- q = q_class(state_size,
- num_timesteps,
- sigma_min=sigma_min,
- dtype=dtype,
- random_seed=random_seed,
- init_mu0_to_zero=not use_bs)
- r = R(state_size,
- num_timesteps,
- sigma_min=sigma_min,
- sigma_init=r_sigma_init,
- dtype=dtype,
- random_seed=random_seed)
- model = Model(p, q, r, state_size, num_timesteps, dtype=dtype)
- return model
-
-
-class BackwardsModel(object):
-
- def __init__(self,
- state_size,
- num_timesteps,
- sigma_min=1e-5,
- dtype=tf.float32):
- self.state_size = state_size
- self.num_timesteps = num_timesteps
- self.sigma_min = sigma_min
- self.dtype = dtype
- self.bs = [
- tf.get_variable(
- shape=[state_size],
- dtype=self.dtype,
- name="b_%d" % (t + 1),
- initializer=tf.zeros_initializer) for t in xrange(num_timesteps)
- ]
- self.Bs = tf.cumsum(self.bs, reverse=True, axis=0)
- self.q_mus = [
- snt.Linear(output_size=state_size) for _ in xrange(num_timesteps)
- ]
- self.q_sigmas = [
- tf.get_variable(
- shape=[state_size],
- dtype=self.dtype,
- name="q_sigma_%d" % (t + 1),
- initializer=tf.zeros_initializer) for t in xrange(num_timesteps)
- ]
- self.r_mus = [
- tf.get_variable(
- shape=[state_size],
- dtype=self.dtype,
- name="r_mu_%d" % (t + 1),
- initializer=tf.zeros_initializer) for t in xrange(num_timesteps)
- ]
- self.r_sigmas = [
- tf.get_variable(
- shape=[state_size],
- dtype=self.dtype,
- name="r_sigma_%d" % (t + 1),
- initializer=tf.zeros_initializer) for t in xrange(num_timesteps)
- ]
-
- def zero_state(self, batch_size):
- return tf.zeros([batch_size, self.state_size], dtype=self.dtype)
-
- def posterior(self, unused_observation, prev_state, unused_t):
- # TODO(dieterichl): Correct this.
- return tf.contrib.distributions.Normal(
- loc=tf.zeros_like(prev_state), scale=tf.zeros_like(prev_state))
-
- def lookahead(self, state, unused_t):
- # TODO(dieterichl): Correct this.
- return tf.contrib.distributions.Normal(
- loc=tf.zeros_like(state), scale=tf.zeros_like(state))
-
- def q_zt(self, observation, next_state, t):
- """Computes the variational posterior q(z_{t}|z_{t+1}, z_n)."""
- t_backwards = self.num_timesteps - t - 1
- batch_size = tf.shape(next_state)[0]
- q_mu = self.q_mus[t_backwards](tf.concat([observation, next_state], axis=1))
- q_sigma = tf.maximum(
- tf.nn.softplus(self.q_sigmas[t_backwards]), self.sigma_min)
- q_sigma = tf.tile(q_sigma[tf.newaxis, :], [batch_size, 1])
- q_zt = tf.contrib.distributions.Normal(loc=q_mu, scale=tf.sqrt(q_sigma))
- return q_zt
-
- def p_zt(self, prev_state, t):
- """Computes the model p(z_{t+1}| z_{t})."""
- t_backwards = self.num_timesteps - t - 1
- z_mu_p = prev_state + self.bs[t_backwards]
- p_zt = tf.contrib.distributions.Normal(
- loc=z_mu_p, scale=tf.ones_like(z_mu_p))
- return p_zt
-
- def generative(self, unused_observation, z_nm1):
- """Computes the model's generative distribution p(z_n| z_{n-1})."""
- generative_p_mu = z_nm1 + self.bs[-1]
- return tf.contrib.distributions.Normal(
- loc=generative_p_mu, scale=tf.ones_like(generative_p_mu))
-
- def r(self, z_t, t):
- t_backwards = self.num_timesteps - t - 1
- batch_size = tf.shape(z_t)[0]
- r_mu = tf.tile(self.r_mus[t_backwards][tf.newaxis, :], [batch_size, 1])
- r_sigma = tf.maximum(
- tf.nn.softplus(self.r_sigmas[t_backwards]), self.sigma_min)
- r_sigma = tf.tile(r_sigma[tf.newaxis, :], [batch_size, 1])
- return tf.contrib.distributions.Normal(loc=r_mu, scale=tf.sqrt(r_sigma))
-
- def likelihood(self, observation):
- batch_size = tf.shape(observation)[0]
- mu = tf.tile(tf.reduce_sum(self.bs, axis=0)[tf.newaxis, :], [batch_size, 1])
- sigma = tf.ones_like(mu) * (self.num_timesteps + 1)
- dist = tf.contrib.distributions.Normal(loc=mu, scale=tf.sqrt(sigma))
- # Average over the batch and take the sum over the state size
- return tf.reduce_mean(tf.reduce_sum(dist.log_prob(observation), axis=1))
-
- def __call__(self, next_state, observation, t):
- # next state = z_{t+1}
- # Compute the q distribution over z, q(z_{t}|z_n, z_{t+1}).
- q_zt = self.q_zt(observation, next_state, t)
- # sample from q
- zt = q_zt.sample()
- # Compute the p distribution over z, p(z_{t+1}|z_{t}).
- p_zt = self.p_zt(zt, t)
- # Compute log p(z_{t+1} | z_t)
- if t == 0:
- log_p_zt = p_zt.log_prob(observation)
- else:
- log_p_zt = p_zt.log_prob(next_state)
-
- # Compute r prior over zt
- r_zt = self.r(zt, t)
- log_r_zt = r_zt.log_prob(zt)
- # Compute proposal density at zt
- log_q_zt = q_zt.log_prob(zt)
- # If we're at the last timestep, also calc the logprob of the observation.
-
- if t == self.num_timesteps - 1:
- p_z0_dist = tf.contrib.distributions.Normal(
- loc=tf.zeros_like(zt), scale=tf.ones_like(zt))
- z0_log_prob = p_z0_dist.log_prob(zt)
- else:
- z0_log_prob = tf.zeros_like(log_q_zt)
- return (zt, log_q_zt, log_p_zt, z0_log_prob, log_r_zt)
-
-
-class LongChainP(object):
-
- def __init__(self,
- state_size,
- num_obs,
- steps_per_obs,
- sigma_min=1e-5,
- variance=1.0,
- observation_variance=1.0,
- observation_type=STANDARD_OBSERVATION,
- transition_type=STANDARD_TRANSITION,
- dtype=tf.float32,
- random_seed=None):
- self.state_size = state_size
- self.steps_per_obs = steps_per_obs
- self.num_obs = num_obs
- self.num_timesteps = steps_per_obs*num_obs + 1
- self.sigma_min = sigma_min
- self.dtype = dtype
- self.variance = variance
- self.observation_variance = observation_variance
- self.observation_type = observation_type
- self.transition_type = transition_type
-
- def likelihood(self, observations):
- """Computes the model's true likelihood of the observations.
-
- Args:
- observations: A [batch_size, m, state_size] Tensor representing each of
- the m observations.
- Returns:
- logprob: The true likelihood of the observations given the model.
- """
- raise ValueError("Likelihood is not defined for long-chain models")
- # batch_size = tf.shape(observations)[0]
- # mu = tf.zeros([batch_size, self.state_size, self.num_obs], dtype=self.dtype)
- # sigma = np.fromfunction(
- # lambda i, j: 1 + self.steps_per_obs*np.minimum(i+1, j+1),
- # [self.num_obs, self.num_obs])
- # sigma += np.eye(self.num_obs)
- # sigma = tf.convert_to_tensor(sigma * self.variance, dtype=self.dtype)
- # sigma = tf.tile(sigma[tf.newaxis, tf.newaxis, ...],
- # [batch_size, self.state_size, 1, 1])
- # dist = tf.contrib.distributions.MultivariateNormalFullCovariance(
- # loc=mu,
- # covariance_matrix=sigma)
- # Average over the batch and take the sum over the state size
- #return tf.reduce_mean(tf.reduce_sum(dist.log_prob(observations), axis=1))
-
- def p_zt(self, prev_state, t):
- """Computes the model p(z_t| z_{t-1})."""
- batch_size = tf.shape(prev_state)[0]
- if t > 0:
- if self.transition_type == ROUND_TRANSITION:
- loc = tf.round(prev_state)
- tf.logging.info("p(z_%d | z_%d) ~ N(round(z_%d), %0.1f)" % (t, t-1, t-1, self.variance))
- elif self.transition_type == STANDARD_TRANSITION:
- loc = prev_state
- tf.logging.info("p(z_%d | z_%d) ~ N(z_%d, %0.1f)" % (t, t-1, t-1, self.variance))
- else: # p(z_0) is Normal(0,1)
- loc = tf.zeros([batch_size, self.state_size], dtype=self.dtype)
- tf.logging.info("p(z_0) ~ N(0,%0.1f)" % self.variance)
-
- p_zt = tf.contrib.distributions.Normal(
- loc=loc,
- scale=tf.sqrt(tf.ones_like(loc) * self.variance))
- return p_zt
-
- def generative(self, z_ni, t):
- """Computes the model's generative distribution p(x_i| z_{ni})."""
- if self.observation_type == SQUARED_OBSERVATION:
- generative_mu = tf.square(z_ni)
- tf.logging.info("p(x_%d | z_%d) ~ N(z_%d^2, %0.1f)" % (t, t, t, self.variance))
- elif self.observation_type == ABS_OBSERVATION:
- generative_mu = tf.abs(z_ni)
- tf.logging.info("p(x_%d | z_%d) ~ N(|z_%d|, %0.1f)" % (t, t, t, self.variance))
- elif self.observation_type == STANDARD_OBSERVATION:
- generative_mu = z_ni
- tf.logging.info("p(x_%d | z_%d) ~ N(z_%d, %0.1f)" % (t, t, t, self.variance))
- generative_sigma_sq = tf.ones_like(generative_mu) * self.observation_variance
- return tf.contrib.distributions.Normal(
- loc=generative_mu, scale=tf.sqrt(generative_sigma_sq))
-
-
-class LongChainQ(object):
-
- def __init__(self,
- state_size,
- num_obs,
- steps_per_obs,
- sigma_min=1e-5,
- dtype=tf.float32,
- random_seed=None):
- self.state_size = state_size
- self.sigma_min = sigma_min
- self.dtype = dtype
- self.steps_per_obs = steps_per_obs
- self.num_obs = num_obs
- self.num_timesteps = num_obs*steps_per_obs +1
-
- initializers = {
- "w": tf.random_uniform_initializer(seed=random_seed),
- "b": tf.zeros_initializer
- }
- self.mus = [
- snt.Linear(output_size=state_size, initializers=initializers)
- for t in xrange(self.num_timesteps)
- ]
- self.sigmas = [
- tf.get_variable(
- shape=[state_size],
- dtype=self.dtype,
- name="q_sigma_%d" % (t + 1),
- initializer=tf.random_uniform_initializer(seed=random_seed))
- for t in xrange(self.num_timesteps)
- ]
-
- def first_relevant_obs_index(self, t):
- return int(max((t-1)/self.steps_per_obs, 0))
-
- def q_zt(self, observations, prev_state, t):
- """Computes a distribution over z_t.
-
- Args:
- observations: a [batch_size, num_observations, state_size] Tensor.
- prev_state: a [batch_size, state_size] Tensor.
- t: The current timestep, an int Tensor.
- """
- # filter out unneeded past obs
- first_relevant_obs_index = int(math.floor(max(t-1, 0) / self.steps_per_obs))
- num_relevant_observations = self.num_obs - first_relevant_obs_index
- observations = observations[:,first_relevant_obs_index:,:]
- batch_size = tf.shape(prev_state)[0]
- # concatenate the prev state and observations along the second axis (that is
- # not the batch or state size axis, and then flatten it to
- # [batch_size, (num_relevant_observations + 1) * state_size] to feed it into
- # the linear layer.
- q_input = tf.concat([observations, prev_state[:,tf.newaxis, :]], axis=1)
- q_input = tf.reshape(q_input,
- [batch_size, (num_relevant_observations + 1) * self.state_size])
- q_mu = self.mus[t](q_input)
- q_sigma = tf.maximum(tf.nn.softplus(self.sigmas[t]), self.sigma_min)
- q_sigma = tf.tile(q_sigma[tf.newaxis, :], [batch_size, 1])
- q_zt = tf.contrib.distributions.Normal(loc=q_mu, scale=tf.sqrt(q_sigma))
- tf.logging.info(
- "q(z_{t} | z_{tm1}, x_{obsf}:{obst}) ~ N(Linear([z_{tm1},x_{obsf}:{obst}]), sigma_{t})".format(
- **{"t": t,
- "tm1": t-1,
- "obsf": (first_relevant_obs_index+1)*self.steps_per_obs,
- "obst":self.steps_per_obs*self.num_obs}))
- return q_zt
-
- def summarize_weights(self):
- pass
-
-class LongChainR(object):
-
- def __init__(self,
- state_size,
- num_obs,
- steps_per_obs,
- sigma_min=1e-5,
- dtype=tf.float32,
- random_seed=None):
- self.state_size = state_size
- self.dtype = dtype
- self.sigma_min = sigma_min
- self.steps_per_obs = steps_per_obs
- self.num_obs = num_obs
- self.num_timesteps = num_obs*steps_per_obs + 1
- self.sigmas = [
- tf.get_variable(
- shape=[self.num_future_obs(t)],
- dtype=self.dtype,
- name="r_sigma_%d" % (t + 1),
- #initializer=tf.random_uniform_initializer(seed=random_seed, maxval=100))
- initializer=tf.constant_initializer(1.0))
- for t in range(self.num_timesteps)
- ]
-
- def first_future_obs_index(self, t):
- return int(math.floor(t / self.steps_per_obs))
-
- def num_future_obs(self, t):
- return int(self.num_obs - self.first_future_obs_index(t))
-
- def r_xn(self, z_t, t):
- """Computes a distribution over the future observations given current latent
- state.
-
- The indexing in these messages is 1 indexed and inclusive. This is
- consistent with the latex documents.
-
- Args:
- z_t: [batch_size, state_size] Tensor
- t: Current timestep
- """
- tf.logging.info(
- "r(x_{start}:{end} | z_{t}) ~ N(z_{t}, sigma_{t})".format(
- **{"t": t,
- "start": (self.first_future_obs_index(t)+1)*self.steps_per_obs,
- "end": self.num_timesteps-1}))
- batch_size = tf.shape(z_t)[0]
- # the mean for all future observations is the same.
- # this tiling results in a [batch_size, num_future_obs, state_size] Tensor
- r_mu = tf.tile(z_t[:,tf.newaxis,:], [1, self.num_future_obs(t), 1])
- # compute the variance
- r_sigma = tf.maximum(tf.nn.softplus(self.sigmas[t]), self.sigma_min)
- # the variance is the same across all state dimensions, so we only have to
- # time sigma to be [batch_size, num_future_obs].
- r_sigma = tf.tile(r_sigma[tf.newaxis,:, tf.newaxis], [batch_size, 1, self.state_size])
- return tf.contrib.distributions.Normal(
- loc=r_mu, scale=tf.sqrt(r_sigma))
-
- def summarize_weights(self):
- pass
-
-
-class LongChainModel(object):
-
- def __init__(self,
- p,
- q,
- r,
- state_size,
- num_obs,
- steps_per_obs,
- dtype=tf.float32,
- disable_r=False):
- self.p = p
- self.q = q
- self.r = r
- self.disable_r = disable_r
- self.state_size = state_size
- self.num_obs = num_obs
- self.steps_per_obs = steps_per_obs
- self.num_timesteps = steps_per_obs*num_obs + 1
- self.dtype = dtype
-
- def zero_state(self, batch_size):
- return tf.zeros([batch_size, self.state_size], dtype=self.dtype)
-
- def next_obs_ind(self, t):
- return int(math.floor(max(t-1,0)/self.steps_per_obs))
-
- def __call__(self, prev_state, observations, t):
- """Computes the importance weight for the model system.
-
- Args:
- prev_state: [batch_size, state_size] Tensor
- observations: [batch_size, num_observations, state_size] Tensor
- """
- # Compute the q distribution over z, q(z_t|z_n, z_{t-1}).
- q_zt = self.q.q_zt(observations, prev_state, t)
- # Compute the p distribution over z, p(z_t|z_{t-1}).
- p_zt = self.p.p_zt(prev_state, t)
- # sample from q and evaluate the logprobs, summing over the state size
- zt = q_zt.sample()
- log_q_zt = tf.reduce_sum(q_zt.log_prob(zt), axis=1)
- log_p_zt = tf.reduce_sum(p_zt.log_prob(zt), axis=1)
- if not self.disable_r and t < self.num_timesteps-1:
- # score the remaining observations using r
- r_xn = self.r.r_xn(zt, t)
- log_r_xn = r_xn.log_prob(observations[:, self.next_obs_ind(t+1):, :])
- # sum over state size and observation, leaving the batch index
- log_r_xn = tf.reduce_sum(log_r_xn, axis=[1,2])
- else:
- log_r_xn = tf.zeros_like(log_p_zt)
- if t != 0 and t % self.steps_per_obs == 0:
- generative_dist = self.p.generative(zt, t)
- log_p_x_given_z = generative_dist.log_prob(observations[:,self.next_obs_ind(t),:])
- log_p_x_given_z = tf.reduce_sum(log_p_x_given_z, axis=1)
- else:
- log_p_x_given_z = tf.zeros_like(log_q_zt)
- return (zt, log_q_zt, log_p_zt, log_p_x_given_z, log_r_xn)
-
- @staticmethod
- def create(state_size,
- num_obs,
- steps_per_obs,
- sigma_min=1e-5,
- variance=1.0,
- observation_variance=1.0,
- observation_type=STANDARD_OBSERVATION,
- transition_type=STANDARD_TRANSITION,
- dtype=tf.float32,
- random_seed=None,
- disable_r=False):
- p = LongChainP(
- state_size,
- num_obs,
- steps_per_obs,
- sigma_min=sigma_min,
- variance=variance,
- observation_variance=observation_variance,
- observation_type=observation_type,
- transition_type=transition_type,
- dtype=dtype,
- random_seed=random_seed)
- q = LongChainQ(
- state_size,
- num_obs,
- steps_per_obs,
- sigma_min=sigma_min,
- dtype=dtype,
- random_seed=random_seed)
- r = LongChainR(
- state_size,
- num_obs,
- steps_per_obs,
- sigma_min=sigma_min,
- dtype=dtype,
- random_seed=random_seed)
- model = LongChainModel(
- p, q, r, state_size, num_obs, steps_per_obs,
- dtype=dtype,
- disable_r=disable_r)
- return model
-
-
-class RTilde(object):
-
- def __init__(self,
- state_size,
- num_timesteps,
- sigma_min=1e-5,
- dtype=tf.float32,
- random_seed=None,
- graph_collection_name="R_TILDE_VARS"):
- self.dtype = dtype
- self.sigma_min = sigma_min
- initializers = {"w": tf.truncated_normal_initializer(seed=random_seed),
- "b": tf.zeros_initializer}
- self.graph_collection_name=graph_collection_name
-
- def custom_getter(getter, *args, **kwargs):
- out = getter(*args, **kwargs)
- ref = tf.get_collection_ref(self.graph_collection_name)
- if out not in ref:
- ref.append(out)
- return out
-
- self.fns = [
- snt.Linear(output_size=2*state_size,
- initializers=initializers,
- name="r_tilde_%d" % t,
- custom_getter=custom_getter)
- for t in xrange(num_timesteps)
- ]
-
- def r_zt(self, z_t, observation, t):
- #out = self.fns[t](tf.stop_gradient(tf.concat([z_t, observation], axis=1)))
- out = self.fns[t](tf.concat([z_t, observation], axis=1))
- mu, raw_sigma_sq = tf.split(out, 2, axis=1)
- sigma_sq = tf.maximum(tf.nn.softplus(raw_sigma_sq), self.sigma_min)
- return mu, sigma_sq
-
-class TDModel(object):
-
- def __init__(self,
- p,
- q,
- r_tilde,
- state_size,
- num_timesteps,
- dtype=tf.float32,
- disable_r=False):
- self.p = p
- self.q = q
- self.r_tilde = r_tilde
- self.disable_r = disable_r
- self.state_size = state_size
- self.num_timesteps = num_timesteps
- self.dtype = dtype
-
- def zero_state(self, batch_size):
- return tf.zeros([batch_size, self.state_size], dtype=self.dtype)
-
- def __call__(self, prev_state, observation, t):
- """Computes the importance weight for the model system.
-
- Args:
- prev_state: [batch_size, state_size] Tensor
- observations: [batch_size, num_observations, state_size] Tensor
- """
- # Compute the q distribution over z, q(z_t|z_n, z_{t-1}).
- q_zt = self.q.q_zt(observation, prev_state, t)
- # Compute the p distribution over z, p(z_t|z_{t-1}).
- p_zt = self.p.p_zt(prev_state, t)
- # sample from q and evaluate the logprobs, summing over the state size
- zt = q_zt.sample()
- # If it isn't the last timestep, compute the distribution over the next z.
- if t < self.num_timesteps - 1:
- p_ztplus1 = self.p.p_zt(zt, t+1)
- else:
- p_ztplus1 = None
- log_q_zt = tf.reduce_sum(q_zt.log_prob(zt), axis=1)
- log_p_zt = tf.reduce_sum(p_zt.log_prob(zt), axis=1)
-
- if not self.disable_r and t < self.num_timesteps-1:
- # score the remaining observations using r
- r_tilde_mu, r_tilde_sigma_sq = self.r_tilde.r_zt(zt, observation, t+1)
- else:
- r_tilde_mu = None
- r_tilde_sigma_sq = None
- if t == self.num_timesteps - 1:
- generative_dist = self.p.generative(observation, zt)
- log_p_x_given_z = tf.reduce_sum(generative_dist.log_prob(observation), axis=1)
- else:
- log_p_x_given_z = tf.zeros_like(log_q_zt)
- return (zt, log_q_zt, log_p_zt, log_p_x_given_z,
- r_tilde_mu, r_tilde_sigma_sq, p_ztplus1)
-
- @staticmethod
- def create(state_size,
- num_timesteps,
- sigma_min=1e-5,
- variance=1.0,
- dtype=tf.float32,
- random_seed=None,
- train_p=True,
- p_type="unimodal",
- q_type="normal",
- mixing_coeff=0.5,
- prior_mode_mean=1.0,
- observation_variance=1.0,
- transition_type=STANDARD_TRANSITION,
- use_bs=True):
- if p_type == "unimodal":
- p = P(state_size,
- num_timesteps,
- sigma_min=sigma_min,
- variance=variance,
- dtype=dtype,
- random_seed=random_seed,
- trainable=train_p,
- init_bs_to_zero=not use_bs)
- elif p_type == "bimodal":
- p = BimodalPriorP(
- state_size,
- num_timesteps,
- mixing_coeff=mixing_coeff,
- prior_mode_mean=prior_mode_mean,
- sigma_min=sigma_min,
- variance=variance,
- dtype=dtype,
- random_seed=random_seed,
- trainable=train_p,
- init_bs_to_zero=not use_bs)
- elif "nonlinear" in p_type:
- if "cauchy" in p_type:
- trans_dist = tf.contrib.distributions.Cauchy
- else:
- trans_dist = tf.contrib.distributions.Normal
-
- p = ShortChainNonlinearP(
- state_size,
- num_timesteps,
- sigma_min=sigma_min,
- variance=variance,
- observation_variance=observation_variance,
- transition_type=transition_type,
- transition_dist=trans_dist,
- dtype=dtype,
- random_seed=random_seed
- )
-
- if q_type == "normal":
- q_class = Q
- elif q_type == "simple_mean":
- q_class = SimpleMeanQ
- elif q_type == "prev_state":
- q_class = PreviousStateQ
- elif q_type == "observation":
- q_class = ObservationQ
-
- q = q_class(state_size,
- num_timesteps,
- sigma_min=sigma_min,
- dtype=dtype,
- random_seed=random_seed,
- init_mu0_to_zero=not use_bs)
- r_tilde = RTilde(
- state_size,
- num_timesteps,
- sigma_min=sigma_min,
- dtype=dtype,
- random_seed=random_seed)
- model = TDModel(p, q, r_tilde, state_size, num_timesteps, dtype=dtype)
- return model
diff --git a/research/fivo/experimental/run.sh b/research/fivo/experimental/run.sh
deleted file mode 100644
index c650f636d5313a196960a92b509202b47e7da518..0000000000000000000000000000000000000000
--- a/research/fivo/experimental/run.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/bash
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-
-model="forward"
-T=5
-num_obs=1
-var=0.1
-n=4
-lr=0.0001
-bound="fivo-aux"
-q_type="normal"
-resampling_method="multinomial"
-rgrad="true"
-p_type="unimodal"
-use_bs=false
-
-LOGDIR=/tmp/fivo/model-$model-$bound-$resampling_method-resampling-rgrad-$rgrad-T-$T-var-$var-n-$n-lr-$lr-q-$q_type-p-$p_type
-
-python train.py \
- --logdir=$LOGDIR \
- --model=$model \
- --bound=$bound \
- --q_type=$q_type \
- --p_type=$p_type \
- --variance=$var \
- --use_resampling_grads=$rgrad \
- --resampling=always \
- --resampling_method=$resampling_method \
- --batch_size=4 \
- --num_samples=$n \
- --num_timesteps=$T \
- --num_eval_samples=256 \
- --summarize_every=100 \
- --learning_rate=$lr \
- --decay_steps=1000000 \
- --max_steps=1000000000 \
- --random_seed=1234 \
- --train_p=false \
- --use_bs=$use_bs \
- --alsologtostderr
diff --git a/research/fivo/experimental/summary_utils.py b/research/fivo/experimental/summary_utils.py
deleted file mode 100644
index 04e4aeea257577e60d3651656d0c62355d501ea8..0000000000000000000000000000000000000000
--- a/research/fivo/experimental/summary_utils.py
+++ /dev/null
@@ -1,332 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Utils for plotting and summarizing.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import matplotlib.gridspec as gridspec
-import matplotlib.pyplot as plt
-import numpy as np
-import scipy
-
-import tensorflow as tf
-
-import models
-
-
-def summarize_ess(weights, only_last_timestep=False):
- """Plots the effective sample size.
-
- Args:
- weights: List of length num_timesteps Tensors of shape
- [num_samples, batch_size]
- """
- num_timesteps = len(weights)
- batch_size = tf.cast(tf.shape(weights[0])[1], dtype=tf.float64)
- for i in range(num_timesteps):
- if only_last_timestep and i < num_timesteps-1: continue
-
- w = tf.nn.softmax(weights[i], dim=0)
- centered_weights = w - tf.reduce_mean(w, axis=0, keepdims=True)
- variance = tf.reduce_sum(tf.square(centered_weights))/(batch_size-1)
- ess = 1./tf.reduce_mean(tf.reduce_sum(tf.square(w), axis=0))
- tf.summary.scalar("ess/%d" % i, ess)
- tf.summary.scalar("ese/%d" % i, ess / batch_size)
- tf.summary.scalar("weight_variance/%d" % i, variance)
-
-
-def summarize_particles(states, weights, observation, model):
- """Plots particle locations and weights.
-
- Args:
- states: List of length num_timesteps Tensors of shape
- [batch_size*num_particles, state_size].
- weights: List of length num_timesteps Tensors of shape [num_samples,
- batch_size]
- observation: Tensor of shape [batch_size*num_samples, state_size]
- """
- num_timesteps = len(weights)
- num_samples, batch_size = weights[0].get_shape().as_list()
- # get q0 information for plotting
- q0_dist = model.q.q_zt(observation, tf.zeros_like(states[0]), 0)
- q0_loc = q0_dist.loc[0:batch_size, 0]
- q0_scale = q0_dist.scale[0:batch_size, 0]
- # get posterior information for plotting
- post = (model.p.mixing_coeff, model.p.prior_mode_mean, model.p.variance,
- tf.reduce_sum(model.p.bs), model.p.num_timesteps)
-
- # Reshape states and weights to be [time, num_samples, batch_size]
- states = tf.stack(states)
- weights = tf.stack(weights)
- # normalize the weights over the sample dimension
- weights = tf.nn.softmax(weights, dim=1)
- states = tf.reshape(states, tf.shape(weights))
-
- ess = 1./tf.reduce_sum(tf.square(weights), axis=1)
-
- def _plot_states(states_batch, weights_batch, observation_batch, ess_batch, q0, post):
- """
- states: [time, num_samples, batch_size]
- weights [time, num_samples, batch_size]
- observation: [batch_size, 1]
- q0: ([batch_size], [batch_size])
- post: ...
- """
- num_timesteps, _, batch_size = states_batch.shape
- plots = []
- for i in range(batch_size):
- states = states_batch[:,:,i]
- weights = weights_batch[:,:,i]
- observation = observation_batch[i]
- ess = ess_batch[:,i]
- q0_loc = q0[0][i]
- q0_scale = q0[1][i]
-
- fig = plt.figure(figsize=(7, (num_timesteps + 1) * 2))
- # Each timestep gets two plots -- a bar plot and a histogram of state locs.
- # The bar plot will be bar_rows rows tall.
- # The histogram will be 1 row tall.
- # There is also 1 extra plot at the top showing the posterior and q.
- bar_rows = 8
- num_rows = (num_timesteps + 1) * (bar_rows + 1)
- gs = gridspec.GridSpec(num_rows, 1)
-
- # Figure out how wide to make the plot
- prior_lims = (post[1] * -2, post[1] * 2)
- q_lims = (scipy.stats.norm.ppf(0.01, loc=q0_loc, scale=q0_scale),
- scipy.stats.norm.ppf(0.99, loc=q0_loc, scale=q0_scale))
- state_width = states.max() - states.min()
- state_lims = (states.min() - state_width * 0.15,
- states.max() + state_width * 0.15)
-
- lims = (min(prior_lims[0], q_lims[0], state_lims[0]),
- max(prior_lims[1], q_lims[1], state_lims[1]))
- # plot the posterior
- z0 = np.arange(lims[0], lims[1], 0.1)
- alpha, pos_mu, sigma_sq, B, T = post
- neg_mu = -pos_mu
- scale = np.sqrt((T + 1) * sigma_sq)
- p_zn = (
- alpha * scipy.stats.norm.pdf(
- observation, loc=pos_mu + B, scale=scale) + (1 - alpha) *
- scipy.stats.norm.pdf(observation, loc=neg_mu + B, scale=scale))
- p_z0 = (
- alpha * scipy.stats.norm.pdf(z0, loc=pos_mu, scale=np.sqrt(sigma_sq))
- + (1 - alpha) * scipy.stats.norm.pdf(
- z0, loc=neg_mu, scale=np.sqrt(sigma_sq)))
- p_zn_given_z0 = scipy.stats.norm.pdf(
- observation, loc=z0 + B, scale=np.sqrt(T * sigma_sq))
- post_z0 = (p_z0 * p_zn_given_z0) / p_zn
- # plot q
- q_z0 = scipy.stats.norm.pdf(z0, loc=q0_loc, scale=q0_scale)
- ax = plt.subplot(gs[0:bar_rows, :])
- ax.plot(z0, q_z0, color="blue")
- ax.plot(z0, post_z0, color="green")
- ax.plot(z0, p_z0, color="red")
- ax.legend(("q", "posterior", "prior"), loc="best", prop={"size": 10})
-
- ax.set_xticks([])
- ax.set_xlim(*lims)
-
- # plot the states
- for t in range(num_timesteps):
- start = (t + 1) * (bar_rows + 1)
- ax1 = plt.subplot(gs[start:start + bar_rows, :])
- ax2 = plt.subplot(gs[start + bar_rows:start + bar_rows + 1, :])
- # plot the states barplot
- # ax1.hist(
- # states[t, :],
- # weights=weights[t, :],
- # bins=50,
- # edgecolor="none",
- # alpha=0.2)
- ax1.bar(states[t,:], weights[t,:], width=0.02, alpha=0.2, edgecolor = "none")
- ax1.set_ylabel("t=%d" % t)
- ax1.set_xticks([])
- ax1.grid(True, which="both")
- ax1.set_xlim(*lims)
- # plot the observation
- ax1.axvline(x=observation, color="red", linestyle="dashed")
- # add the ESS
- ax1.text(0.1, 0.9, "ESS: %0.2f" % ess[t],
- ha='center', va='center', transform=ax1.transAxes)
-
- # plot the state location histogram
- ax2.hist2d(
- states[t, :], np.zeros_like(states[t, :]), bins=[50, 1], cmap="Greys")
- ax2.grid(False)
- ax2.set_yticks([])
- ax2.set_xlim(*lims)
- if t != num_timesteps - 1:
- ax2.set_xticks([])
-
- fig.canvas.draw()
- p = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep="")
- plots.append(p.reshape(fig.canvas.get_width_height()[::-1] + (3,)))
- plt.close(fig)
- return np.stack(plots)
-
- plots = tf.py_func(_plot_states,
- [states, weights, observation, ess, (q0_loc, q0_scale), post],
- [tf.uint8])[0]
- tf.summary.image("states", plots, 5, collections=["infrequent_summaries"])
-
-
-def plot_weights(weights, resampled=None):
- """Plots the weights and effective sample size from an SMC rollout.
-
- Args:
- weights: [num_timesteps, num_samples, batch_size] importance weights
- resampled: [num_timesteps] 0/1 indicating if resampling ocurred
- """
- weights = tf.convert_to_tensor(weights)
-
- def _make_plots(weights, resampled):
- num_timesteps, num_samples, batch_size = weights.shape
- plots = []
- for i in range(batch_size):
- fig, axes = plt.subplots(nrows=1, sharex=True, figsize=(8, 4))
- axes.stackplot(np.arange(num_timesteps), np.transpose(weights[:, :, i]))
- axes.set_title("Weights")
- axes.set_xlabel("Steps")
- axes.set_ylim([0, 1])
- axes.set_xlim([0, num_timesteps - 1])
- for j in np.where(resampled > 0)[0]:
- axes.axvline(x=j, color="red", linestyle="dashed", ymin=0.0, ymax=1.0)
- fig.canvas.draw()
- data = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep="")
- data = data.reshape(fig.canvas.get_width_height()[::-1] + (3,))
- plots.append(data)
- plt.close(fig)
- return np.stack(plots, axis=0)
-
- if resampled is None:
- num_timesteps, _, batch_size = weights.get_shape().as_list()
- resampled = tf.zeros([num_timesteps], dtype=tf.float32)
- plots = tf.py_func(_make_plots,
- [tf.nn.softmax(weights, dim=1),
- tf.to_float(resampled)], [tf.uint8])[0]
- batch_size = weights.get_shape().as_list()[-1]
- tf.summary.image(
- "weights", plots, batch_size, collections=["infrequent_summaries"])
-
-
-def summarize_weights(weights, num_timesteps, num_samples):
- # weights is [num_timesteps, num_samples, batch_size]
- weights = tf.convert_to_tensor(weights)
- mean = tf.reduce_mean(weights, axis=1, keepdims=True)
- squared_diff = tf.square(weights - mean)
- variances = tf.reduce_sum(squared_diff, axis=1) / (num_samples - 1)
- # average the variance over the batch
- variances = tf.reduce_mean(variances, axis=1)
- avg_magnitude = tf.reduce_mean(tf.abs(weights), axis=[1, 2])
- for t in xrange(num_timesteps):
- tf.summary.scalar("weights/variance_%d" % t, variances[t])
- tf.summary.scalar("weights/magnitude_%d" % t, avg_magnitude[t])
- tf.summary.histogram("weights/step_%d" % t, weights[t])
-
-
-def summarize_learning_signal(rewards, tag):
- num_resampling_events, _ = rewards.get_shape().as_list()
- mean = tf.reduce_mean(rewards, axis=1)
- avg_magnitude = tf.reduce_mean(tf.abs(rewards), axis=1)
- reward_square = tf.reduce_mean(tf.square(rewards), axis=1)
- for t in xrange(num_resampling_events):
- tf.summary.scalar("%s/mean_%d" % (tag, t), mean[t])
- tf.summary.scalar("%s/magnitude_%d" % (tag, t), avg_magnitude[t])
- tf.summary.scalar("%s/squared_%d" % (tag, t), reward_square[t])
- tf.summary.histogram("%s/step_%d" % (tag, t), rewards[t])
-
-
-def summarize_qs(model, observation, states):
- model.q.summarize_weights()
- if hasattr(model.p, "posterior") and callable(getattr(model.p, "posterior")):
- states = [tf.zeros_like(states[0])] + states[:-1]
- for t, prev_state in enumerate(states):
- p = model.p.posterior(observation, prev_state, t)
- q = model.q.q_zt(observation, prev_state, t)
- kl = tf.reduce_mean(tf.contrib.distributions.kl_divergence(p, q))
- tf.summary.scalar("kl_q/%d" % t, tf.reduce_mean(kl))
- mean_diff = q.loc - p.loc
- mean_abs_err = tf.abs(mean_diff)
- mean_rel_err = tf.abs(mean_diff / p.loc)
- tf.summary.scalar("q_mean_convergence/absolute_error_%d" % t,
- tf.reduce_mean(mean_abs_err))
- tf.summary.scalar("q_mean_convergence/relative_error_%d" % t,
- tf.reduce_mean(mean_rel_err))
- sigma_diff = tf.square(q.scale) - tf.square(p.scale)
- sigma_abs_err = tf.abs(sigma_diff)
- sigma_rel_err = tf.abs(sigma_diff / tf.square(p.scale))
- tf.summary.scalar("q_variance_convergence/absolute_error_%d" % t,
- tf.reduce_mean(sigma_abs_err))
- tf.summary.scalar("q_variance_convergence/relative_error_%d" % t,
- tf.reduce_mean(sigma_rel_err))
-
-
-def summarize_rs(model, states):
- model.r.summarize_weights()
- for t, state in enumerate(states):
- true_r = model.p.lookahead(state, t)
- r = model.r.r_xn(state, t)
- kl = tf.reduce_mean(tf.contrib.distributions.kl_divergence(true_r, r))
- tf.summary.scalar("kl_r/%d" % t, tf.reduce_mean(kl))
- mean_diff = true_r.loc - r.loc
- mean_abs_err = tf.abs(mean_diff)
- mean_rel_err = tf.abs(mean_diff / true_r.loc)
- tf.summary.scalar("r_mean_convergence/absolute_error_%d" % t,
- tf.reduce_mean(mean_abs_err))
- tf.summary.scalar("r_mean_convergence/relative_error_%d" % t,
- tf.reduce_mean(mean_rel_err))
- sigma_diff = tf.square(r.scale) - tf.square(true_r.scale)
- sigma_abs_err = tf.abs(sigma_diff)
- sigma_rel_err = tf.abs(sigma_diff / tf.square(true_r.scale))
- tf.summary.scalar("r_variance_convergence/absolute_error_%d" % t,
- tf.reduce_mean(sigma_abs_err))
- tf.summary.scalar("r_variance_convergence/relative_error_%d" % t,
- tf.reduce_mean(sigma_rel_err))
-
-
-def summarize_model(model, true_bs, observation, states, bound, summarize_r=True):
- if hasattr(model.p, "bs"):
- model_b = tf.reduce_sum(model.p.bs, axis=0)
- true_b = tf.reduce_sum(true_bs, axis=0)
- abs_err = tf.abs(model_b - true_b)
- rel_err = abs_err / true_b
- tf.summary.scalar("sum_of_bs/data_generating_process", tf.reduce_mean(true_b))
- tf.summary.scalar("sum_of_bs/model", tf.reduce_mean(model_b))
- tf.summary.scalar("sum_of_bs/absolute_error", tf.reduce_mean(abs_err))
- tf.summary.scalar("sum_of_bs/relative_error", tf.reduce_mean(rel_err))
- #summarize_qs(model, observation, states)
- #if bound == "fivo-aux" and summarize_r:
- # summarize_rs(model, states)
-
-
-def summarize_grads(grads, loss_name):
- grad_ema = tf.train.ExponentialMovingAverage(decay=0.99)
- vectorized_grads = tf.concat(
- [tf.reshape(g, [-1]) for g, _ in grads if g is not None], axis=0)
- new_second_moments = tf.square(vectorized_grads)
- new_first_moments = vectorized_grads
- maintain_grad_ema_op = grad_ema.apply([new_first_moments, new_second_moments])
- first_moments = grad_ema.average(new_first_moments)
- second_moments = grad_ema.average(new_second_moments)
- variances = second_moments - tf.square(first_moments)
- tf.summary.scalar("grad_variance/%s" % loss_name, tf.reduce_mean(variances))
- tf.summary.histogram("grad_variance/%s" % loss_name, variances)
- tf.summary.histogram("grad_mean/%s" % loss_name, first_moments)
- return maintain_grad_ema_op
diff --git a/research/fivo/experimental/train.py b/research/fivo/experimental/train.py
deleted file mode 100644
index 8abc9909b115298a30151a332d340f7b25e3cf90..0000000000000000000000000000000000000000
--- a/research/fivo/experimental/train.py
+++ /dev/null
@@ -1,637 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Main script for running fivo"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from collections import defaultdict
-
-import numpy as np
-import tensorflow as tf
-
-import bounds
-import data
-import models
-import summary_utils as summ
-
-tf.logging.set_verbosity(tf.logging.INFO)
-
-tf.app.flags.DEFINE_integer("random_seed", None,
- "A random seed for the data generating process. Same seed "
- "-> same data generating process and initialization.")
-tf.app.flags.DEFINE_enum("bound", "fivo", ["iwae", "fivo", "fivo-aux", "fivo-aux-td"],
- "The bound to optimize.")
-tf.app.flags.DEFINE_enum("model", "forward", ["forward", "long_chain"],
- "The model to use.")
-tf.app.flags.DEFINE_enum("q_type", "normal",
- ["normal", "simple_mean", "prev_state", "observation"],
- "The parameterization to use for q")
-tf.app.flags.DEFINE_enum("p_type", "unimodal", ["unimodal", "bimodal", "nonlinear"],
- "The type of prior.")
-tf.app.flags.DEFINE_boolean("train_p", True,
- "If false, do not train the model p.")
-
-tf.app.flags.DEFINE_integer("state_size", 1,
- "The dimensionality of the state space.")
-tf.app.flags.DEFINE_float("variance", 1.0,
- "The variance of the data generating process.")
-
-tf.app.flags.DEFINE_boolean("use_bs", True,
- "If False, initialize all bs to 0.")
-tf.app.flags.DEFINE_float("bimodal_prior_weight", 0.5,
- "The weight assigned to the positive mode of the prior in "
- "both the data generating process and p.")
-tf.app.flags.DEFINE_float("bimodal_prior_mean", None,
- "If supplied, sets the mean of the 2 modes of the prior to "
- "be 1 and -1 times the supplied value. This is for both the "
- "data generating process and p.")
-tf.app.flags.DEFINE_float("fixed_observation", None,
- "If supplied, fix the observation to a constant value in the"
- " data generating process only.")
-tf.app.flags.DEFINE_float("r_sigma_init", 1.,
- "Value to initialize variance of r to.")
-tf.app.flags.DEFINE_enum("observation_type",
- models.STANDARD_OBSERVATION, models.OBSERVATION_TYPES,
- "The type of observation for the long chain model.")
-tf.app.flags.DEFINE_enum("transition_type",
- models.STANDARD_TRANSITION, models.TRANSITION_TYPES,
- "The type of transition for the long chain model.")
-tf.app.flags.DEFINE_float("observation_variance", None,
- "The variance of the observation. Defaults to 'variance'")
-
-tf.app.flags.DEFINE_integer("num_timesteps", 5,
- "Number of timesteps in the sequence.")
-tf.app.flags.DEFINE_integer("num_observations", 1,
- "The number of observations.")
-tf.app.flags.DEFINE_integer("steps_per_observation", 5,
- "The number of timesteps between each observation.")
-
-tf.app.flags.DEFINE_integer("batch_size", 4,
- "The number of examples per batch.")
-tf.app.flags.DEFINE_integer("num_samples", 4,
- "The number particles to use.")
-tf.app.flags.DEFINE_integer("num_eval_samples", 512,
- "The batch size and # of particles to use for eval.")
-
-tf.app.flags.DEFINE_string("resampling", "always",
- "How to resample. Accepts 'always','never', or a "
- "comma-separated list of booleans like 'true,true,false'.")
-tf.app.flags.DEFINE_enum("resampling_method", "multinomial", ["multinomial",
- "stratified",
- "systematic",
- "relaxed-logblend",
- "relaxed-stateblend",
- "relaxed-linearblend",
- "relaxed-stateblend-st",],
- "Type of resampling method to use.")
-tf.app.flags.DEFINE_boolean("use_resampling_grads", True,
- "Whether or not to use resampling grads to optimize FIVO."
- "Disabled automatically if resampling_method=relaxed.")
-tf.app.flags.DEFINE_boolean("disable_r", False,
- "If false, r is not used for fivo-aux and is set to zeros.")
-
-tf.app.flags.DEFINE_float("learning_rate", 1e-4,
- "The learning rate to use for ADAM or SGD.")
-tf.app.flags.DEFINE_integer("decay_steps", 25000,
- "The number of steps before the learning rate is halved.")
-tf.app.flags.DEFINE_integer("max_steps", int(1e6),
- "The number of steps to run training for.")
-
-tf.app.flags.DEFINE_string("logdir", "/tmp/fivo-aux",
- "Directory for summaries and checkpoints.")
-
-tf.app.flags.DEFINE_integer("summarize_every", int(1e3),
- "The number of steps between each evaluation.")
-FLAGS = tf.app.flags.FLAGS
-
-
-def combine_grad_lists(grad_lists):
- # grads is num_losses by num_variables.
- # each list could have different variables.
- # for each variable, sum the grads across all losses.
- grads_dict = defaultdict(list)
- var_dict = {}
- for grad_list in grad_lists:
- for grad, var in grad_list:
- if grad is not None:
- grads_dict[var.name].append(grad)
- var_dict[var.name] = var
-
- final_grads = []
- for var_name, var in var_dict.iteritems():
- grads = grads_dict[var_name]
- if len(grads) > 0:
- tf.logging.info("Var %s has combined grads from %s." %
- (var_name, [g.name for g in grads]))
- grad = tf.reduce_sum(grads, axis=0)
- else:
- tf.logging.info("Var %s has no grads" % var_name)
- grad = None
- final_grads.append((grad, var))
- return final_grads
-
-
-def make_apply_grads_op(losses, global_step, learning_rate, lr_decay_steps):
- for l in losses:
- assert isinstance(l, bounds.Loss)
-
- lr = tf.train.exponential_decay(
- learning_rate, global_step, lr_decay_steps, 0.5, staircase=False)
- tf.summary.scalar("learning_rate", lr)
- opt = tf.train.AdamOptimizer(lr)
-
- ema_ops = []
- grads = []
- for loss_name, loss, loss_var_collection in losses:
- tf.logging.info("Computing grads of %s w.r.t. vars in collection %s" %
- (loss_name, loss_var_collection))
- g = opt.compute_gradients(loss,
- var_list=tf.get_collection(loss_var_collection))
- ema_ops.append(summ.summarize_grads(g, loss_name))
- grads.append(g)
-
- all_grads = combine_grad_lists(grads)
- apply_grads_op = opt.apply_gradients(all_grads, global_step=global_step)
-
- # Update the emas after applying the grads.
- with tf.control_dependencies([apply_grads_op]):
- train_op = tf.group(*ema_ops)
- return train_op
-
-
-def add_check_numerics_ops():
- check_op = []
- for op in tf.get_default_graph().get_operations():
- bad = ["logits/Log", "sample/Reshape", "log_prob/mul",
- "log_prob/SparseSoftmaxCrossEntropyWithLogits/Reshape",
- "entropy/Reshape", "entropy/LogSoftmax", "Categorical", "Mean"]
- if all([x not in op.name for x in bad]):
- for output in op.outputs:
- if output.dtype in [tf.float16, tf.float32, tf.float64]:
- if op._get_control_flow_context() is not None: # pylint: disable=protected-access
- raise ValueError("`tf.add_check_numerics_ops() is not compatible "
- "with TensorFlow control flow operations such as "
- "`tf.cond()` or `tf.while_loop()`.")
-
- message = op.name + ":" + str(output.value_index)
- with tf.control_dependencies(check_op):
- check_op = [tf.check_numerics(output, message=message)]
- return tf.group(*check_op)
-
-
-def create_long_chain_graph(bound, state_size, num_obs, steps_per_obs,
- batch_size, num_samples, num_eval_samples,
- resampling_schedule, use_resampling_grads,
- learning_rate, lr_decay_steps, dtype="float64"):
- num_timesteps = num_obs * steps_per_obs + 1
- # Make the dataset.
- dataset = data.make_long_chain_dataset(
- state_size=state_size,
- num_obs=num_obs,
- steps_per_obs=steps_per_obs,
- batch_size=batch_size,
- num_samples=num_samples,
- variance=FLAGS.variance,
- observation_variance=FLAGS.observation_variance,
- dtype=dtype,
- observation_type=FLAGS.observation_type,
- transition_type=FLAGS.transition_type,
- fixed_observation=FLAGS.fixed_observation)
- itr = dataset.make_one_shot_iterator()
- _, observations = itr.get_next()
- # Make the dataset for eval
- eval_dataset = data.make_long_chain_dataset(
- state_size=state_size,
- num_obs=num_obs,
- steps_per_obs=steps_per_obs,
- batch_size=batch_size,
- num_samples=num_eval_samples,
- variance=FLAGS.variance,
- observation_variance=FLAGS.observation_variance,
- dtype=dtype,
- observation_type=FLAGS.observation_type,
- transition_type=FLAGS.transition_type,
- fixed_observation=FLAGS.fixed_observation)
- eval_itr = eval_dataset.make_one_shot_iterator()
- _, eval_observations = eval_itr.get_next()
-
- # Make the model.
- model = models.LongChainModel.create(
- state_size,
- num_obs,
- steps_per_obs,
- observation_type=FLAGS.observation_type,
- transition_type=FLAGS.transition_type,
- variance=FLAGS.variance,
- observation_variance=FLAGS.observation_variance,
- dtype=tf.as_dtype(dtype),
- disable_r=FLAGS.disable_r)
-
- # Compute the bound and loss
- if bound == "iwae":
- (_, losses, ema_op, _, _) = bounds.iwae(
- model,
- observations,
- num_timesteps,
- num_samples=num_samples)
- (eval_log_p_hat, _, _, _, eval_log_weights) = bounds.iwae(
- model,
- eval_observations,
- num_timesteps,
- num_samples=num_eval_samples,
- summarize=False)
- eval_log_p_hat = tf.reduce_mean(eval_log_p_hat)
- elif bound == "fivo" or "fivo-aux":
- (_, losses, ema_op, _, _) = bounds.fivo(
- model,
- observations,
- num_timesteps,
- resampling_schedule=resampling_schedule,
- use_resampling_grads=use_resampling_grads,
- resampling_type=FLAGS.resampling_method,
- aux=("aux" in bound),
- num_samples=num_samples)
- (eval_log_p_hat, _, _, _, eval_log_weights) = bounds.fivo(
- model,
- eval_observations,
- num_timesteps,
- resampling_schedule=resampling_schedule,
- use_resampling_grads=False,
- resampling_type="multinomial",
- aux=("aux" in bound),
- num_samples=num_eval_samples,
- summarize=False)
- eval_log_p_hat = tf.reduce_mean(eval_log_p_hat)
-
- summ.summarize_ess(eval_log_weights, only_last_timestep=True)
-
- tf.summary.scalar("log_p_hat", eval_log_p_hat)
-
- # Compute and apply grads.
- global_step = tf.train.get_or_create_global_step()
-
- apply_grads = make_apply_grads_op(losses,
- global_step,
- learning_rate,
- lr_decay_steps)
-
- # Update the emas after applying the grads.
- with tf.control_dependencies([apply_grads]):
- train_op = tf.group(ema_op)
-
- # We can't calculate the likelihood for most of these models
- # so we just return zeros.
- eval_likelihood = tf.zeros([], dtype=dtype)
- return global_step, train_op, eval_log_p_hat, eval_likelihood
-
-
-def create_graph(bound, state_size, num_timesteps, batch_size,
- num_samples, num_eval_samples, resampling_schedule,
- use_resampling_grads, learning_rate, lr_decay_steps,
- train_p, dtype='float64'):
- if FLAGS.use_bs:
- true_bs = None
- else:
- true_bs = [np.zeros([state_size]).astype(dtype) for _ in xrange(num_timesteps)]
-
- # Make the dataset.
- true_bs, dataset = data.make_dataset(
- bs=true_bs,
- state_size=state_size,
- num_timesteps=num_timesteps,
- batch_size=batch_size,
- num_samples=num_samples,
- variance=FLAGS.variance,
- prior_type=FLAGS.p_type,
- bimodal_prior_weight=FLAGS.bimodal_prior_weight,
- bimodal_prior_mean=FLAGS.bimodal_prior_mean,
- transition_type=FLAGS.transition_type,
- fixed_observation=FLAGS.fixed_observation,
- dtype=dtype)
- itr = dataset.make_one_shot_iterator()
- _, observations = itr.get_next()
- # Make the dataset for eval
- _, eval_dataset = data.make_dataset(
- bs=true_bs,
- state_size=state_size,
- num_timesteps=num_timesteps,
- batch_size=num_eval_samples,
- num_samples=num_eval_samples,
- variance=FLAGS.variance,
- prior_type=FLAGS.p_type,
- bimodal_prior_weight=FLAGS.bimodal_prior_weight,
- bimodal_prior_mean=FLAGS.bimodal_prior_mean,
- transition_type=FLAGS.transition_type,
- fixed_observation=FLAGS.fixed_observation,
- dtype=dtype)
- eval_itr = eval_dataset.make_one_shot_iterator()
- _, eval_observations = eval_itr.get_next()
-
- # Make the model.
- if bound == "fivo-aux-td":
- model = models.TDModel.create(
- state_size,
- num_timesteps,
- variance=FLAGS.variance,
- train_p=train_p,
- p_type=FLAGS.p_type,
- q_type=FLAGS.q_type,
- mixing_coeff=FLAGS.bimodal_prior_weight,
- prior_mode_mean=FLAGS.bimodal_prior_mean,
- observation_variance=FLAGS.observation_variance,
- transition_type=FLAGS.transition_type,
- use_bs=FLAGS.use_bs,
- dtype=tf.as_dtype(dtype),
- random_seed=FLAGS.random_seed)
- else:
- model = models.Model.create(
- state_size,
- num_timesteps,
- variance=FLAGS.variance,
- train_p=train_p,
- p_type=FLAGS.p_type,
- q_type=FLAGS.q_type,
- mixing_coeff=FLAGS.bimodal_prior_weight,
- prior_mode_mean=FLAGS.bimodal_prior_mean,
- observation_variance=FLAGS.observation_variance,
- transition_type=FLAGS.transition_type,
- use_bs=FLAGS.use_bs,
- r_sigma_init=FLAGS.r_sigma_init,
- dtype=tf.as_dtype(dtype),
- random_seed=FLAGS.random_seed)
-
- # Compute the bound and loss
- if bound == "iwae":
- (_, losses, ema_op, _, _) = bounds.iwae(
- model,
- observations,
- num_timesteps,
- num_samples=num_samples)
- (eval_log_p_hat, _, _, eval_states, eval_log_weights) = bounds.iwae(
- model,
- eval_observations,
- num_timesteps,
- num_samples=num_eval_samples,
- summarize=True)
-
- eval_log_p_hat = tf.reduce_mean(eval_log_p_hat)
-
- elif "fivo" in bound:
- if bound == "fivo-aux-td":
- (_, losses, ema_op, _, _) = bounds.fivo_aux_td(
- model,
- observations,
- num_timesteps,
- resampling_schedule=resampling_schedule,
- num_samples=num_samples)
- (eval_log_p_hat, _, _, eval_states, eval_log_weights) = bounds.fivo_aux_td(
- model,
- eval_observations,
- num_timesteps,
- resampling_schedule=resampling_schedule,
- num_samples=num_eval_samples,
- summarize=True)
- else:
- (_, losses, ema_op, _, _) = bounds.fivo(
- model,
- observations,
- num_timesteps,
- resampling_schedule=resampling_schedule,
- use_resampling_grads=use_resampling_grads,
- resampling_type=FLAGS.resampling_method,
- aux=("aux" in bound),
- num_samples=num_samples)
- (eval_log_p_hat, _, _, eval_states, eval_log_weights) = bounds.fivo(
- model,
- eval_observations,
- num_timesteps,
- resampling_schedule=resampling_schedule,
- use_resampling_grads=False,
- resampling_type="multinomial",
- aux=("aux" in bound),
- num_samples=num_eval_samples,
- summarize=True)
- eval_log_p_hat = tf.reduce_mean(eval_log_p_hat)
-
- summ.summarize_ess(eval_log_weights, only_last_timestep=True)
-
- # if FLAGS.p_type == "bimodal":
- # # create the observations that showcase the model.
- # mode_odds_ratio = tf.convert_to_tensor([1., 3., 1./3., 512., 1./512.],
- # dtype=tf.float64)
- # mode_odds_ratio = tf.expand_dims(mode_odds_ratio, 1)
- # k = ((num_timesteps+1) * FLAGS.variance) / (2*FLAGS.bimodal_prior_mean)
- # explain_obs = tf.reduce_sum(model.p.bs) + tf.log(mode_odds_ratio) * k
- # explain_obs = tf.tile(explain_obs, [num_eval_samples, 1])
- # # run the model on the explainable observations
- # if bound == "iwae":
- # (_, _, _, explain_states, explain_log_weights) = bounds.iwae(
- # model,
- # explain_obs,
- # num_timesteps,
- # num_samples=num_eval_samples)
- # elif bound == "fivo" or "fivo-aux":
- # (_, _, _, explain_states, explain_log_weights) = bounds.fivo(
- # model,
- # explain_obs,
- # num_timesteps,
- # resampling_schedule=resampling_schedule,
- # use_resampling_grads=False,
- # resampling_type="multinomial",
- # aux=("aux" in bound),
- # num_samples=num_eval_samples)
- # summ.summarize_particles(explain_states,
- # explain_log_weights,
- # explain_obs,
- # model)
-
- # Calculate the true likelihood.
- if hasattr(model.p, 'likelihood') and callable(getattr(model.p, 'likelihood')):
- eval_likelihood = model.p.likelihood(eval_observations)/ FLAGS.num_timesteps
- else:
- eval_likelihood = tf.zeros_like(eval_log_p_hat)
-
- tf.summary.scalar("log_p_hat", eval_log_p_hat)
- tf.summary.scalar("likelihood", eval_likelihood)
- tf.summary.scalar("bound_gap", eval_likelihood - eval_log_p_hat)
- summ.summarize_model(model, true_bs, eval_observations, eval_states, bound,
- summarize_r=not bound == "fivo-aux-td")
-
- # Compute and apply grads.
- global_step = tf.train.get_or_create_global_step()
-
- apply_grads = make_apply_grads_op(losses,
- global_step,
- learning_rate,
- lr_decay_steps)
-
- # Update the emas after applying the grads.
- with tf.control_dependencies([apply_grads]):
- train_op = tf.group(ema_op)
- #train_op = tf.group(ema_op, add_check_numerics_ops())
-
- return global_step, train_op, eval_log_p_hat, eval_likelihood
-
-
-def parse_resampling_schedule(schedule, num_timesteps):
- schedule = schedule.strip().lower()
- if schedule == "always":
- return [True] * (num_timesteps - 1) + [False]
- elif schedule == "never":
- return [False] * num_timesteps
- elif "every" in schedule:
- n = int(schedule.split("_")[1])
- return [(i+1) % n == 0 for i in xrange(num_timesteps)]
- else:
- sched = [x.strip() == "true" for x in schedule.split(",")]
- assert len(
- sched
- ) == num_timesteps, "Wrong number of timesteps in resampling schedule."
- return sched
-
-
-def create_log_hook(step, eval_log_p_hat, eval_likelihood):
- def summ_formatter(d):
- return ("Step {step}, log p_hat: {log_p_hat:.5f} likelihood: {likelihood:.5f}".format(**d))
- hook = tf.train.LoggingTensorHook(
- {
- "step": step,
- "log_p_hat": eval_log_p_hat,
- "likelihood": eval_likelihood,
- },
- every_n_iter=FLAGS.summarize_every,
- formatter=summ_formatter)
- return hook
-
-
-def create_infrequent_summary_hook():
- infrequent_summary_hook = tf.train.SummarySaverHook(
- save_steps=10000,
- output_dir=FLAGS.logdir,
- summary_op=tf.summary.merge_all(key="infrequent_summaries")
- )
- return infrequent_summary_hook
-
-
-def main(unused_argv):
- if FLAGS.model == "long_chain":
- resampling_schedule = parse_resampling_schedule(FLAGS.resampling,
- FLAGS.num_timesteps + 1)
- else:
- resampling_schedule = parse_resampling_schedule(FLAGS.resampling,
- FLAGS.num_timesteps)
- if FLAGS.random_seed is None:
- seed = np.random.randint(0, high=10000)
- else:
- seed = FLAGS.random_seed
- tf.logging.info("Using random seed %d", seed)
-
- if FLAGS.model == "long_chain":
- assert FLAGS.q_type == "normal", "Q type %s not supported for long chain models" % FLAGS.q_type
- assert FLAGS.p_type == "unimodal", "Bimodal priors are not supported for long chain models"
- assert not FLAGS.use_bs, "Bs are not supported with long chain models"
- assert FLAGS.num_timesteps == FLAGS.num_observations * FLAGS.steps_per_observation, "Num timesteps does not match."
- assert FLAGS.bound != "fivo-aux-td", "TD Training is not compatible with long chain models."
-
- if FLAGS.model == "forward":
- if "nonlinear" not in FLAGS.p_type:
- assert FLAGS.transition_type == models.STANDARD_TRANSITION, "Non-standard transitions not supported by the forward model."
- assert FLAGS.observation_type == models.STANDARD_OBSERVATION, "Non-standard observations not supported by the forward model."
- assert FLAGS.observation_variance is None, "Forward model does not support observation variance."
- assert FLAGS.num_observations == 1, "Forward model only supports 1 observation."
-
- if "relaxed" in FLAGS.resampling_method:
- FLAGS.use_resampling_grads = False
- assert FLAGS.bound != "fivo-aux-td", "TD Training is not compatible with relaxed resampling."
-
- if FLAGS.observation_variance is None:
- FLAGS.observation_variance = FLAGS.variance
-
- if FLAGS.p_type == "bimodal":
- assert FLAGS.bimodal_prior_mean is not None, "Must specify prior mean if using bimodal p."
-
- if FLAGS.p_type == "nonlinear" or FLAGS.p_type == "nonlinear-cauchy":
- assert not FLAGS.use_bs, "Using bs is not compatible with the nonlinear model."
-
- g = tf.Graph()
- with g.as_default():
- # Set the seeds.
- tf.set_random_seed(seed)
- np.random.seed(seed)
- if FLAGS.model == "long_chain":
- (global_step, train_op, eval_log_p_hat,
- eval_likelihood) = create_long_chain_graph(
- FLAGS.bound,
- FLAGS.state_size,
- FLAGS.num_observations,
- FLAGS.steps_per_observation,
- FLAGS.batch_size,
- FLAGS.num_samples,
- FLAGS.num_eval_samples,
- resampling_schedule,
- FLAGS.use_resampling_grads,
- FLAGS.learning_rate,
- FLAGS.decay_steps)
- else:
- (global_step, train_op,
- eval_log_p_hat, eval_likelihood) = create_graph(
- FLAGS.bound,
- FLAGS.state_size,
- FLAGS.num_timesteps,
- FLAGS.batch_size,
- FLAGS.num_samples,
- FLAGS.num_eval_samples,
- resampling_schedule,
- FLAGS.use_resampling_grads,
- FLAGS.learning_rate,
- FLAGS.decay_steps,
- FLAGS.train_p)
-
- log_hooks = [create_log_hook(global_step, eval_log_p_hat, eval_likelihood)]
- if len(tf.get_collection("infrequent_summaries")) > 0:
- log_hooks.append(create_infrequent_summary_hook())
-
- tf.logging.info("trainable variables:")
- tf.logging.info([v.name for v in tf.trainable_variables()])
- tf.logging.info("p vars:")
- tf.logging.info([v.name for v in tf.get_collection("P_VARS")])
- tf.logging.info("q vars:")
- tf.logging.info([v.name for v in tf.get_collection("Q_VARS")])
- tf.logging.info("r vars:")
- tf.logging.info([v.name for v in tf.get_collection("R_VARS")])
- tf.logging.info("r tilde vars:")
- tf.logging.info([v.name for v in tf.get_collection("R_TILDE_VARS")])
-
- with tf.train.MonitoredTrainingSession(
- master="",
- is_chief=True,
- hooks=log_hooks,
- checkpoint_dir=FLAGS.logdir,
- save_checkpoint_secs=120,
- save_summaries_steps=FLAGS.summarize_every,
- log_step_count_steps=FLAGS.summarize_every) as sess:
- cur_step = -1
- while True:
- if sess.should_stop() or cur_step > FLAGS.max_steps:
- break
- # run a step
- _, cur_step = sess.run([train_op, global_step])
-
-
-if __name__ == "__main__":
- tf.app.run(main)
diff --git a/research/fivo/fivo/__init__.py b/research/fivo/fivo/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/fivo/fivo/bounds.py b/research/fivo/fivo/bounds.py
deleted file mode 100644
index 088519033dd80669e99015b8e465888bd94a4cb1..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/bounds.py
+++ /dev/null
@@ -1,317 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Implementation of objectives for training stochastic latent variable models.
-
-Contains implementations of the Importance Weighted Autoencoder objective (IWAE)
-and the Filtering Variational objective (FIVO).
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import functools
-import tensorflow as tf
-
-from fivo import nested_utils as nested
-from fivo import smc
-
-
-def iwae(model,
- observations,
- seq_lengths,
- num_samples=1,
- parallel_iterations=30,
- swap_memory=True):
- """Computes the IWAE lower bound on the log marginal probability.
-
- This method accepts a stochastic latent variable model and some observations
- and computes a stochastic lower bound on the log marginal probability of the
- observations. The IWAE estimator is defined by averaging multiple importance
- weights. For more details see "Importance Weighted Autoencoders" by Burda
- et al. https://arxiv.org/abs/1509.00519.
-
- When num_samples = 1, this bound becomes the evidence lower bound (ELBO).
-
- Args:
- model: A subclass of ELBOTrainableSequenceModel that implements one
- timestep of the model. See models/vrnn.py for an example.
- observations: The inputs to the model. A potentially nested list or tuple of
- Tensors each of shape [max_seq_len, batch_size, ...]. The Tensors must
- have a rank at least two and have matching shapes in the first two
- dimensions, which represent time and the batch respectively. The model
- will be provided with the observations before computing the bound.
- seq_lengths: A [batch_size] Tensor of ints encoding the length of each
- sequence in the batch (sequences can be padded to a common length).
- num_samples: The number of samples to use.
- parallel_iterations: The number of parallel iterations to use for the
- internal while loop.
- swap_memory: Whether GPU-CPU memory swapping should be enabled for the
- internal while loop.
-
- Returns:
- log_p_hat: A Tensor of shape [batch_size] containing IWAE's estimate of the
- log marginal probability of the observations.
- log_weights: A Tensor of shape [max_seq_len, batch_size, num_samples]
- containing the log weights at each timestep. Will not be valid for
- timesteps past the end of a sequence.
- """
- log_p_hat, log_weights, _, final_state = fivo(
- model,
- observations,
- seq_lengths,
- num_samples=num_samples,
- resampling_criterion=smc.never_resample_criterion,
- parallel_iterations=parallel_iterations,
- swap_memory=swap_memory)
- return log_p_hat, log_weights, final_state
-
-
-def fivo(model,
- observations,
- seq_lengths,
- num_samples=1,
- resampling_criterion=smc.ess_criterion,
- resampling_type='multinomial',
- relaxed_resampling_temperature=0.5,
- parallel_iterations=30,
- swap_memory=True,
- random_seed=None):
- """Computes the FIVO lower bound on the log marginal probability.
-
- This method accepts a stochastic latent variable model and some observations
- and computes a stochastic lower bound on the log marginal probability of the
- observations. The lower bound is defined by a particle filter's unbiased
- estimate of the marginal probability of the observations. For more details see
- "Filtering Variational Objectives" by Maddison et al.
- https://arxiv.org/abs/1705.09279.
-
- When the resampling criterion is "never resample", this bound becomes IWAE.
-
- Args:
- model: A subclass of ELBOTrainableSequenceModel that implements one
- timestep of the model. See models/vrnn.py for an example.
- observations: The inputs to the model. A potentially nested list or tuple of
- Tensors each of shape [max_seq_len, batch_size, ...]. The Tensors must
- have a rank at least two and have matching shapes in the first two
- dimensions, which represent time and the batch respectively. The model
- will be provided with the observations before computing the bound.
- seq_lengths: A [batch_size] Tensor of ints encoding the length of each
- sequence in the batch (sequences can be padded to a common length).
- num_samples: The number of particles to use in each particle filter.
- resampling_criterion: The resampling criterion to use for this particle
- filter. Must accept the number of samples, the current log weights,
- and the current timestep and return a boolean Tensor of shape [batch_size]
- indicating whether each particle filter should resample. See
- ess_criterion and related functions for examples. When
- resampling_criterion is never_resample_criterion, resampling_fn is ignored
- and never called.
- resampling_type: The type of resampling, one of "multinomial" or "relaxed".
- relaxed_resampling_temperature: A positive temperature only used for relaxed
- resampling.
- parallel_iterations: The number of parallel iterations to use for the
- internal while loop. Note that values greater than 1 can introduce
- non-determinism even when random_seed is provided.
- swap_memory: Whether GPU-CPU memory swapping should be enabled for the
- internal while loop.
- random_seed: The random seed to pass to the resampling operations in
- the particle filter. Mainly useful for testing.
-
- Returns:
- log_p_hat: A Tensor of shape [batch_size] containing FIVO's estimate of the
- log marginal probability of the observations.
- log_weights: A Tensor of shape [max_seq_len, batch_size, num_samples]
- containing the log weights at each timestep of the particle filter. Note
- that on timesteps when a resampling operation is performed the log weights
- are reset to 0. Will not be valid for timesteps past the end of a
- sequence.
- resampled: A Tensor of shape [max_seq_len, batch_size] indicating when the
- particle filters resampled. Will be 1.0 on timesteps when resampling
- occurred and 0.0 on timesteps when it did not.
- """
- # batch_size is the number of particle filters running in parallel.
- batch_size = tf.shape(seq_lengths)[0]
-
- # Each sequence in the batch will be the input data for a different
- # particle filter. The batch will be laid out as:
- # particle 1 of particle filter 1
- # particle 1 of particle filter 2
- # ...
- # particle 1 of particle filter batch_size
- # particle 2 of particle filter 1
- # ...
- # particle num_samples of particle filter batch_size
- observations = nested.tile_tensors(observations, [1, num_samples])
- tiled_seq_lengths = tf.tile(seq_lengths, [num_samples])
- model.set_observations(observations, tiled_seq_lengths)
-
- if resampling_type == 'multinomial':
- resampling_fn = smc.multinomial_resampling
- elif resampling_type == 'relaxed':
- resampling_fn = functools.partial(
- smc.relaxed_resampling, temperature=relaxed_resampling_temperature)
- resampling_fn = functools.partial(resampling_fn, random_seed=random_seed)
-
- def transition_fn(prev_state, t):
- if prev_state is None:
- return model.zero_state(batch_size * num_samples, tf.float32)
- return model.propose_and_weight(prev_state, t)
-
- log_p_hat, log_weights, resampled, final_state, _ = smc.smc(
- transition_fn,
- seq_lengths,
- num_particles=num_samples,
- resampling_criterion=resampling_criterion,
- resampling_fn=resampling_fn,
- parallel_iterations=parallel_iterations,
- swap_memory=swap_memory)
-
- return log_p_hat, log_weights, resampled, final_state
-
-def fivo_aux_td(
- model,
- observations,
- seq_lengths,
- num_samples=1,
- resampling_criterion=smc.ess_criterion,
- resampling_type='multinomial',
- relaxed_resampling_temperature=0.5,
- parallel_iterations=30,
- swap_memory=True,
- random_seed=None):
- """Experimental."""
- # batch_size is the number of particle filters running in parallel.
- batch_size = tf.shape(seq_lengths)[0]
- max_seq_len = tf.reduce_max(seq_lengths)
-
- # Each sequence in the batch will be the input data for a different
- # particle filter. The batch will be laid out as:
- # particle 1 of particle filter 1
- # particle 1 of particle filter 2
- # ...
- # particle 1 of particle filter batch_size
- # particle 2 of particle filter 1
- # ...
- # particle num_samples of particle filter batch_size
- observations = nested.tile_tensors(observations, [1, num_samples])
- tiled_seq_lengths = tf.tile(seq_lengths, [num_samples])
- model.set_observations(observations, tiled_seq_lengths)
-
- if resampling_type == 'multinomial':
- resampling_fn = smc.multinomial_resampling
- elif resampling_type == 'relaxed':
- resampling_fn = functools.partial(
- smc.relaxed_resampling, temperature=relaxed_resampling_temperature)
- resampling_fn = functools.partial(resampling_fn, random_seed=random_seed)
-
- def transition_fn(prev_state, t):
- if prev_state is None:
- model_init_state = model.zero_state(batch_size * num_samples, tf.float32)
- return (tf.zeros([num_samples*batch_size], dtype=tf.float32),
- (tf.zeros([num_samples*batch_size, model.latent_size], dtype=tf.float32),
- tf.zeros([num_samples*batch_size, model.latent_size], dtype=tf.float32)),
- model_init_state)
-
- prev_log_r, prev_log_r_tilde, prev_model_state = prev_state
- (new_model_state, zt, log_q_zt, log_p_zt,
- log_p_x_given_z, log_r_tilde, p_ztplus1) = model(prev_model_state, t)
- r_tilde_mu, r_tilde_sigma_sq = log_r_tilde
- # Compute the weight without r.
- log_weight = log_p_zt + log_p_x_given_z - log_q_zt
- # Compute log_r and log_r_tilde.
- p_mu = tf.stop_gradient(p_ztplus1.mean())
- p_sigma_sq = tf.stop_gradient(p_ztplus1.variance())
- log_r = (tf.log(r_tilde_sigma_sq) -
- tf.log(r_tilde_sigma_sq + p_sigma_sq) -
- tf.square(r_tilde_mu - p_mu)/(r_tilde_sigma_sq + p_sigma_sq))
- # log_r is [num_samples*batch_size, latent_size]. We sum it along the last
- # dimension to compute log r.
- log_r = 0.5*tf.reduce_sum(log_r, axis=-1)
- # Compute prev log r tilde
- prev_r_tilde_mu, prev_r_tilde_sigma_sq = prev_log_r_tilde
- prev_log_r_tilde = -0.5*tf.reduce_sum(
- tf.square(tf.stop_gradient(zt) - prev_r_tilde_mu)/prev_r_tilde_sigma_sq, axis=-1)
- # If the sequence is on the last timestep, log_r and log_r_tilde are just zeros.
- last_timestep = t >= (tiled_seq_lengths - 1)
- log_r = tf.where(last_timestep,
- tf.zeros_like(log_r),
- log_r)
- prev_log_r_tilde = tf.where(last_timestep,
- tf.zeros_like(prev_log_r_tilde),
- prev_log_r_tilde)
- log_weight += tf.stop_gradient(log_r - prev_log_r)
- new_state = (log_r, log_r_tilde, new_model_state)
- loop_fn_args = (log_r, prev_log_r_tilde, log_p_x_given_z, log_r - prev_log_r)
- return log_weight, new_state, loop_fn_args
-
- def loop_fn(loop_state, loop_args, unused_model_state, log_weights, resampled, mask, t):
- if loop_state is None:
- return (tf.zeros([batch_size], dtype=tf.float32),
- tf.zeros([batch_size], dtype=tf.float32),
- tf.zeros([num_samples, batch_size], dtype=tf.float32))
- log_p_hat_acc, bellman_loss_acc, log_r_diff_acc = loop_state
- log_r, prev_log_r_tilde, log_p_x_given_z, log_r_diff = loop_args
- # Compute the log_p_hat update
- log_p_hat_update = tf.reduce_logsumexp(
- log_weights, axis=0) - tf.log(tf.to_float(num_samples))
- # If it is the last timestep, we always add the update.
- log_p_hat_acc += tf.cond(t >= max_seq_len-1,
- lambda: log_p_hat_update,
- lambda: log_p_hat_update * resampled)
- # Compute the Bellman update.
- log_r = tf.reshape(log_r, [num_samples, batch_size])
- prev_log_r_tilde = tf.reshape(prev_log_r_tilde, [num_samples, batch_size])
- log_p_x_given_z = tf.reshape(log_p_x_given_z, [num_samples, batch_size])
- mask = tf.reshape(mask, [num_samples, batch_size])
- # On the first timestep there is no bellman error because there is no
- # prev_log_r_tilde.
- mask = tf.cond(tf.equal(t, 0),
- lambda: tf.zeros_like(mask),
- lambda: mask)
- # On the first timestep also fix up prev_log_r_tilde, which will be -inf.
- prev_log_r_tilde = tf.where(
- tf.is_inf(prev_log_r_tilde),
- tf.zeros_like(prev_log_r_tilde),
- prev_log_r_tilde)
- # log_lambda is [num_samples, batch_size]
- log_lambda = tf.reduce_mean(prev_log_r_tilde - log_p_x_given_z - log_r,
- axis=0, keepdims=True)
- bellman_error = mask * tf.square(
- prev_log_r_tilde -
- tf.stop_gradient(log_lambda + log_p_x_given_z + log_r)
- )
- bellman_loss_acc += tf.reduce_mean(bellman_error, axis=0)
- # Compute the log_r_diff update
- log_r_diff_acc += mask * tf.reshape(log_r_diff, [num_samples, batch_size])
- return (log_p_hat_acc, bellman_loss_acc, log_r_diff_acc)
-
- log_weights, resampled, accs = smc.smc(
- transition_fn,
- seq_lengths,
- num_particles=num_samples,
- resampling_criterion=resampling_criterion,
- resampling_fn=resampling_fn,
- loop_fn=loop_fn,
- parallel_iterations=parallel_iterations,
- swap_memory=swap_memory)
-
- log_p_hat, bellman_loss, log_r_diff = accs
- loss_per_seq = [- log_p_hat, bellman_loss]
- tf.summary.scalar("bellman_loss",
- tf.reduce_mean(bellman_loss / tf.to_float(seq_lengths)))
- tf.summary.scalar("log_r_diff",
- tf.reduce_mean(tf.reduce_mean(log_r_diff, axis=0) / tf.to_float(seq_lengths)))
- return loss_per_seq, log_p_hat, log_weights, resampled
diff --git a/research/fivo/fivo/bounds_test.py b/research/fivo/fivo/bounds_test.py
deleted file mode 100644
index c970f74f4cec36a855c54bbe6cdf8d76c3f86599..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/bounds_test.py
+++ /dev/null
@@ -1,183 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests for fivo.bounds"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import tensorflow as tf
-
-from fivo.test_utils import create_vrnn
-from fivo import bounds
-
-
-class BoundsTest(tf.test.TestCase):
-
- def test_elbo(self):
- """A golden-value test for the ELBO (the IWAE bound with num_samples=1)."""
- tf.set_random_seed(1234)
- with self.test_session() as sess:
- model, inputs, targets, lengths = create_vrnn(random_seed=1234)
- outs = bounds.iwae(model, (inputs, targets), lengths, num_samples=1,
- parallel_iterations=1)
- sess.run(tf.global_variables_initializer())
- log_p_hat, _, _ = sess.run(outs)
- self.assertAllClose([-21.615765, -13.614225], log_p_hat)
-
- def test_iwae(self):
- """A golden-value test for the IWAE bound."""
- tf.set_random_seed(1234)
- with self.test_session() as sess:
- model, inputs, targets, lengths = create_vrnn(random_seed=1234)
- outs = bounds.iwae(model, (inputs, targets), lengths, num_samples=4,
- parallel_iterations=1)
- sess.run(tf.global_variables_initializer())
- log_p_hat, weights, _ = sess.run(outs)
- self.assertAllClose([-23.301426, -13.64028], log_p_hat)
- weights_gt = np.array(
- [[[-3.66708851, -2.07074022, -4.91751671, -5.03293562],
- [-2.99690723, -3.17782736, -4.50084877, -3.48536515]],
- [[-6.2539978, -4.37615728, -7.43738699, -7.85044909],
- [-8.27518654, -6.71545124, -8.96198845, -7.05567837]],
- [[-9.19093227, -8.01637268, -11.64603615, -10.51128292],
- [-12.34527206, -11.54284477, -11.8667469, -9.69417381]],
- [[-12.20609856, -10.47217369, -13.66270638, -13.46115875],
- [-17.17656708, -16.25190353, -15.28658581, -12.33067703]],
- [[-16.14766312, -15.57472229, -17.47755432, -17.98189926],
- [-17.17656708, -16.25190353, -15.28658581, -12.33067703]],
- [[-20.07182884, -18.43191147, -20.1606636, -21.45263863],
- [-17.17656708, -16.25190353, -15.28658581, -12.33067703]],
- [[-24.10270691, -22.20865822, -24.14675522, -25.27248383],
- [-17.17656708, -16.25190353, -15.28658581, -12.33067703]]])
- self.assertAllClose(weights_gt, weights)
-
- def test_fivo(self):
- """A golden-value test for the FIVO bound."""
- tf.set_random_seed(1234)
- with self.test_session() as sess:
- model, inputs, targets, lengths = create_vrnn(random_seed=1234)
- outs = bounds.fivo(model, (inputs, targets), lengths, num_samples=4,
- random_seed=1234, parallel_iterations=1)
- sess.run(tf.global_variables_initializer())
- log_p_hat, weights, resampled, _ = sess.run(outs)
- self.assertAllClose([-22.98902512, -14.21689224], log_p_hat)
- weights_gt = np.array(
- [[[-3.66708851, -2.07074022, -4.91751671, -5.03293562],
- [-2.99690723, -3.17782736, -4.50084877, -3.48536515]],
- [[-2.67100811, -2.30541706, -2.34178066, -2.81751347],
- [-8.27518654, -6.71545124, -8.96198845, -7.05567837]],
- [[-5.65190411, -5.94563246, -6.55041981, -5.4783473],
- [-12.34527206, -11.54284477, -11.8667469, -9.69417381]],
- [[-8.71947861, -8.40143299, -8.54593086, -8.42822266],
- [-4.28782988, -4.50591278, -3.40847206, -2.63650274]],
- [[-12.7003831, -13.5039815, -12.3569726, -12.9489622],
- [-4.28782988, -4.50591278, -3.40847206, -2.63650274]],
- [[-16.4520301, -16.3611698, -15.0314846, -16.4197006],
- [-4.28782988, -4.50591278, -3.40847206, -2.63650274]],
- [[-20.7010765, -20.1379165, -19.0020351, -20.2395458],
- [-4.28782988, -4.50591278, -3.40847206, -2.63650274]]])
- self.assertAllClose(weights_gt, weights)
- resampled_gt = np.array(
- [[1., 0.],
- [0., 0.],
- [0., 1.],
- [0., 0.],
- [0., 0.],
- [0., 0.],
- [0., 0.]])
- self.assertAllClose(resampled_gt, resampled)
-
- def test_fivo_relaxed(self):
- """A golden-value test for the FIVO bound with relaxed sampling."""
- tf.set_random_seed(1234)
- with self.test_session() as sess:
- model, inputs, targets, lengths = create_vrnn(random_seed=1234)
- outs = bounds.fivo(model, (inputs, targets), lengths, num_samples=4,
- random_seed=1234, parallel_iterations=1,
- resampling_type="relaxed")
- sess.run(tf.global_variables_initializer())
- log_p_hat, weights, resampled, _ = sess.run(outs)
- self.assertAllClose([-22.942394, -14.273882], log_p_hat)
- weights_gt = np.array(
- [[[-3.66708851, -2.07074118, -4.91751575, -5.03293514],
- [-2.99690628, -3.17782831, -4.50084877, -3.48536515]],
- [[-2.84939098, -2.30087185, -2.35649204, -2.48417377],
- [-8.27518654, -6.71545172, -8.96199131, -7.05567837]],
- [[-5.92327023, -5.9433074, -6.5826683, -5.04259014],
- [-12.34527206, -11.54284668, -11.86675072, -9.69417477]],
- [[-8.95323944, -8.40061855, -8.52760506, -7.99130583],
- [-4.58102798, -4.56017351, -3.46283388, -2.65550804]],
- [[-12.87836456, -13.49628639, -12.31680107, -12.74228859],
- [-4.58102798, -4.56017351, -3.46283388, -2.65550804]],
- [[-16.78347397, -16.35150909, -14.98797417, -16.35162735],
- [-4.58102798, -4.56017351, -3.46283388, -2.65550804]],
- [[-20.81165886, -20.1307621, -18.92229652, -20.17458153],
- [-4.58102798, -4.56017351, -3.46283388, -2.65550804]]])
- self.assertAllClose(weights_gt, weights)
- resampled_gt = np.array(
- [[1., 0.],
- [0., 0.],
- [0., 1.],
- [0., 0.],
- [0., 0.],
- [0., 0.],
- [0., 0.]])
- self.assertAllClose(resampled_gt, resampled)
-
- def test_fivo_aux_relaxed(self):
- """A golden-value test for the FIVO-AUX bound with relaxed sampling."""
- tf.set_random_seed(1234)
- with self.test_session() as sess:
- model, inputs, targets, lengths = create_vrnn(random_seed=1234,
- use_tilt=True)
- outs = bounds.fivo(model, (inputs, targets), lengths, num_samples=4,
- random_seed=1234, parallel_iterations=1,
- resampling_type="relaxed")
- sess.run(tf.global_variables_initializer())
- log_p_hat, weights, resampled, _ = sess.run(outs)
- self.assertAllClose([-23.1395, -14.271059], log_p_hat)
- weights_gt = np.array(
- [[[-5.19826221, -3.55476403, -5.98663855, -6.08058834],
- [-6.31685925, -5.70243931, -7.07638931, -6.18138981]],
- [[-3.97986865, -3.58831525, -3.85753584, -3.5010016],
- [-11.38203049, -8.66213989, -11.23646641, -10.02024746]],
- [[-6.62269831, -6.36680222, -6.78096485, -5.80072498],
- [-3.55419445, -8.11326408, -3.48766923, -3.08593249]],
- [[-10.56472301, -10.16084099, -9.96741676, -8.5270071],
- [-6.04880285, -7.80853653, -4.72652149, -3.49711013]],
- [[-13.36585426, -16.08720398, -13.33416367, -13.1017189],
- [-0., -0., -0., -0.]],
- [[-17.54233551, -17.35167503, -16.79163361, -16.51471138],
- [0., -0., -0., -0.]],
- [[-19.74024963, -18.69452858, -17.76246452, -18.76182365],
- [0., -0., -0., -0.]]])
- self.assertAllClose(weights_gt, weights)
- resampled_gt = np.array([[1., 0.],
- [0., 1.],
- [0., 0.],
- [0., 1.],
- [0., 0.],
- [0., 0.],
- [0., 0.]])
- self.assertAllClose(resampled_gt, resampled)
-
-
-if __name__ == "__main__":
- np.set_printoptions(threshold=np.nan) # Used to easily see the gold values.
- # Use print(repr(numpy_array)) to print the values.
- tf.test.main()
diff --git a/research/fivo/fivo/data/__init__.py b/research/fivo/fivo/data/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/fivo/fivo/data/calculate_pianoroll_mean.py b/research/fivo/fivo/data/calculate_pianoroll_mean.py
deleted file mode 100644
index 93f712bd328f61a83faffc55ad2cf6ca33b47fb7..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/data/calculate_pianoroll_mean.py
+++ /dev/null
@@ -1,65 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Script to calculate the mean of a pianoroll dataset.
-
-Given a pianoroll pickle file, this script loads the dataset and
-calculates the mean of the training set. Then it updates the pickle file
-so that the key "train_mean" points to the mean vector.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import pickle
-import numpy as np
-
-import tensorflow as tf
-
-
-from datasets import sparse_pianoroll_to_dense
-
-tf.app.flags.DEFINE_string('in_file', None,
- 'Filename of the pickled pianoroll dataset to load.')
-tf.app.flags.DEFINE_string('out_file', None,
- 'Name of the output pickle file. Defaults to in_file, '
- 'updating the input pickle file.')
-tf.app.flags.mark_flag_as_required('in_file')
-
-FLAGS = tf.app.flags.FLAGS
-
-MIN_NOTE = 21
-MAX_NOTE = 108
-NUM_NOTES = MAX_NOTE - MIN_NOTE + 1
-
-
-def main(unused_argv):
- if FLAGS.out_file is None:
- FLAGS.out_file = FLAGS.in_file
- with tf.gfile.Open(FLAGS.in_file, 'r') as f:
- pianorolls = pickle.load(f)
- dense_pianorolls = [sparse_pianoroll_to_dense(p, MIN_NOTE, NUM_NOTES)[0]
- for p in pianorolls['train']]
- # Concatenate all elements along the time axis.
- concatenated = np.concatenate(dense_pianorolls, axis=0)
- mean = np.mean(concatenated, axis=0)
- pianorolls['train_mean'] = mean
- # Write out the whole pickle file, including the train mean.
- pickle.dump(pianorolls, open(FLAGS.out_file, 'wb'))
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/fivo/fivo/data/create_timit_dataset.py b/research/fivo/fivo/data/create_timit_dataset.py
deleted file mode 100644
index ea1cd3b10cb0812c2d6aad51491924ecfe8eec37..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/data/create_timit_dataset.py
+++ /dev/null
@@ -1,180 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Preprocesses TIMIT from raw wavfiles to create a set of TFRecords.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import glob
-import os
-import random
-import re
-
-import numpy as np
-import tensorflow as tf
-
-tf.app.flags.DEFINE_string("raw_timit_dir", None,
- "Directory containing TIMIT files.")
-tf.app.flags.DEFINE_string("out_dir", None,
- "Output directory for TFRecord files.")
-tf.app.flags.DEFINE_float("valid_frac", 0.05,
- "Fraction of train set to use as valid set. "
- "Must be between 0.0 and 1.0.")
-
-tf.app.flags.mark_flag_as_required("raw_timit_dir")
-tf.app.flags.mark_flag_as_required("out_dir")
-
-FLAGS = tf.app.flags.FLAGS
-
-NUM_TRAIN_FILES = 4620
-NUM_TEST_FILES = 1680
-SAMPLES_PER_TIMESTEP = 200
-
-# Regexes for reading SPHERE header files.
-SAMPLE_COUNT_REGEX = re.compile(r"sample_count -i (\d+)")
-SAMPLE_MIN_REGEX = re.compile(r"sample_min -i (-?\d+)")
-SAMPLE_MAX_REGEX = re.compile(r"sample_max -i (-?\d+)")
-
-
-def get_filenames(split):
- """Get all wav filenames from the TIMIT archive."""
- path = os.path.join(FLAGS.raw_timit_dir, "TIMIT", split, "*", "*", "*.WAV")
- # Sort the output by name so the order is deterministic.
- files = sorted(glob.glob(path))
- return files
-
-
-def load_timit_wav(filename):
- """Loads a TIMIT wavfile into a numpy array.
-
- TIMIT wavfiles include a SPHERE header, detailed in the TIMIT docs. The first
- line is the header type and the second is the length of the header in bytes.
- After the header, the remaining bytes are actual WAV data.
-
- The header includes information about the WAV data such as the number of
- samples and minimum and maximum amplitude. This function asserts that the
- loaded wav data matches the header.
-
- Args:
- filename: The name of the TIMIT wavfile to load.
- Returns:
- wav: A numpy array containing the loaded wav data.
- """
- wav_file = open(filename, "rb")
- header_type = wav_file.readline()
- header_length_str = wav_file.readline()
- # The header length includes the length of the first two lines.
- header_remaining_bytes = (int(header_length_str) - len(header_type) -
- len(header_length_str))
- header = wav_file.read(header_remaining_bytes)
- # Read the relevant header fields.
- sample_count = int(SAMPLE_COUNT_REGEX.search(header).group(1))
- sample_min = int(SAMPLE_MIN_REGEX.search(header).group(1))
- sample_max = int(SAMPLE_MAX_REGEX.search(header).group(1))
- wav = np.fromstring(wav_file.read(), dtype="int16").astype("float32")
- # Check that the loaded data conforms to the header description.
- assert len(wav) == sample_count
- assert wav.min() == sample_min
- assert wav.max() == sample_max
- return wav
-
-
-def preprocess(wavs, block_size, mean, std):
- """Normalize the wav data and reshape it into chunks."""
- processed_wavs = []
- for wav in wavs:
- wav = (wav - mean) / std
- wav_length = wav.shape[0]
- if wav_length % block_size != 0:
- pad_width = block_size - (wav_length % block_size)
- wav = np.pad(wav, (0, pad_width), "constant")
- assert wav.shape[0] % block_size == 0
- wav = wav.reshape((-1, block_size))
- processed_wavs.append(wav)
- return processed_wavs
-
-
-def create_tfrecord_from_wavs(wavs, output_file):
- """Writes processed wav files to disk as sharded TFRecord files."""
- with tf.python_io.TFRecordWriter(output_file) as builder:
- for wav in wavs:
- builder.write(wav.astype(np.float32).tobytes())
-
-
-def main(unused_argv):
- train_filenames = get_filenames("TRAIN")
- test_filenames = get_filenames("TEST")
-
- num_train_files = len(train_filenames)
- num_test_files = len(test_filenames)
- num_valid_files = int(num_train_files * FLAGS.valid_frac)
- num_train_files -= num_valid_files
-
- print("%d train / %d valid / %d test" % (
- num_train_files, num_valid_files, num_test_files))
-
- random.seed(1234)
- random.shuffle(train_filenames)
-
- valid_filenames = train_filenames[:num_valid_files]
- train_filenames = train_filenames[num_valid_files:]
-
- # Make sure there is no overlap in the train, test, and valid sets.
- train_s = set(train_filenames)
- test_s = set(test_filenames)
- valid_s = set(valid_filenames)
- # Disable explicit length testing to make the assertions more readable.
- # pylint: disable=g-explicit-length-test
- assert len(train_s & test_s) == 0
- assert len(train_s & valid_s) == 0
- assert len(valid_s & test_s) == 0
- # pylint: enable=g-explicit-length-test
-
- train_wavs = [load_timit_wav(f) for f in train_filenames]
- valid_wavs = [load_timit_wav(f) for f in valid_filenames]
- test_wavs = [load_timit_wav(f) for f in test_filenames]
- assert len(train_wavs) + len(valid_wavs) == NUM_TRAIN_FILES
- assert len(test_wavs) == NUM_TEST_FILES
-
- # Calculate the mean and standard deviation of the train set.
- train_stacked = np.hstack(train_wavs)
- train_mean = np.mean(train_stacked)
- train_std = np.std(train_stacked)
- print("train mean: %f train std: %f" % (train_mean, train_std))
-
- # Process all data, normalizing with the train set statistics.
- processed_train_wavs = preprocess(train_wavs, SAMPLES_PER_TIMESTEP,
- train_mean, train_std)
- processed_valid_wavs = preprocess(valid_wavs, SAMPLES_PER_TIMESTEP,
- train_mean, train_std)
- processed_test_wavs = preprocess(test_wavs, SAMPLES_PER_TIMESTEP, train_mean,
- train_std)
-
- # Write the datasets to disk.
- create_tfrecord_from_wavs(
- processed_train_wavs,
- os.path.join(FLAGS.out_dir, "train"))
- create_tfrecord_from_wavs(
- processed_valid_wavs,
- os.path.join(FLAGS.out_dir, "valid"))
- create_tfrecord_from_wavs(
- processed_test_wavs,
- os.path.join(FLAGS.out_dir, "test"))
-
-
-if __name__ == "__main__":
- tf.app.run()
diff --git a/research/fivo/fivo/data/datasets.py b/research/fivo/fivo/data/datasets.py
deleted file mode 100644
index 6d5324623250e31d65b23c97e7e684de59da1ba6..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/data/datasets.py
+++ /dev/null
@@ -1,453 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Code for creating sequence datasets.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import pickle
-
-import numpy as np
-from scipy.sparse import coo_matrix
-import tensorflow as tf
-
-# The default number of threads used to process data in parallel.
-DEFAULT_PARALLELISM = 12
-
-
-def sparse_pianoroll_to_dense(pianoroll, min_note, num_notes):
- """Converts a sparse pianoroll to a dense numpy array.
-
- Given a sparse pianoroll, converts it to a dense numpy array of shape
- [num_timesteps, num_notes] where entry i,j is 1.0 if note j is active on
- timestep i and 0.0 otherwise.
-
- Args:
- pianoroll: A sparse pianoroll object, a list of tuples where the i'th tuple
- contains the indices of the notes active at timestep i.
- min_note: The minimum note in the pianoroll, subtracted from all notes so
- that the minimum note becomes 0.
- num_notes: The number of possible different note indices, determines the
- second dimension of the resulting dense array.
- Returns:
- dense_pianoroll: A [num_timesteps, num_notes] numpy array of floats.
- num_timesteps: A python int, the number of timesteps in the pianoroll.
- """
- num_timesteps = len(pianoroll)
- inds = []
- for time, chord in enumerate(pianoroll):
- # Re-index the notes to start from min_note.
- inds.extend((time, note-min_note) for note in chord)
- shape = [num_timesteps, num_notes]
- values = [1.] * len(inds)
- sparse_pianoroll = coo_matrix(
- (values, ([x[0] for x in inds], [x[1] for x in inds])),
- shape=shape)
- return sparse_pianoroll.toarray(), num_timesteps
-
-
-def create_pianoroll_dataset(path,
- split,
- batch_size,
- num_parallel_calls=DEFAULT_PARALLELISM,
- shuffle=False,
- repeat=False,
- min_note=21,
- max_note=108):
- """Creates a pianoroll dataset.
-
- Args:
- path: The path of a pickle file containing the dataset to load.
- split: The split to use, can be train, test, or valid.
- batch_size: The batch size. If repeat is False then it is not guaranteed
- that the true batch size will match for all batches since batch_size
- may not necessarily evenly divide the number of elements.
- num_parallel_calls: The number of threads to use for parallel processing of
- the data.
- shuffle: If true, shuffles the order of the dataset.
- repeat: If true, repeats the dataset endlessly.
- min_note: The minimum note number of the dataset. For all pianoroll datasets
- the minimum note is number 21, and changing this affects the dimension of
- the data. This is useful mostly for testing.
- max_note: The maximum note number of the dataset. For all pianoroll datasets
- the maximum note is number 108, and changing this affects the dimension of
- the data. This is useful mostly for testing.
- Returns:
- inputs: A batch of input sequences represented as a dense Tensor of shape
- [time, batch_size, data_dimension]. The sequences in inputs are the
- sequences in targets shifted one timestep into the future, padded with
- zeros. This tensor is mean-centered, with the mean taken from the pickle
- file key 'train_mean'.
- targets: A batch of target sequences represented as a dense Tensor of
- shape [time, batch_size, data_dimension].
- lens: An int Tensor of shape [batch_size] representing the lengths of each
- sequence in the batch.
- mean: A float Tensor of shape [data_dimension] containing the mean loaded
- from the pickle file.
- """
- # Load the data from disk.
- num_notes = max_note - min_note + 1
- with tf.gfile.Open(path, "r") as f:
- raw_data = pickle.load(f)
- pianorolls = raw_data[split]
- mean = raw_data["train_mean"]
- num_examples = len(pianorolls)
-
- def pianoroll_generator():
- for sparse_pianoroll in pianorolls:
- yield sparse_pianoroll_to_dense(sparse_pianoroll, min_note, num_notes)
-
- dataset = tf.data.Dataset.from_generator(
- pianoroll_generator,
- output_types=(tf.float64, tf.int64),
- output_shapes=([None, num_notes], []))
-
- if repeat: dataset = dataset.repeat()
- if shuffle: dataset = dataset.shuffle(num_examples)
-
- # Batch sequences togther, padding them to a common length in time.
- dataset = dataset.padded_batch(batch_size,
- padded_shapes=([None, num_notes], []))
-
- def process_pianoroll_batch(data, lengths):
- """Create mean-centered and time-major next-step prediction Tensors."""
- data = tf.to_float(tf.transpose(data, perm=[1, 0, 2]))
- lengths = tf.to_int32(lengths)
- targets = data
- # Mean center the inputs.
- inputs = data - tf.constant(mean, dtype=tf.float32,
- shape=[1, 1, mean.shape[0]])
- # Shift the inputs one step forward in time. Also remove the last timestep
- # so that targets and inputs are the same length.
- inputs = tf.pad(inputs, [[1, 0], [0, 0], [0, 0]], mode="CONSTANT")[:-1]
- # Mask out unused timesteps.
- inputs *= tf.expand_dims(tf.transpose(
- tf.sequence_mask(lengths, dtype=inputs.dtype)), 2)
- return inputs, targets, lengths
-
- dataset = dataset.map(process_pianoroll_batch,
- num_parallel_calls=num_parallel_calls)
- dataset = dataset.prefetch(num_examples)
-
- itr = dataset.make_one_shot_iterator()
- inputs, targets, lengths = itr.get_next()
- return inputs, targets, lengths, tf.constant(mean, dtype=tf.float32)
-
-
-def create_human_pose_dataset(
- path,
- split,
- batch_size,
- num_parallel_calls=DEFAULT_PARALLELISM,
- shuffle=False,
- repeat=False,):
- """Creates a human pose dataset.
-
- Args:
- path: The path of a pickle file containing the dataset to load.
- split: The split to use, can be train, test, or valid.
- batch_size: The batch size. If repeat is False then it is not guaranteed
- that the true batch size will match for all batches since batch_size
- may not necessarily evenly divide the number of elements.
- num_parallel_calls: The number of threads to use for parallel processing of
- the data.
- shuffle: If true, shuffles the order of the dataset.
- repeat: If true, repeats the dataset endlessly.
- Returns:
- inputs: A batch of input sequences represented as a dense Tensor of shape
- [time, batch_size, data_dimension]. The sequences in inputs are the
- sequences in targets shifted one timestep into the future, padded with
- zeros. This tensor is mean-centered, with the mean taken from the pickle
- file key 'train_mean'.
- targets: A batch of target sequences represented as a dense Tensor of
- shape [time, batch_size, data_dimension].
- lens: An int Tensor of shape [batch_size] representing the lengths of each
- sequence in the batch.
- mean: A float Tensor of shape [data_dimension] containing the mean loaded
- from the pickle file.
- """
- # Load the data from disk.
- with tf.gfile.Open(path, "r") as f:
- raw_data = pickle.load(f)
-
- mean = raw_data["train_mean"]
- pose_sequences = raw_data[split]
- num_examples = len(pose_sequences)
- num_features = pose_sequences[0].shape[1]
-
- def pose_generator():
- """A generator that yields pose data sequences."""
- # Each timestep has 32 x values followed by 32 y values so is 64
- # dimensional.
- for pose_sequence in pose_sequences:
- yield pose_sequence, pose_sequence.shape[0]
-
- dataset = tf.data.Dataset.from_generator(
- pose_generator,
- output_types=(tf.float64, tf.int64),
- output_shapes=([None, num_features], []))
-
- if repeat:
- dataset = dataset.repeat()
- if shuffle:
- dataset = dataset.shuffle(num_examples)
-
- # Batch sequences togther, padding them to a common length in time.
- dataset = dataset.padded_batch(
- batch_size, padded_shapes=([None, num_features], []))
-
- # Post-process each batch, ensuring that it is mean-centered and time-major.
- def process_pose_data(data, lengths):
- """Creates Tensors for next step prediction and mean-centers the input."""
- data = tf.to_float(tf.transpose(data, perm=[1, 0, 2]))
- lengths = tf.to_int32(lengths)
- targets = data
- # Mean center the inputs.
- inputs = data - tf.constant(
- mean, dtype=tf.float32, shape=[1, 1, mean.shape[0]])
- # Shift the inputs one step forward in time. Also remove the last timestep
- # so that targets and inputs are the same length.
- inputs = tf.pad(inputs, [[1, 0], [0, 0], [0, 0]], mode="CONSTANT")[:-1]
- # Mask out unused timesteps.
- inputs *= tf.expand_dims(
- tf.transpose(tf.sequence_mask(lengths, dtype=inputs.dtype)), 2)
- return inputs, targets, lengths
-
- dataset = dataset.map(
- process_pose_data,
- num_parallel_calls=num_parallel_calls)
- dataset = dataset.prefetch(num_examples)
-
- itr = dataset.make_one_shot_iterator()
- inputs, targets, lengths = itr.get_next()
- return inputs, targets, lengths, tf.constant(mean, dtype=tf.float32)
-
-
-def create_speech_dataset(path,
- batch_size,
- samples_per_timestep=200,
- num_parallel_calls=DEFAULT_PARALLELISM,
- prefetch_buffer_size=2048,
- shuffle=False,
- repeat=False):
- """Creates a speech dataset.
-
- Args:
- path: The path of a possibly sharded TFRecord file containing the data.
- batch_size: The batch size. If repeat is False then it is not guaranteed
- that the true batch size will match for all batches since batch_size
- may not necessarily evenly divide the number of elements.
- samples_per_timestep: The number of audio samples per timestep. Used to
- reshape the data into sequences of shape [time, samples_per_timestep].
- Should not change except for testing -- in all speech datasets 200 is the
- number of samples per timestep.
- num_parallel_calls: The number of threads to use for parallel processing of
- the data.
- prefetch_buffer_size: The size of the prefetch queues to use after reading
- and processing the raw data.
- shuffle: If true, shuffles the order of the dataset.
- repeat: If true, repeats the dataset endlessly.
- Returns:
- inputs: A batch of input sequences represented as a dense Tensor of shape
- [time, batch_size, samples_per_timestep]. The sequences in inputs are the
- sequences in targets shifted one timestep into the future, padded with
- zeros.
- targets: A batch of target sequences represented as a dense Tensor of
- shape [time, batch_size, samples_per_timestep].
- lens: An int Tensor of shape [batch_size] representing the lengths of each
- sequence in the batch.
- """
- filenames = [path]
-
- def read_speech_example(value):
- """Parses a single tf.Example from the TFRecord file."""
- decoded = tf.decode_raw(value, out_type=tf.float32)
- example = tf.reshape(decoded, [-1, samples_per_timestep])
- length = tf.shape(example)[0]
- return example, length
-
- # Create the dataset from the TFRecord files
- dataset = tf.data.TFRecordDataset(filenames).map(
- read_speech_example, num_parallel_calls=num_parallel_calls)
- dataset = dataset.prefetch(prefetch_buffer_size)
-
- if repeat: dataset = dataset.repeat()
- if shuffle: dataset = dataset.shuffle(prefetch_buffer_size)
-
- dataset = dataset.padded_batch(
- batch_size, padded_shapes=([None, samples_per_timestep], []))
-
- def process_speech_batch(data, lengths):
- """Creates Tensors for next step prediction."""
- data = tf.transpose(data, perm=[1, 0, 2])
- lengths = tf.to_int32(lengths)
- targets = data
- # Shift the inputs one step forward in time. Also remove the last timestep
- # so that targets and inputs are the same length.
- inputs = tf.pad(data, [[1, 0], [0, 0], [0, 0]], mode="CONSTANT")[:-1]
- # Mask out unused timesteps.
- inputs *= tf.expand_dims(
- tf.transpose(tf.sequence_mask(lengths, dtype=inputs.dtype)), 2)
- return inputs, targets, lengths
-
- dataset = dataset.map(process_speech_batch,
- num_parallel_calls=num_parallel_calls)
- dataset = dataset.prefetch(prefetch_buffer_size)
-
- itr = dataset.make_one_shot_iterator()
- inputs, targets, lengths = itr.get_next()
- return inputs, targets, lengths
-
-
-SQUARED_OBSERVATION = "squared"
-ABS_OBSERVATION = "abs"
-STANDARD_OBSERVATION = "standard"
-OBSERVATION_TYPES = [SQUARED_OBSERVATION, ABS_OBSERVATION, STANDARD_OBSERVATION]
-
-ROUND_TRANSITION = "round"
-STANDARD_TRANSITION = "standard"
-TRANSITION_TYPES = [ROUND_TRANSITION, STANDARD_TRANSITION]
-
-
-def create_chain_graph_dataset(
- batch_size,
- num_timesteps,
- steps_per_observation=None,
- state_size=1,
- transition_variance=1.,
- observation_variance=1.,
- transition_type=STANDARD_TRANSITION,
- observation_type=STANDARD_OBSERVATION,
- fixed_observation=None,
- prefetch_buffer_size=2048,
- dtype="float32"):
- """Creates a toy chain graph dataset.
-
- Creates a dataset where the data are sampled from a diffusion process. The
- 'latent' states of the process are sampled as a chain of Normals:
-
- z0 ~ N(0, transition_variance)
- z1 ~ N(transition_fn(z0), transition_variance)
- ...
-
- where transition_fn could be round z0 or pass it through unchanged.
-
- The observations are produced every steps_per_observation timesteps as a
- function of the latent zs. For example if steps_per_observation is 3 then the
- first observation will be produced as a function of z3:
-
- x1 ~ N(observation_fn(z3), observation_variance)
-
- where observation_fn could square z3, take the absolute value, or pass
- it through unchanged.
-
- Only the observations are returned.
-
- Args:
- batch_size: The batch size. The number of trajectories to run in parallel.
- num_timesteps: The length of the chain of latent states (i.e. the
- number of z's excluding z0.
- steps_per_observation: The number of latent states between each observation,
- must evenly divide num_timesteps.
- state_size: The size of the latent state and observation, must be a
- python int.
- transition_variance: The variance of the transition density.
- observation_variance: The variance of the observation density.
- transition_type: Must be one of "round" or "standard". "round" means that
- the transition density is centered at the rounded previous latent state.
- "standard" centers the transition density at the previous latent state,
- unchanged.
- observation_type: Must be one of "squared", "abs" or "standard". "squared"
- centers the observation density at the squared latent state. "abs"
- centers the observaiton density at the absolute value of the current
- latent state. "standard" centers the observation density at the current
- latent state.
- fixed_observation: If not None, fixes all observations to be a constant.
- Must be a scalar.
- prefetch_buffer_size: The size of the prefetch queues to use after reading
- and processing the raw data.
- dtype: A string convertible to a tensorflow datatype. The datatype used
- to represent the states and observations.
- Returns:
- observations: A batch of observations represented as a dense Tensor of
- shape [num_observations, batch_size, state_size]. num_observations is
- num_timesteps/steps_per_observation.
- lens: An int Tensor of shape [batch_size] representing the lengths of each
- sequence in the batch. Will contain num_observations as each entry.
- Raises:
- ValueError: Raised if steps_per_observation does not evenly divide
- num_timesteps.
- """
- if steps_per_observation is None:
- steps_per_observation = num_timesteps
- if num_timesteps % steps_per_observation != 0:
- raise ValueError("steps_per_observation must evenly divide num_timesteps.")
- num_observations = int(num_timesteps / steps_per_observation)
- def data_generator():
- """An infinite generator of latents and observations from the model."""
- transition_std = np.sqrt(transition_variance)
- observation_std = np.sqrt(observation_variance)
- while True:
- states = []
- observations = []
- # Sample z0 ~ Normal(0, sqrt(variance)).
- states.append(
- np.random.normal(size=[state_size],
- scale=observation_std).astype(dtype))
- # Start the range at 1 because we've already generated z0.
- # The range ends at num_timesteps+1 because we want to include the
- # num_timesteps-th step.
- for t in xrange(1, num_timesteps+1):
- if transition_type == ROUND_TRANSITION:
- loc = np.round(states[-1])
- elif transition_type == STANDARD_TRANSITION:
- loc = states[-1]
- z_t = np.random.normal(size=[state_size], loc=loc, scale=transition_std)
- states.append(z_t.astype(dtype))
- if t % steps_per_observation == 0:
- if fixed_observation is None:
- if observation_type == SQUARED_OBSERVATION:
- loc = np.square(states[-1])
- elif observation_type == ABS_OBSERVATION:
- loc = np.abs(states[-1])
- elif observation_type == STANDARD_OBSERVATION:
- loc = states[-1]
- x_t = np.random.normal(size=[state_size],
- loc=loc,
- scale=observation_std).astype(dtype)
- else:
- x_t = np.ones([state_size]) * fixed_observation
-
- observations.append(x_t)
- yield states, observations
-
- dataset = tf.data.Dataset.from_generator(
- data_generator,
- output_types=(tf.as_dtype(dtype), tf.as_dtype(dtype)),
- output_shapes=([num_timesteps+1, state_size],
- [num_observations, state_size])
- )
- dataset = dataset.repeat().batch(batch_size)
- dataset = dataset.prefetch(prefetch_buffer_size)
- itr = dataset.make_one_shot_iterator()
- _, observations = itr.get_next()
- # Transpose observations from [batch, time, state_size] to
- # [time, batch, state_size].
- observations = tf.transpose(observations, perm=[1, 0, 2])
- lengths = tf.ones([batch_size], dtype=tf.int32) * num_observations
- return observations, lengths
diff --git a/research/fivo/fivo/data/datasets_test.py b/research/fivo/fivo/data/datasets_test.py
deleted file mode 100644
index e6bbfda67aa44efc0bc4b1a34eb0cb9f09d53de5..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/data/datasets_test.py
+++ /dev/null
@@ -1,303 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests for fivo.data.datasets."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import pickle
-import os
-
-import numpy as np
-import tensorflow as tf
-
-from fivo.data import datasets
-
-FLAGS = tf.app.flags.FLAGS
-
-
-class DatasetsTest(tf.test.TestCase):
-
- def test_sparse_pianoroll_to_dense_empty_at_end(self):
- sparse_pianoroll = [(0, 1), (1, 0), (), (1,), (), ()]
- dense_pianoroll, num_timesteps = datasets.sparse_pianoroll_to_dense(
- sparse_pianoroll, min_note=0, num_notes=2)
- self.assertEqual(num_timesteps, 6)
- self.assertAllEqual([[1, 1],
- [1, 1],
- [0, 0],
- [0, 1],
- [0, 0],
- [0, 0]], dense_pianoroll)
-
- def test_sparse_pianoroll_to_dense_with_chord(self):
- sparse_pianoroll = [(0, 1), (1, 0), (), (1,)]
- dense_pianoroll, num_timesteps = datasets.sparse_pianoroll_to_dense(
- sparse_pianoroll, min_note=0, num_notes=2)
- self.assertEqual(num_timesteps, 4)
- self.assertAllEqual([[1, 1],
- [1, 1],
- [0, 0],
- [0, 1]], dense_pianoroll)
-
- def test_sparse_pianoroll_to_dense_simple(self):
- sparse_pianoroll = [(0,), (), (1,)]
- dense_pianoroll, num_timesteps = datasets.sparse_pianoroll_to_dense(
- sparse_pianoroll, min_note=0, num_notes=2)
- self.assertEqual(num_timesteps, 3)
- self.assertAllEqual([[1, 0],
- [0, 0],
- [0, 1]], dense_pianoroll)
-
- def test_sparse_pianoroll_to_dense_subtracts_min_note(self):
- sparse_pianoroll = [(4, 5), (5, 4), (), (5,), (), ()]
- dense_pianoroll, num_timesteps = datasets.sparse_pianoroll_to_dense(
- sparse_pianoroll, min_note=4, num_notes=2)
- self.assertEqual(num_timesteps, 6)
- self.assertAllEqual([[1, 1],
- [1, 1],
- [0, 0],
- [0, 1],
- [0, 0],
- [0, 0]], dense_pianoroll)
-
- def test_sparse_pianoroll_to_dense_uses_num_notes(self):
- sparse_pianoroll = [(4, 5), (5, 4), (), (5,), (), ()]
- dense_pianoroll, num_timesteps = datasets.sparse_pianoroll_to_dense(
- sparse_pianoroll, min_note=4, num_notes=3)
- self.assertEqual(num_timesteps, 6)
- self.assertAllEqual([[1, 1, 0],
- [1, 1, 0],
- [0, 0, 0],
- [0, 1, 0],
- [0, 0, 0],
- [0, 0, 0]], dense_pianoroll)
-
- def test_pianoroll_dataset(self):
- pianoroll_data = [[(0,), (), (1,)],
- [(0, 1), (1,)],
- [(1,), (0,), (), (0, 1), (), ()]]
- pianoroll_mean = np.zeros([3])
- pianoroll_mean[-1] = 1
- data = {"train": pianoroll_data, "train_mean": pianoroll_mean}
- path = os.path.join(tf.test.get_temp_dir(), "test.pkl")
- pickle.dump(data, open(path, "wb"))
- with self.test_session() as sess:
- inputs, targets, lens, mean = datasets.create_pianoroll_dataset(
- path, "train", 2, num_parallel_calls=1,
- shuffle=False, repeat=False,
- min_note=0, max_note=2)
- i1, t1, l1 = sess.run([inputs, targets, lens])
- i2, t2, l2 = sess.run([inputs, targets, lens])
- m = sess.run(mean)
- # Check the lengths.
- self.assertAllEqual([3, 2], l1)
- self.assertAllEqual([6], l2)
- # Check the mean.
- self.assertAllEqual(pianoroll_mean, m)
- # Check the targets. The targets should not be mean-centered and should
- # be padded with zeros to a common length within a batch.
- self.assertAllEqual([[1, 0, 0],
- [0, 0, 0],
- [0, 1, 0]], t1[:, 0, :])
- self.assertAllEqual([[1, 1, 0],
- [0, 1, 0],
- [0, 0, 0]], t1[:, 1, :])
- self.assertAllEqual([[0, 1, 0],
- [1, 0, 0],
- [0, 0, 0],
- [1, 1, 0],
- [0, 0, 0],
- [0, 0, 0]], t2[:, 0, :])
- # Check the inputs. Each sequence should start with zeros on the first
- # timestep. Each sequence should be padded with zeros to a common length
- # within a batch. The mean should be subtracted from all timesteps except
- # the first and the padding.
- self.assertAllEqual([[0, 0, 0],
- [1, 0, -1],
- [0, 0, -1]], i1[:, 0, :])
- self.assertAllEqual([[0, 0, 0],
- [1, 1, -1],
- [0, 0, 0]], i1[:, 1, :])
- self.assertAllEqual([[0, 0, 0],
- [0, 1, -1],
- [1, 0, -1],
- [0, 0, -1],
- [1, 1, -1],
- [0, 0, -1]], i2[:, 0, :])
-
- def test_human_pose_dataset(self):
- pose_data = [
- [[0, 0], [2, 2]],
- [[2, 2]],
- [[0, 0], [0, 0], [2, 2], [2, 2], [0, 0]],
- ]
- pose_data = [np.array(x, dtype=np.float64) for x in pose_data]
- pose_data_mean = np.array([1, 1], dtype=np.float64)
- data = {
- "train": pose_data,
- "train_mean": pose_data_mean,
- }
- path = os.path.join(tf.test.get_temp_dir(), "test_human_pose_dataset.pkl")
- with open(path, "wb") as out:
- pickle.dump(data, out)
- with self.test_session() as sess:
- inputs, targets, lens, mean = datasets.create_human_pose_dataset(
- path, "train", 2, num_parallel_calls=1, shuffle=False, repeat=False)
- i1, t1, l1 = sess.run([inputs, targets, lens])
- i2, t2, l2 = sess.run([inputs, targets, lens])
- m = sess.run(mean)
- # Check the lengths.
- self.assertAllEqual([2, 1], l1)
- self.assertAllEqual([5], l2)
- # Check the mean.
- self.assertAllEqual(pose_data_mean, m)
- # Check the targets. The targets should not be mean-centered and should
- # be padded with zeros to a common length within a batch.
- self.assertAllEqual([[0, 0], [2, 2]], t1[:, 0, :])
- self.assertAllEqual([[2, 2], [0, 0]], t1[:, 1, :])
- self.assertAllEqual([[0, 0], [0, 0], [2, 2], [2, 2], [0, 0]], t2[:, 0, :])
- # Check the inputs. Each sequence should start with zeros on the first
- # timestep. Each sequence should be padded with zeros to a common length
- # within a batch. The mean should be subtracted from all timesteps except
- # the first and the padding.
- self.assertAllEqual([[0, 0], [-1, -1]], i1[:, 0, :])
- self.assertAllEqual([[0, 0], [0, 0]], i1[:, 1, :])
- self.assertAllEqual([[0, 0], [-1, -1], [-1, -1], [1, 1], [1, 1]],
- i2[:, 0, :])
-
- def test_speech_dataset(self):
- with self.test_session() as sess:
- path = os.path.join(
- os.path.dirname(os.path.dirname(os.path.realpath(__file__))),
- "test_data",
- "tiny_speech_dataset.tfrecord")
- inputs, targets, lens = datasets.create_speech_dataset(
- path, 3, samples_per_timestep=2, num_parallel_calls=1,
- prefetch_buffer_size=3, shuffle=False, repeat=False)
- inputs1, targets1, lengths1 = sess.run([inputs, targets, lens])
- inputs2, targets2, lengths2 = sess.run([inputs, targets, lens])
- # Check the lengths.
- self.assertAllEqual([1, 2, 3], lengths1)
- self.assertAllEqual([4], lengths2)
- # Check the targets. The targets should be padded with zeros to a common
- # length within a batch.
- self.assertAllEqual([[[0., 1.], [0., 1.], [0., 1.]],
- [[0., 0.], [2., 3.], [2., 3.]],
- [[0., 0.], [0., 0.], [4., 5.]]],
- targets1)
- self.assertAllEqual([[[0., 1.]],
- [[2., 3.]],
- [[4., 5.]],
- [[6., 7.]]],
- targets2)
- # Check the inputs. Each sequence should start with zeros on the first
- # timestep. Each sequence should be padded with zeros to a common length
- # within a batch.
- self.assertAllEqual([[[0., 0.], [0., 0.], [0., 0.]],
- [[0., 0.], [0., 1.], [0., 1.]],
- [[0., 0.], [0., 0.], [2., 3.]]],
- inputs1)
- self.assertAllEqual([[[0., 0.]],
- [[0., 1.]],
- [[2., 3.]],
- [[4., 5.]]],
- inputs2)
-
- def test_chain_graph_raises_error_on_wrong_steps_per_observation(self):
- with self.assertRaises(ValueError):
- datasets.create_chain_graph_dataset(
- batch_size=4,
- num_timesteps=10,
- steps_per_observation=9)
-
- def test_chain_graph_single_obs(self):
- with self.test_session() as sess:
- np.random.seed(1234)
- num_observations = 1
- num_timesteps = 5
- batch_size = 2
- state_size = 1
- observations, lengths = datasets.create_chain_graph_dataset(
- batch_size=batch_size,
- num_timesteps=num_timesteps,
- state_size=state_size)
- out_observations, out_lengths = sess.run([observations, lengths])
- self.assertAllEqual([num_observations, num_observations], out_lengths)
- self.assertAllClose(
- [[[1.426677], [-1.789461]]],
- out_observations)
-
- def test_chain_graph_multiple_obs(self):
- with self.test_session() as sess:
- np.random.seed(1234)
- num_observations = 3
- num_timesteps = 6
- batch_size = 2
- state_size = 1
- observations, lengths = datasets.create_chain_graph_dataset(
- batch_size=batch_size,
- num_timesteps=num_timesteps,
- steps_per_observation=num_timesteps/num_observations,
- state_size=state_size)
- out_observations, out_lengths = sess.run([observations, lengths])
- self.assertAllEqual([num_observations, num_observations], out_lengths)
- self.assertAllClose(
- [[[0.40051451], [1.07405114]],
- [[1.73932898], [3.16880035]],
- [[-1.98377144], [2.82669163]]],
- out_observations)
-
- def test_chain_graph_state_dims(self):
- with self.test_session() as sess:
- np.random.seed(1234)
- num_observations = 1
- num_timesteps = 5
- batch_size = 2
- state_size = 3
- observations, lengths = datasets.create_chain_graph_dataset(
- batch_size=batch_size,
- num_timesteps=num_timesteps,
- state_size=state_size)
- out_observations, out_lengths = sess.run([observations, lengths])
- self.assertAllEqual([num_observations, num_observations], out_lengths)
- self.assertAllClose(
- [[[1.052287, -4.560759, 3.07988],
- [2.008926, 0.495567, 3.488678]]],
- out_observations)
-
- def test_chain_graph_fixed_obs(self):
- with self.test_session() as sess:
- np.random.seed(1234)
- num_observations = 3
- num_timesteps = 6
- batch_size = 2
- state_size = 1
- observations, lengths = datasets.create_chain_graph_dataset(
- batch_size=batch_size,
- num_timesteps=num_timesteps,
- steps_per_observation=num_timesteps/num_observations,
- state_size=state_size,
- fixed_observation=4.)
- out_observations, out_lengths = sess.run([observations, lengths])
- self.assertAllEqual([num_observations, num_observations], out_lengths)
- self.assertAllClose(
- np.ones([num_observations, batch_size, state_size]) * 4.,
- out_observations)
-
-if __name__ == "__main__":
- tf.test.main()
diff --git a/research/fivo/fivo/ghmm_runners.py b/research/fivo/fivo/ghmm_runners.py
deleted file mode 100644
index 1f1ba6d4f9ea9ed9dee7d95449ba73285c77f24d..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/ghmm_runners.py
+++ /dev/null
@@ -1,235 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Creates and runs Gaussian HMM-related graphs."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-
-import numpy as np
-import tensorflow as tf
-
-from fivo import smc
-from fivo import bounds
-from fivo.data import datasets
-from fivo.models import ghmm
-
-
-def run_train(config):
- """Runs training for a Gaussian HMM setup."""
-
- def create_logging_hook(step, bound_value, likelihood, bound_gap):
- """Creates a logging hook that prints the bound value periodically."""
- bound_label = config.bound + "/t"
- def summary_formatter(log_dict):
- string = ("Step {step}, %s: {value:.3f}, "
- "likelihood: {ll:.3f}, gap: {gap:.3e}") % bound_label
- return string.format(**log_dict)
- logging_hook = tf.train.LoggingTensorHook(
- {"step": step, "value": bound_value,
- "ll": likelihood, "gap": bound_gap},
- every_n_iter=config.summarize_every,
- formatter=summary_formatter)
- return logging_hook
-
- def create_losses(model, observations, lengths):
- """Creates the loss to be optimized.
-
- Args:
- model: A Trainable GHMM model.
- observations: A set of observations.
- lengths: The lengths of each sequence in the observations.
- Returns:
- loss: A float Tensor that when differentiated yields the gradients
- to apply to the model. Should be optimized via gradient descent.
- bound: A float Tensor containing the value of the bound that is
- being optimized.
- true_ll: The true log-likelihood of the data under the model.
- bound_gap: The gap between the bound and the true log-likelihood.
- """
- # Compute lower bounds on the log likelihood.
- if config.bound == "elbo":
- ll_per_seq, _, _ = bounds.iwae(
- model, observations, lengths, num_samples=1,
- parallel_iterations=config.parallel_iterations
- )
- elif config.bound == "iwae":
- ll_per_seq, _, _ = bounds.iwae(
- model, observations, lengths, num_samples=config.num_samples,
- parallel_iterations=config.parallel_iterations
- )
- elif config.bound == "fivo":
- if config.resampling_type == "relaxed":
- ll_per_seq, _, _, _ = bounds.fivo(
- model,
- observations,
- lengths,
- num_samples=config.num_samples,
- resampling_criterion=smc.ess_criterion,
- resampling_type=config.resampling_type,
- relaxed_resampling_temperature=config.
- relaxed_resampling_temperature,
- random_seed=config.random_seed,
- parallel_iterations=config.parallel_iterations)
- else:
- ll_per_seq, _, _, _ = bounds.fivo(
- model, observations, lengths,
- num_samples=config.num_samples,
- resampling_criterion=smc.ess_criterion,
- resampling_type=config.resampling_type,
- random_seed=config.random_seed,
- parallel_iterations=config.parallel_iterations
- )
- ll_per_t = tf.reduce_mean(ll_per_seq / tf.to_float(lengths))
- # Compute the data's true likelihood under the model and the bound gap.
- true_ll_per_seq = model.likelihood(tf.squeeze(observations))
- true_ll_per_t = tf.reduce_mean(true_ll_per_seq / tf.to_float(lengths))
- bound_gap = true_ll_per_seq - ll_per_seq
- bound_gap = tf.reduce_mean(bound_gap/ tf.to_float(lengths))
- tf.summary.scalar("train_ll_bound", ll_per_t)
- tf.summary.scalar("train_true_ll", true_ll_per_t)
- tf.summary.scalar("bound_gap", bound_gap)
- return -ll_per_t, ll_per_t, true_ll_per_t, bound_gap
-
- def create_graph():
- """Creates the training graph."""
- global_step = tf.train.get_or_create_global_step()
- xs, lengths = datasets.create_chain_graph_dataset(
- config.batch_size,
- config.num_timesteps,
- steps_per_observation=1,
- state_size=1,
- transition_variance=config.variance,
- observation_variance=config.variance)
- model = ghmm.TrainableGaussianHMM(
- config.num_timesteps,
- config.proposal_type,
- transition_variances=config.variance,
- emission_variances=config.variance,
- random_seed=config.random_seed)
- loss, bound, true_ll, gap = create_losses(model, xs, lengths)
- opt = tf.train.AdamOptimizer(config.learning_rate)
- grads = opt.compute_gradients(loss, var_list=tf.trainable_variables())
- train_op = opt.apply_gradients(grads, global_step=global_step)
- return bound, true_ll, gap, train_op, global_step
-
- with tf.Graph().as_default():
- if config.random_seed:
- tf.set_random_seed(config.random_seed)
- np.random.seed(config.random_seed)
- bound, true_ll, gap, train_op, global_step = create_graph()
- log_hook = create_logging_hook(global_step, bound, true_ll, gap)
- with tf.train.MonitoredTrainingSession(
- master="",
- hooks=[log_hook],
- checkpoint_dir=config.logdir,
- save_checkpoint_secs=120,
- save_summaries_steps=config.summarize_every,
- log_step_count_steps=config.summarize_every*20) as sess:
- cur_step = -1
- while cur_step <= config.max_steps and not sess.should_stop():
- cur_step = sess.run(global_step)
- _, cur_step = sess.run([train_op, global_step])
-
-
-def run_eval(config):
- """Evaluates a Gaussian HMM using the given config."""
-
- def create_bound(model, xs, lengths):
- """Creates the bound to be evaluated."""
- if config.bound == "elbo":
- ll_per_seq, log_weights, _ = bounds.iwae(
- model, xs, lengths, num_samples=1,
- parallel_iterations=config.parallel_iterations
- )
- elif config.bound == "iwae":
- ll_per_seq, log_weights, _ = bounds.iwae(
- model, xs, lengths, num_samples=config.num_samples,
- parallel_iterations=config.parallel_iterations
- )
- elif config.bound == "fivo":
- ll_per_seq, log_weights, resampled, _ = bounds.fivo(
- model, xs, lengths,
- num_samples=config.num_samples,
- resampling_criterion=smc.ess_criterion,
- resampling_type=config.resampling_type,
- random_seed=config.random_seed,
- parallel_iterations=config.parallel_iterations
- )
- # Compute bound scaled by number of timesteps.
- bound_per_t = ll_per_seq / tf.to_float(lengths)
- if config.bound == "fivo":
- return bound_per_t, log_weights, resampled
- else:
- return bound_per_t, log_weights
-
- def create_graph():
- """Creates the dataset, model, and bound."""
- xs, lengths = datasets.create_chain_graph_dataset(
- config.batch_size,
- config.num_timesteps,
- steps_per_observation=1,
- state_size=1,
- transition_variance=config.variance,
- observation_variance=config.variance)
- model = ghmm.TrainableGaussianHMM(
- config.num_timesteps,
- config.proposal_type,
- transition_variances=config.variance,
- emission_variances=config.variance,
- random_seed=config.random_seed)
- true_likelihood = tf.reduce_mean(
- model.likelihood(tf.squeeze(xs)) / tf.to_float(lengths))
- outs = [true_likelihood]
- outs.extend(list(create_bound(model, xs, lengths)))
- return outs
-
- with tf.Graph().as_default():
- if config.random_seed:
- tf.set_random_seed(config.random_seed)
- np.random.seed(config.random_seed)
- graph_outs = create_graph()
- with tf.train.SingularMonitoredSession(
- checkpoint_dir=config.logdir) as sess:
- outs = sess.run(graph_outs)
- likelihood = outs[0]
- avg_bound = np.mean(outs[1])
- std = np.std(outs[1])
- log_weights = outs[2]
- log_weight_variances = np.var(log_weights, axis=2)
- avg_log_weight_variance = np.var(log_weight_variances, axis=1)
- avg_log_weight = np.mean(log_weights, axis=(1, 2))
- data = {"mean": avg_bound, "std": std, "log_weights": log_weights,
- "log_weight_means": avg_log_weight,
- "log_weight_variances": avg_log_weight_variance}
- if len(outs) == 4:
- data["resampled"] = outs[3]
- data["avg_resampled"] = np.mean(outs[3], axis=1)
- # Log some useful statistics.
- tf.logging.info("Evaled bound %s with batch_size: %d, num_samples: %d."
- % (config.bound, config.batch_size, config.num_samples))
- tf.logging.info("mean: %f, std: %f" % (avg_bound, std))
- tf.logging.info("true likelihood: %s" % likelihood)
- tf.logging.info("avg log weight: %s" % avg_log_weight)
- tf.logging.info("log weight variance: %s" % avg_log_weight_variance)
- if len(outs) == 4:
- tf.logging.info("avg resamples per t: %s" % data["avg_resampled"])
- if not tf.gfile.Exists(config.logdir):
- tf.gfile.MakeDirs(config.logdir)
- with tf.gfile.Open(os.path.join(config.logdir, "out.npz"), "w") as fout:
- np.save(fout, data)
diff --git a/research/fivo/fivo/ghmm_runners_test.py b/research/fivo/fivo/ghmm_runners_test.py
deleted file mode 100644
index 50044ad475b3458858b580a6ff7664267485757b..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/ghmm_runners_test.py
+++ /dev/null
@@ -1,106 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests for fivo.ghmm_runners."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import numpy as np
-import tensorflow as tf
-
-from fivo import ghmm_runners
-
-
-class GHMMRunnersTest(tf.test.TestCase):
-
- def default_config(self):
- class Config(object):
- pass
- config = Config()
- config.model = "ghmm"
- config.bound = "fivo"
- config.proposal_type = "prior"
- config.batch_size = 4
- config.num_samples = 4
- config.num_timesteps = 10
- config.variance = 0.1
- config.resampling_type = "multinomial"
- config.random_seed = 1234
- config.parallel_iterations = 1
- config.learning_rate = 1e-4
- config.summarize_every = 1
- config.max_steps = 1
- return config
-
- def test_eval_ghmm_notraining_fivo_prior(self):
- self.eval_ghmm_notraining("fivo", "prior", -3.063864)
-
- def test_eval_ghmm_notraining_fivo_true_filtering(self):
- self.eval_ghmm_notraining("fivo", "true-filtering", -1.1409812)
-
- def test_eval_ghmm_notraining_fivo_true_smoothing(self):
- self.eval_ghmm_notraining("fivo", "true-smoothing", -0.85592091)
-
- def test_eval_ghmm_notraining_iwae_prior(self):
- self.eval_ghmm_notraining("iwae", "prior", -5.9730167)
-
- def test_eval_ghmm_notraining_iwae_true_filtering(self):
- self.eval_ghmm_notraining("iwae", "true-filtering", -1.1485999)
-
- def test_eval_ghmm_notraining_iwae_true_smoothing(self):
- self.eval_ghmm_notraining("iwae", "true-smoothing", -0.85592091)
-
- def eval_ghmm_notraining(self, bound, proposal_type, expected_bound_avg):
- config = self.default_config()
- config.proposal_type = proposal_type
- config.bound = bound
- config.logdir = os.path.join(
- tf.test.get_temp_dir(), "test-ghmm-%s-%s" % (proposal_type, bound))
-
- ghmm_runners.run_eval(config)
-
- data = np.load(os.path.join(config.logdir, "out.npz")).item()
- self.assertAlmostEqual(expected_bound_avg, data["mean"], places=3)
-
- def test_train_ghmm_for_one_step_and_eval_fivo_filtering(self):
- self.train_ghmm_for_one_step_and_eval("fivo", "filtering", -16.727108)
-
- def test_train_ghmm_for_one_step_and_eval_fivo_smoothing(self):
- self.train_ghmm_for_one_step_and_eval("fivo", "smoothing", -19.381277)
-
- def test_train_ghmm_for_one_step_and_eval_iwae_filtering(self):
- self.train_ghmm_for_one_step_and_eval("iwae", "filtering", -33.31966)
-
- def test_train_ghmm_for_one_step_and_eval_iwae_smoothing(self):
- self.train_ghmm_for_one_step_and_eval("iwae", "smoothing", -46.388447)
-
- def train_ghmm_for_one_step_and_eval(self, bound, proposal_type, expected_bound_avg):
- config = self.default_config()
- config.proposal_type = proposal_type
- config.bound = bound
- config.max_steps = 1
- config.logdir = os.path.join(
- tf.test.get_temp_dir(), "test-ghmm-training-%s-%s" % (proposal_type, bound))
- ghmm_runners.run_train(config)
- ghmm_runners.run_eval(config)
- data = np.load(os.path.join(config.logdir, "out.npz")).item()
- self.assertAlmostEqual(expected_bound_avg, data["mean"], places=2)
-
-
-if __name__ == "__main__":
- tf.test.main()
diff --git a/research/fivo/fivo/models/__init__.py b/research/fivo/fivo/models/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/fivo/fivo/models/base.py b/research/fivo/fivo/models/base.py
deleted file mode 100644
index 5ffcb7af216f5659e71d7425eeb4e2c3158b3d47..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/models/base.py
+++ /dev/null
@@ -1,342 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Reusable model classes for FIVO."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import sonnet as snt
-import tensorflow as tf
-
-from fivo import nested_utils as nested
-
-tfd = tf.contrib.distributions
-
-
-class ELBOTrainableSequenceModel(object):
- """An abstract class for ELBO-trainable sequence models to extend.
-
- Because the ELBO, IWAE, and FIVO bounds all accept the same arguments,
- any model that is ELBO-trainable is also IWAE- and FIVO-trainable.
- """
-
- def zero_state(self, batch_size, dtype):
- """Returns the initial state of the model as a Tensor or tuple of Tensors.
-
- Args:
- batch_size: The batch size.
- dtype: The datatype to use for the state.
- """
- raise NotImplementedError("zero_state not yet implemented.")
-
- def set_observations(self, observations, seq_lengths):
- """Sets the observations for the model.
-
- This method provides the model with all observed variables including both
- inputs and targets. It will be called before running any computations with
- the model that require the observations, e.g. training the model or
- computing bounds, and should be used to run any necessary preprocessing
- steps.
-
- Args:
- observations: A potentially nested set of Tensors containing
- all observations for the model, both inputs and targets. Typically
- a set of Tensors with shape [max_seq_len, batch_size, data_size].
- seq_lengths: A [batch_size] Tensor of ints encoding the length of each
- sequence in the batch (sequences can be padded to a common length).
- """
- self.observations = observations
- self.max_seq_len = tf.reduce_max(seq_lengths)
- self.observations_ta = nested.tas_for_tensors(
- observations, self.max_seq_len, clear_after_read=False)
- self.seq_lengths = seq_lengths
-
- def propose_and_weight(self, state, t):
- """Propogates model state one timestep and computes log weights.
-
- This method accepts the current state of the model and computes the state
- for the next timestep as well as the incremental log weight of each
- element in the batch.
-
- Args:
- state: The current state of the model.
- t: A scalar integer Tensor representing the current timestep.
- Returns:
- next_state: The state of the model after one timestep.
- log_weights: A [batch_size] Tensor containing the incremental log weights.
- """
- raise NotImplementedError("propose_and_weight not yet implemented.")
-
-DEFAULT_INITIALIZERS = {"w": tf.contrib.layers.xavier_initializer(),
- "b": tf.zeros_initializer()}
-
-
-class ConditionalNormalDistribution(object):
- """A Normal distribution conditioned on Tensor inputs via a fc network."""
-
- def __init__(self, size, hidden_layer_sizes, sigma_min=0.0,
- raw_sigma_bias=0.25, hidden_activation_fn=tf.nn.relu,
- initializers=None, name="conditional_normal_distribution"):
- """Creates a conditional Normal distribution.
-
- Args:
- size: The dimension of the random variable.
- hidden_layer_sizes: The sizes of the hidden layers of the fully connected
- network used to condition the distribution on the inputs.
- sigma_min: The minimum standard deviation allowed, a scalar.
- raw_sigma_bias: A scalar that is added to the raw standard deviation
- output from the fully connected network. Set to 0.25 by default to
- prevent standard deviations close to 0.
- hidden_activation_fn: The activation function to use on the hidden layers
- of the fully connected network.
- initializers: The variable intitializers to use for the fully connected
- network. The network is implemented using snt.nets.MLP so it must
- be a dictionary mapping the keys 'w' and 'b' to the initializers for
- the weights and biases. Defaults to xavier for the weights and zeros
- for the biases when initializers is None.
- name: The name of this distribution, used for sonnet scoping.
- """
- self.sigma_min = sigma_min
- self.raw_sigma_bias = raw_sigma_bias
- self.name = name
- self.size = size
- if initializers is None:
- initializers = DEFAULT_INITIALIZERS
- self.fcnet = snt.nets.MLP(
- output_sizes=hidden_layer_sizes + [2*size],
- activation=hidden_activation_fn,
- initializers=initializers,
- activate_final=False,
- use_bias=True,
- name=name + "_fcnet")
-
- def condition(self, tensor_list, **unused_kwargs):
- """Computes the parameters of a normal distribution based on the inputs."""
- inputs = tf.concat(tensor_list, axis=1)
- outs = self.fcnet(inputs)
- mu, sigma = tf.split(outs, 2, axis=1)
- sigma = tf.maximum(tf.nn.softplus(sigma + self.raw_sigma_bias),
- self.sigma_min)
- return mu, sigma
-
- def __call__(self, *args, **kwargs):
- """Creates a normal distribution conditioned on the inputs."""
- mu, sigma = self.condition(args, **kwargs)
- return tf.contrib.distributions.Normal(loc=mu, scale=sigma)
-
-
-class ConditionalBernoulliDistribution(object):
- """A Bernoulli distribution conditioned on Tensor inputs via a fc net."""
-
- def __init__(self, size, hidden_layer_sizes, hidden_activation_fn=tf.nn.relu,
- initializers=None, bias_init=0.0,
- name="conditional_bernoulli_distribution"):
- """Creates a conditional Bernoulli distribution.
-
- Args:
- size: The dimension of the random variable.
- hidden_layer_sizes: The sizes of the hidden layers of the fully connected
- network used to condition the distribution on the inputs.
- hidden_activation_fn: The activation function to use on the hidden layers
- of the fully connected network.
- initializers: The variable intiializers to use for the fully connected
- network. The network is implemented using snt.nets.MLP so it must
- be a dictionary mapping the keys 'w' and 'b' to the initializers for
- the weights and biases. Defaults to xavier for the weights and zeros
- for the biases when initializers is None.
- bias_init: A scalar or vector Tensor that is added to the output of the
- fully-connected network that parameterizes the mean of this
- distribution.
- name: The name of this distribution, used for sonnet scoping.
- """
- self.bias_init = bias_init
- self.size = size
- if initializers is None:
- initializers = DEFAULT_INITIALIZERS
- self.fcnet = snt.nets.MLP(
- output_sizes=hidden_layer_sizes + [size],
- activation=hidden_activation_fn,
- initializers=initializers,
- activate_final=False,
- use_bias=True,
- name=name + "_fcnet")
-
- def condition(self, tensor_list):
- """Computes the p parameter of the Bernoulli distribution."""
- inputs = tf.concat(tensor_list, axis=1)
- return self.fcnet(inputs) + self.bias_init
-
- def __call__(self, *args):
- p = self.condition(args)
- return tf.contrib.distributions.Bernoulli(logits=p)
-
-
-class NormalApproximatePosterior(ConditionalNormalDistribution):
- """A Normally-distributed approx. posterior with res_q parameterization."""
-
- def __init__(self, size, hidden_layer_sizes, sigma_min=0.0,
- raw_sigma_bias=0.25, hidden_activation_fn=tf.nn.relu,
- initializers=None, smoothing=False,
- name="conditional_normal_distribution"):
- super(NormalApproximatePosterior, self).__init__(
- size, hidden_layer_sizes, sigma_min=sigma_min,
- raw_sigma_bias=raw_sigma_bias,
- hidden_activation_fn=hidden_activation_fn, initializers=initializers,
- name=name)
- self.smoothing = smoothing
-
- def condition(self, tensor_list, prior_mu, smoothing_tensors=None):
- """Generates the mean and variance of the normal distribution.
-
- Args:
- tensor_list: The list of Tensors to condition on. Will be concatenated and
- fed through a fully connected network.
- prior_mu: The mean of the prior distribution associated with this
- approximate posterior. Will be added to the mean produced by
- this approximate posterior, in res_q fashion.
- smoothing_tensors: A list of Tensors. If smoothing is True, these Tensors
- will be concatenated with the tensors in tensor_list.
- Returns:
- mu: The mean of the approximate posterior.
- sigma: The standard deviation of the approximate posterior.
- """
- if self.smoothing:
- tensor_list.extend(smoothing_tensors)
- mu, sigma = super(NormalApproximatePosterior, self).condition(tensor_list)
- return mu + prior_mu, sigma
-
-
-class NonstationaryLinearDistribution(object):
- """A set of loc-scale distributions that are linear functions of inputs.
-
- This class defines a series of location-scale distributions such that
- the means are learnable linear functions of the inputs and the log variances
- are learnable constants. The functions and log variances are different across
- timesteps, allowing the distributions to be nonstationary.
- """
-
- def __init__(self,
- num_timesteps,
- inputs_per_timestep=None,
- outputs_per_timestep=None,
- initializers=None,
- variance_min=0.0,
- output_distribution=tfd.Normal,
- dtype=tf.float32):
- """Creates a NonstationaryLinearDistribution.
-
- Args:
- num_timesteps: The number of timesteps, i.e. the number of distributions.
- inputs_per_timestep: A list of python ints, the dimension of inputs to the
- linear function at each timestep. If not provided, the dimension at each
- timestep is assumed to be 1.
- outputs_per_timestep: A list of python ints, the dimension of the output
- distribution at each timestep. If not provided, the dimension at each
- timestep is assumed to be 1.
- initializers: A dictionary containing intializers for the variables. The
- initializer under the key 'w' is used for the weights in the linear
- function and the initializer under the key 'b' is used for the biases.
- Defaults to xavier initialization for the weights and zeros for the
- biases.
- variance_min: Python float, the minimum variance of each distribution.
- output_distribution: A locatin-scale subclass of tfd.Distribution that
- defines the output distribution, e.g. Normal.
- dtype: The dtype of the weights and biases.
- """
- if not initializers:
- initializers = DEFAULT_INITIALIZERS
- if not inputs_per_timestep:
- inputs_per_timestep = [1] * num_timesteps
- if not outputs_per_timestep:
- outputs_per_timestep = [1] * num_timesteps
- self.num_timesteps = num_timesteps
- self.variance_min = variance_min
- self.initializers = initializers
- self.dtype = dtype
- self.output_distribution = output_distribution
-
- def _get_variables_ta(shapes, name, initializer, trainable=True):
- """Creates a sequence of variables and stores them in a TensorArray."""
- # Infer shape if all shapes are equal.
- first_shape = shapes[0]
- infer_shape = all(shape == first_shape for shape in shapes)
- ta = tf.TensorArray(
- dtype=dtype, size=len(shapes), dynamic_size=False,
- clear_after_read=False, infer_shape=infer_shape)
- for t, shape in enumerate(shapes):
- var = tf.get_variable(
- name % t, shape=shape, initializer=initializer, trainable=trainable)
- ta = ta.write(t, var)
- return ta
-
- bias_shapes = [[num_outputs] for num_outputs in outputs_per_timestep]
- self.log_variances = _get_variables_ta(
- bias_shapes, "proposal_log_variance_%d", initializers["b"])
- self.mean_biases = _get_variables_ta(
- bias_shapes, "proposal_b_%d", initializers["b"])
- weight_shapes = zip(inputs_per_timestep, outputs_per_timestep)
- self.mean_weights = _get_variables_ta(
- weight_shapes, "proposal_w_%d", initializers["w"])
- self.shapes = tf.TensorArray(
- dtype=tf.int32, size=num_timesteps,
- dynamic_size=False, clear_after_read=False).unstack(weight_shapes)
-
- def __call__(self, t, inputs):
- """Computes the distribution at timestep t.
-
- Args:
- t: Scalar integer Tensor, the current timestep. Must be in
- [0, num_timesteps).
- inputs: The inputs to the linear function parameterizing the mean of
- the current distribution. A Tensor of shape [batch_size, num_inputs_t].
- Returns:
- A tfd.Distribution subclass representing the distribution at timestep t.
- """
- b = self.mean_biases.read(t)
- w = self.mean_weights.read(t)
- shape = self.shapes.read(t)
- w = tf.reshape(w, shape)
- b = tf.reshape(b, [shape[1], 1])
- log_variance = self.log_variances.read(t)
- scale = tf.sqrt(tf.maximum(tf.exp(log_variance), self.variance_min))
- loc = tf.matmul(w, inputs, transpose_a=True) + b
- return self.output_distribution(loc=loc, scale=scale)
-
-
-def encode_all(inputs, encoder):
- """Encodes a timeseries of inputs with a time independent encoder.
-
- Args:
- inputs: A [time, batch, feature_dimensions] tensor.
- encoder: A network that takes a [batch, features_dimensions] input and
- encodes the input.
- Returns:
- A [time, batch, encoded_feature_dimensions] output tensor.
- """
- input_shape = tf.shape(inputs)
- num_timesteps, batch_size = input_shape[0], input_shape[1]
- reshaped_inputs = tf.reshape(inputs, [-1, inputs.shape[-1]])
- inputs_encoded = encoder(reshaped_inputs)
- inputs_encoded = tf.reshape(inputs_encoded,
- [num_timesteps, batch_size, encoder.output_size])
- return inputs_encoded
-
-
-def ta_for_tensor(x, **kwargs):
- """Creates a TensorArray for the input tensor."""
- return tf.TensorArray(
- x.dtype, tf.shape(x)[0], dynamic_size=False, **kwargs).unstack(x)
diff --git a/research/fivo/fivo/models/ghmm.py b/research/fivo/fivo/models/ghmm.py
deleted file mode 100644
index 07cf6c50e803383ef5690e8d24010e4706286eb7..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/models/ghmm.py
+++ /dev/null
@@ -1,483 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""A Gaussian hidden markov model.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-from fivo.models import base
-
-tfd = tf.contrib.distributions
-
-
-class GaussianHMM(object):
- """A hidden markov model with 1-D Gaussian latent space and observations.
-
- This is a hidden markov model where the state and observations are
- one-dimensional Gaussians. The mean of each latent state is a linear
- function of the previous latent state, and the mean of each observation
- is a linear function of the current latent state.
-
- The description that follows is 0-indexed instead of 1-indexed to make
- it easier to reason about the parameters passed to the model.
-
- The parameters of the model are:
- T: The number timesteps, latent states, and observations.
- vz_t, t=0 to T-1: The variance of the latent state at timestep t.
- vx_t, t=0 to T-1: The variance of the observation at timestep t.
- wz_t, t=1 to T-1: The weight that defines the latent transition at t.
- wx_t, t=0 to T-1: The weight that defines the observation function at t.
-
- There are T vz_t, vx_t, and wx_t but only T-1 wz_t because there are only
- T-1 transitions in the model.
-
- Given these parameters, sampling from the model is defined as
-
- z_0 ~ N(0, vz_0)
- x_0 | z_0 ~ N(wx_0 * z_0, vx_0)
- z_1 | z_0 ~ N(wz_1 * z_0, vz_1)
- x_1 | z_1 ~ N(wx_1 * z_1, vx_1)
- ...
- z_{T-1} | z_{T-2} ~ N(wz_{T-1} * z_{T-2}, vz_{T-1})
- x_{T-1} | z_{T-1} ~ N(wx_{T-1} * z_{T-1}, vx_{T-1}).
- """
-
- def __init__(self,
- num_timesteps,
- transition_variances=1.,
- emission_variances=1.,
- transition_weights=1.,
- emission_weights=1.,
- dtype=tf.float32):
- """Creates a gaussian hidden markov model.
-
- Args:
- num_timesteps: A python int, the number of timesteps in the model.
- transition_variances: The variance of p(z_t | z_t-1). Can be a scalar,
- setting all variances to be the same, or a Tensor of shape
- [num_timesteps].
- emission_variances: The variance of p(x_t | z_t). Can be a scalar,
- setting all variances to be the same, or a Tensor of shape
- [num_timesteps].
- transition_weights: The weight that defines the linear function that
- produces the mean of z_t given z_{t-1}. Can be a scalar, setting
- all weights to be the same, or a Tensor of shape [num_timesteps-1].
- emission_weights: The weight that defines the linear function that
- produces the mean of x_t given z_t. Can be a scalar, setting
- all weights to be the same, or a Tensor of shape [num_timesteps].
- dtype: The datatype of the state.
- """
- self.num_timesteps = num_timesteps
- self.dtype = dtype
-
- def _expand_param(param, size):
- param = tf.convert_to_tensor(param, dtype=self.dtype)
- if not param.get_shape().as_list():
- param = tf.tile(param[tf.newaxis], [size])
-
- return param
-
- def _ta_for_param(param):
- size = tf.shape(param)[0]
- ta = tf.TensorArray(dtype=param.dtype,
- size=size,
- dynamic_size=False,
- clear_after_read=False).unstack(param)
- return ta
-
- self.transition_variances = _ta_for_param(
- _expand_param(transition_variances, num_timesteps))
- self.transition_weights = _ta_for_param(
- _expand_param(transition_weights, num_timesteps-1))
- em_var = _expand_param(emission_variances, num_timesteps)
- self.emission_variances = _ta_for_param(em_var)
- em_w = _expand_param(emission_weights, num_timesteps)
- self.emission_weights = _ta_for_param(em_w)
- self._compute_covariances(em_w, em_var)
-
- def _compute_covariances(self, emission_weights, emission_variances):
- """Compute all covariance matrices.
-
- Computes the covaraince matrix for the latent variables, the observations,
- and the covariance between the latents and observations.
-
- Args:
- emission_weights: A Tensor of shape [num_timesteps] containing
- the emission distribution weights at each timestep.
- emission_variances: A Tensor of shape [num_timesteps] containing
- the emiision distribution variances at each timestep.
- """
- # Compute the marginal variance of each latent.
- z_variances = [self.transition_variances.read(0)]
- for i in range(1, self.num_timesteps):
- z_variances.append(
- z_variances[i-1] * tf.square(self.transition_weights.read(i-1)) +
- self.transition_variances.read(i))
- # Compute the latent covariance matrix.
- sigma_z = []
- for i in range(self.num_timesteps):
- sigma_z_row = []
- for j in range(self.num_timesteps):
- if i == j:
- sigma_z_row.append(z_variances[i])
- continue
- min_ind = min(i, j)
- max_ind = max(i, j)
- weight = tf.reduce_prod(
- self.transition_weights.gather(tf.range(min_ind, max_ind)))
- sigma_z_row.append(z_variances[min_ind] * weight)
- sigma_z.append(tf.stack(sigma_z_row))
- self.sigma_z = tf.stack(sigma_z)
- # Compute the observation covariance matrix.
- x_weights_outer = tf.einsum("i,j->ij", emission_weights, emission_weights)
- self.sigma_x = x_weights_outer * self.sigma_z + tf.diag(emission_variances)
- # Compute the latent - observation covariance matrix.
- # The first axis will index latents, the second axis will index observtions.
- self.sigma_zx = emission_weights[tf.newaxis, :] * self.sigma_z
- self.obs_dist = tfd.MultivariateNormalFullCovariance(
- loc=tf.zeros([self.num_timesteps], dtype=tf.float32),
- covariance_matrix=self.sigma_x)
-
- def transition(self, t, z_prev):
- """Compute the transition distribution p(z_t | z_t-1).
-
- Args:
- t: The current timestep, a scalar integer Tensor. When t=0 z_prev is
- mostly ignored and the distribution p(z_0) is returned. z_prev is
- 'mostly' ignored because it is still used to derive batch_size.
- z_prev: A [batch_size] set of states.
- Returns:
- p(z_t | z_t-1) as a univariate normal distribution.
- """
- batch_size = tf.shape(z_prev)[0]
- scale = tf.sqrt(self.transition_variances.read(t))
- scale = tf.tile(scale[tf.newaxis], [batch_size])
- loc = tf.cond(tf.greater(t, 0),
- lambda: self.transition_weights.read(t-1)*z_prev,
- lambda: tf.zeros_like(scale))
- return tfd.Normal(loc=loc, scale=scale)
-
- def emission(self, t, z):
- """Compute the emission distribution p(x_t | z_t).
-
- Args:
- t: The current timestep, a scalar integer Tensor.
- z: A [batch_size] set of the current states.
- Returns:
- p(x_t | z_t) as a univariate normal distribution.
- """
- batch_size = tf.shape(z)[0]
- scale = tf.sqrt(self.emission_variances.read(t))
- scale = tf.tile(scale[tf.newaxis], [batch_size])
- loc = self.emission_weights.read(t)*z
- return tfd.Normal(loc=loc, scale=scale)
-
- def filtering(self, t, z_prev, x_cur):
- """Computes the filtering distribution p(z_t | z_{t-1}, x_t).
-
- Args:
- t: A python int, the index for z_t. When t is 0, z_prev is ignored,
- giving p(z_0 | x_0).
- z_prev: z_{t-1}, the previous z to condition on. A Tensor of shape
- [batch_size].
- x_cur: x_t, the current x to condition on. A Tensor of shape [batch_size].
- Returns:
- p(z_t | z_{t-1}, x_t) as a univariate normal distribution.
- """
- z_prev = tf.convert_to_tensor(z_prev)
- x_cur = tf.convert_to_tensor(x_cur)
- batch_size = tf.shape(z_prev)[0]
- z_var = self.transition_variances.read(t)
- x_var = self.emission_variances.read(t)
- x_weight = self.emission_weights.read(t)
- prev_state_weight = x_var/(tf.square(x_weight)*z_var + x_var)
- prev_state_weight *= tf.cond(tf.greater(t, 0),
- lambda: self.transition_weights.read(t-1),
- lambda: tf.zeros_like(prev_state_weight))
- cur_obs_weight = (x_weight*z_var)/(tf.square(x_weight)*z_var + x_var)
- loc = prev_state_weight*z_prev + cur_obs_weight*x_cur
- scale = tf.sqrt((z_var*x_var)/(tf.square(x_weight)*z_var + x_var))
- scale = tf.tile(scale[tf.newaxis], [batch_size])
- return tfd.Normal(loc=loc, scale=scale)
-
- def smoothing(self, t, z_prev, xs):
- """Computes the smoothing distribution p(z_t | z_{t-1}, x_{t:num_timesteps).
-
- Args:
- t: A python int, the index for z_t. When t is 0, z_prev is ignored,
- giving p(z_0 | x_{0:num_timesteps-1}).
- z_prev: z_{t-1}, the previous z to condition on. A Tensor of shape
- [batch_size].
- xs: x_{t:num_timesteps}, the future xs to condition on. A Tensor of shape
- [num_timesteps - t, batch_size].
- Returns:
- p(z_t | z_{t-1}, x_{t:num_timesteps}) as a univariate normal distribution.
- """
- xs = tf.convert_to_tensor(xs)
- z_prev = tf.convert_to_tensor(z_prev)
- batch_size = tf.shape(xs)[1]
- mess_mean, mess_prec = tf.cond(
- tf.less(t, self.num_timesteps-1),
- lambda: tf.unstack(self._compute_backwards_messages(xs[1:]).read(0)),
- lambda: [tf.zeros([batch_size]), tf.zeros([batch_size])])
- return self._smoothing_from_message(t, z_prev, xs[0], mess_mean, mess_prec)
-
- def _smoothing_from_message(self, t, z_prev, x_t, mess_mean, mess_prec):
- """Computes the smoothing distribution given message incoming to z_t.
-
- Computes p(z_t | z_{t-1}, x_{t:num_timesteps}) given the message incoming
- to the node for z_t.
-
- Args:
- t: A python int, the index for z_t. When t is 0, z_prev is ignored.
- z_prev: z_{t-1}, the previous z to condition on. A Tensor of shape
- [batch_size].
- x_t: The observation x at timestep t.
- mess_mean: The mean of the message incoming to z_t, in information form.
- mess_prec: The precision of the message incoming to z_t.
- Returns:
- p(z_t | z_{t-1}, x_{t:num_timesteps}) as a univariate normal distribution.
- """
-
- batch_size = tf.shape(x_t)[0]
- z_var = self.transition_variances.read(t)
- x_var = self.emission_variances.read(t)
- w_x = self.emission_weights.read(t)
-
- def transition_term():
- return (tf.square(self.transition_weights.read(t))/
- self.transition_variances.read(t+1))
-
- prec = 1./z_var + tf.square(w_x)/x_var + mess_prec
- prec += tf.cond(tf.less(t, self.num_timesteps-1),
- transition_term, lambda: 0.)
- mean = x_t*(w_x/x_var) + mess_mean
- mean += tf.cond(tf.greater(t, 0),
- lambda: z_prev*(self.transition_weights.read(t-1)/z_var),
- lambda: 0.)
- mean = tf.reshape(mean / prec, [batch_size])
- scale = tf.reshape(tf.sqrt(1./prec), [batch_size])
- return tfd.Normal(loc=mean, scale=scale)
-
- def _compute_backwards_messages(self, xs):
- """Computes the backwards messages used in smoothing."""
- batch_size = tf.shape(xs)[1]
- num_xs = tf.shape(xs)[0]
- until_t = self.num_timesteps - num_xs
- xs = tf.TensorArray(dtype=xs.dtype,
- size=num_xs,
- dynamic_size=False,
- clear_after_read=True).unstack(xs)
- messages_ta = tf.TensorArray(dtype=xs.dtype,
- size=num_xs,
- dynamic_size=False,
- clear_after_read=False)
-
- def compute_message(t, prev_mean, prev_prec, messages_ta):
- """Computes one step of the backwards messages."""
- z_var = self.transition_variances.read(t)
- w_z = self.transition_weights.read(t-1)
- x_var = self.emission_variances.read(t)
- w_x = self.emission_weights.read(t)
- cur_x = xs.read(t - until_t)
-
- # If it isn't the first message, add the terms from the transition.
- def transition_term():
- return (tf.square(self.transition_weights.read(t))/
- self.transition_variances.read(t+1))
-
- unary_prec = 1/z_var + tf.square(w_x)/x_var
- unary_prec += tf.cond(tf.less(t, self.num_timesteps-1),
- transition_term, lambda: 0.)
-
- unary_mean = (w_x / x_var) * cur_x
- pairwise_prec = w_z / z_var
-
- next_prec = -tf.square(pairwise_prec)/(unary_prec + prev_prec)
- next_mean = (pairwise_prec * (unary_mean + prev_mean) /
- (unary_prec + prev_prec))
- next_prec = tf.reshape(next_prec, [batch_size])
- next_mean = tf.reshape(next_mean, [batch_size])
- messages_ta = messages_ta.write(t - until_t,
- tf.stack([next_mean, next_prec]))
- return t-1, next_mean, next_prec, messages_ta
-
- def pred(t, *unused_args):
- return tf.greater_equal(t, until_t)
-
- init_prec = tf.zeros([batch_size], dtype=xs.dtype)
- init_mean = tf.zeros([batch_size], dtype=xs.dtype)
- t0 = tf.constant(self.num_timesteps - 1, dtype=tf.int32)
-
- outs = tf.while_loop(pred, compute_message,
- (t0, init_mean, init_prec, messages_ta))
- messages = outs[-1]
- return messages
-
- def lookahead(self, t, z_prev):
- """Compute the 'lookahead' distribution, p(x_{t:T} | z_{t-1}).
-
- Args:
- t: A scalar Tensor int, the current timestep. Must be at least 1.
- z_prev: The latent state at time t-1. A Tensor of shape [batch_size].
- Returns:
- p(x_{t:T} | z_{t-1}) as a multivariate normal distribution.
- """
- z_prev = tf.convert_to_tensor(z_prev)
- sigma_zx = self.sigma_zx[t-1, t:]
- z_var = self.sigma_z[t-1, t-1]
- mean = tf.einsum("i,j->ij", z_prev, sigma_zx) / z_var
- variance = (self.sigma_x[t:, t:] -
- tf.einsum("i,j->ij", sigma_zx, sigma_zx) / z_var)
- return tfd.MultivariateNormalFullCovariance(
- loc=mean, covariance_matrix=variance)
-
- def likelihood(self, xs):
- """Compute the true marginal likelihood of the data.
-
- Args:
- xs: The observations, a [num_timesteps, batch_size] float Tensor.
- Returns:
- likelihoods: A [batch_size] float Tensor representing the likelihood of
- each sequence of observations in the batch.
- """
- return self.obs_dist.log_prob(tf.transpose(xs))
-
-
-class TrainableGaussianHMM(GaussianHMM, base.ELBOTrainableSequenceModel):
- """An interface between importance-sampling training methods and the GHMM."""
-
- def __init__(self,
- num_timesteps,
- proposal_type,
- transition_variances=1.,
- emission_variances=1.,
- transition_weights=1.,
- emission_weights=1.,
- random_seed=None,
- dtype=tf.float32):
- """Constructs a trainable Gaussian HMM.
-
- Args:
- num_timesteps: A python int, the number of timesteps in the model.
- proposal_type: The type of proposal to use in the importance sampling
- setup. Could be "filtering", "smoothing", "prior", "true-filtering",
- or "true-smoothing". If "true-filtering" or "true-smoothing" are
- selected, then the true filtering or smoothing distributions are used to
- propose new states. If "learned-filtering" is selected then a
- distribution with learnable parameters is used. Specifically at each
- timestep the proposal is Gaussian with mean that is a learnable linear
- function of the previous state and current observation. The log variance
- is a per-timestep learnable constant. "learned-smoothing" is similar,
- but the mean is a learnable linear function of the previous state and
- all future observations. Note that this proposal class includes the true
- posterior. If "prior" is selected then states are proposed from the
- model's prior.
- transition_variances: The variance of p(z_t | z_t-1). Can be a scalar,
- setting all variances to be the same, or a Tensor of shape
- [num_timesteps].
- emission_variances: The variance of p(x_t | z_t). Can be a scalar,
- setting all variances to be the same, or a Tensor of shape
- [num_timesteps].
- transition_weights: The weight that defines the linear function that
- produces the mean of z_t given z_{t-1}. Can be a scalar, setting
- all weights to be the same, or a Tensor of shape [num_timesteps-1].
- emission_weights: The weight that defines the linear function that
- produces the mean of x_t given z_t. Can be a scalar, setting
- all weights to be the same, or a Tensor of shape [num_timesteps].
- random_seed: A seed for the proposal sampling, mainly useful for testing.
- dtype: The datatype of the state.
- """
- super(TrainableGaussianHMM, self).__init__(
- num_timesteps, transition_variances, emission_variances,
- transition_weights, emission_weights, dtype=dtype)
- self.random_seed = random_seed
- assert proposal_type in ["filtering", "smoothing", "prior",
- "true-filtering", "true-smoothing"]
- if proposal_type == "true-filtering":
- self.proposal = self._filtering_proposal
- elif proposal_type == "true-smoothing":
- self.proposal = self._smoothing_proposal
- elif proposal_type == "prior":
- self.proposal = self.transition
- elif proposal_type == "filtering":
- self._learned_proposal_fn = base.NonstationaryLinearDistribution(
- num_timesteps, inputs_per_timestep=[1] + [2] * (num_timesteps-1))
- self.proposal = self._learned_filtering_proposal
- elif proposal_type == "smoothing":
- inputs_per_timestep = [num_timesteps] + [num_timesteps - t
- for t in range(num_timesteps-1)]
- self._learned_proposal_fn = base.NonstationaryLinearDistribution(
- num_timesteps, inputs_per_timestep=inputs_per_timestep)
- self.proposal = self._learned_smoothing_proposal
-
- def set_observations(self, xs, seq_lengths):
- """Sets the observations and stores the backwards messages."""
- # Squeeze out data dimension since everything is 1-d.
- xs = tf.squeeze(xs)
- self.batch_size = tf.shape(xs)[1]
- super(TrainableGaussianHMM, self).set_observations(xs, seq_lengths)
- self.messages = self._compute_backwards_messages(xs[1:])
-
- def zero_state(self, batch_size, dtype):
- return tf.zeros([batch_size], dtype=dtype)
-
- def propose_and_weight(self, state, t):
- """Computes the next state and log weights for the GHMM."""
- state_shape = tf.shape(state)
- xt = self.observations[t]
- p_zt = self.transition(t, state)
- q_zt = self.proposal(t, state)
- zt = q_zt.sample(seed=self.random_seed)
- zt = tf.reshape(zt, state_shape)
- p_xt_given_zt = self.emission(t, zt)
- log_p_zt = p_zt.log_prob(zt)
- log_q_zt = q_zt.log_prob(zt)
- log_p_xt_given_zt = p_xt_given_zt.log_prob(xt)
- weight = log_p_zt + log_p_xt_given_zt - log_q_zt
- return weight, zt
-
- def _filtering_proposal(self, t, state):
- """Uses the stored observations to compute the filtering distribution."""
- cur_x = self.observations[t]
- return self.filtering(t, state, cur_x)
-
- def _smoothing_proposal(self, t, state):
- """Uses the stored messages to compute the smoothing distribution."""
- mess_mean, mess_prec = tf.cond(
- tf.less(t, self.num_timesteps-1),
- lambda: tf.unstack(self.messages.read(t)),
- lambda: [tf.zeros([self.batch_size]), tf.zeros([self.batch_size])])
- return self._smoothing_from_message(t, state, self.observations[t],
- mess_mean, mess_prec)
-
- def _learned_filtering_proposal(self, t, state):
- cur_x = self.observations[t]
- inputs = tf.cond(tf.greater(t, 0),
- lambda: tf.stack([state, cur_x], axis=0),
- lambda: cur_x[tf.newaxis, :])
- return self._learned_proposal_fn(t, inputs)
-
- def _learned_smoothing_proposal(self, t, state):
- xs = self.observations_ta.gather(tf.range(t, self.num_timesteps))
- inputs = tf.cond(tf.greater(t, 0),
- lambda: tf.concat([state[tf.newaxis, :], xs], axis=0),
- lambda: xs)
- return self._learned_proposal_fn(t, inputs)
diff --git a/research/fivo/fivo/models/ghmm_test.py b/research/fivo/fivo/models/ghmm_test.py
deleted file mode 100644
index 15a03c0c7abeae09bd1cfc87f917ef53ecac205f..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/models/ghmm_test.py
+++ /dev/null
@@ -1,313 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests for fivo.models.ghmm"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import tensorflow as tf
-
-from fivo.models.ghmm import GaussianHMM
-from fivo.models.ghmm import TrainableGaussianHMM
-
-
-class GHMMTest(tf.test.TestCase):
-
- def test_transition_no_weights(self):
- with self.test_session() as sess:
- ghmm = GaussianHMM(3,
- transition_variances=[1., 2., 3.])
- prev_z = tf.constant([1., 2.], dtype=tf.float32)
- z0 = ghmm.transition(0, prev_z)
- z1 = ghmm.transition(1, prev_z)
- z2 = ghmm.transition(2, prev_z)
- outs = sess.run([z0.mean(), z0.variance(),
- z1.mean(), z1.variance(),
- z2.mean(), z2.variance()])
- self.assertAllClose(outs, [[0., 0.], [1., 1.],
- [1., 2.], [2., 2.],
- [1., 2.], [3., 3.]])
-
- def test_transition_with_weights(self):
- with self.test_session() as sess:
- ghmm = GaussianHMM(3,
- transition_variances=[1., 2., 3.],
- transition_weights=[2., 3.])
- prev_z = tf.constant([1., 2.], dtype=tf.float32)
- z0 = ghmm.transition(0, prev_z)
- z1 = ghmm.transition(1, prev_z)
- z2 = ghmm.transition(2, prev_z)
- outs = sess.run([z0.mean(), z0.variance(),
- z1.mean(), z1.variance(),
- z2.mean(), z2.variance()])
- self.assertAllClose(outs, [[0., 0.], [1., 1.],
- [2., 4.], [2., 2.],
- [3., 6.], [3., 3.]])
-
- def test_emission_no_weights(self):
- with self.test_session() as sess:
- ghmm = GaussianHMM(3, emission_variances=[1., 2., 3.])
- z = tf.constant([1., 2.], dtype=tf.float32)
- x0 = ghmm.emission(0, z)
- x1 = ghmm.emission(1, z)
- x2 = ghmm.emission(2, z)
- outs = sess.run([x0.mean(), x0.variance(),
- x1.mean(), x1.variance(),
- x2.mean(), x2.variance()])
- self.assertAllClose(outs, [[1., 2.], [1., 1.],
- [1., 2.], [2., 2.],
- [1., 2.], [3., 3.]])
-
- def test_emission_with_weights(self):
- with self.test_session() as sess:
- ghmm = GaussianHMM(3,
- emission_variances=[1., 2., 3.],
- emission_weights=[1., 2., 3.])
- z = tf.constant([1., 2.], dtype=tf.float32)
- x0 = ghmm.emission(0, z)
- x1 = ghmm.emission(1, z)
- x2 = ghmm.emission(2, z)
- outs = sess.run([x0.mean(), x0.variance(),
- x1.mean(), x1.variance(),
- x2.mean(), x2.variance()])
- self.assertAllClose(outs, [[1., 2.], [1., 1.],
- [2., 4.], [2., 2.],
- [3., 6.], [3., 3.]])
-
- def test_filtering_no_weights(self):
- with self.test_session() as sess:
- ghmm = GaussianHMM(3,
- transition_variances=[1., 2., 3.],
- emission_variances=[4., 5., 6.])
- z_prev = tf.constant([1., 2.], dtype=tf.float32)
- x_cur = tf.constant([3., 4.], dtype=tf.float32)
- expected_outs = [[[3./5., 4./5.], [4./5., 4./5.]],
- [[11./7., 18./7.], [10./7., 10./7.]],
- [[5./3., 8./3.], [2., 2.]]]
- f_post_0 = ghmm.filtering(0, z_prev, x_cur)
- f_post_1 = ghmm.filtering(1, z_prev, x_cur)
- f_post_2 = ghmm.filtering(2, z_prev, x_cur)
- outs = sess.run([[f_post_0.mean(), f_post_0.variance()],
- [f_post_1.mean(), f_post_1.variance()],
- [f_post_2.mean(), f_post_2.variance()]])
- self.assertAllClose(expected_outs, outs)
-
- def test_filtering_with_weights(self):
- with self.test_session() as sess:
- ghmm = GaussianHMM(3,
- transition_variances=[1., 2., 3.],
- emission_variances=[4., 5., 6.],
- transition_weights=[7., 8.],
- emission_weights=[9., 10., 11])
- z_prev = tf.constant([1., 2.], dtype=tf.float32)
- x_cur = tf.constant([3., 4.], dtype=tf.float32)
- expected_outs = [[[27./85., 36./85.], [4./85., 4./85.]],
- [[95./205., 150./205.], [10./205., 10./205.]],
- [[147./369., 228./369.], [18./369., 18./369.]]]
- f_post_0 = ghmm.filtering(0, z_prev, x_cur)
- f_post_1 = ghmm.filtering(1, z_prev, x_cur)
- f_post_2 = ghmm.filtering(2, z_prev, x_cur)
- outs = sess.run([[f_post_0.mean(), f_post_0.variance()],
- [f_post_1.mean(), f_post_1.variance()],
- [f_post_2.mean(), f_post_2.variance()]])
- self.assertAllClose(expected_outs, outs)
-
- def test_smoothing(self):
- with self.test_session() as sess:
- ghmm = GaussianHMM(3,
- transition_variances=[1., 2., 3.],
- emission_variances=[4., 5., 6.])
- z_prev = tf.constant([1., 2.], dtype=tf.float32)
- xs = tf.constant([[1., 2.],
- [3., 4.],
- [5., 6.]], dtype=tf.float32)
- s_post1 = ghmm.smoothing(0, z_prev, xs)
- outs = sess.run([s_post1.mean(), s_post1.variance()])
- expected_outs = [[281./421., 410./421.], [292./421., 292./421.]]
- self.assertAllClose(expected_outs, outs)
-
- expected_outs = [[149./73., 222./73.], [90./73., 90./73.]]
- s_post2 = ghmm.smoothing(1, z_prev, xs[1:])
- outs = sess.run([s_post2.mean(), s_post2.variance()])
- self.assertAllClose(expected_outs, outs)
-
- s_post3 = ghmm.smoothing(2, z_prev, xs[2:])
- outs = sess.run([s_post3.mean(), s_post3.variance()])
- expected_outs = [[7./3., 10./3.], [2., 2.]]
- self.assertAllClose(expected_outs, outs)
-
- def test_smoothing_with_weights(self):
- with self.test_session() as sess:
- x_weight = np.array([4, 5, 6, 7], dtype=np.float32)
- sigma_x = np.array([5, 6, 7, 8], dtype=np.float32)
- z_weight = np.array([1, 2, 3], dtype=np.float32)
- sigma_z = np.array([1, 2, 3, 4], dtype=np.float32)
- z_prev = np.array([1, 2], dtype=np.float32)
- batch_size = 2
- xs = np.array([[1, 2], [3, 4], [5, 6], [7, 8]], dtype=np.float32)
-
- z_cov, x_cov, z_x_cov = self._compute_covariance_matrices(
- x_weight, z_weight, sigma_x, sigma_z)
-
- expected_outs = []
- # Compute mean and variance for z_0 when we don't condition
- # on previous zs.
- sigma_12 = z_x_cov[0, :]
- sigma_12_22 = np.dot(sigma_12, np.linalg.inv(x_cov))
- mean = np.dot(sigma_12_22, xs)
- variance = np.squeeze(z_cov[0, 0] - np.dot(sigma_12_22, sigma_12))
- expected_outs.append([mean, np.tile(variance, [batch_size])])
-
- # Compute mean and variance for remaining z_ts.
- for t in xrange(1, 4):
- sigma_12 = np.concatenate([[z_cov[t, t - 1]], z_x_cov[t, t:]])
- sigma_22 = np.vstack((
- np.hstack((z_cov[t-1, t-1], z_x_cov[t-1, t:])),
- np.hstack((np.transpose([z_x_cov[t-1, t:]]), x_cov[t:, t:]))
- ))
- sigma_12_22 = np.dot(sigma_12, np.linalg.inv(sigma_22))
- mean = np.dot(sigma_12_22, np.vstack((z_prev, xs[t:])))
- variance = np.squeeze(z_cov[t, t] - np.dot(sigma_12_22, sigma_12))
- expected_outs.append([mean, np.tile(variance, [batch_size])])
-
- ghmm = GaussianHMM(4,
- transition_variances=sigma_z,
- emission_variances=sigma_x,
- transition_weights=z_weight,
- emission_weights=x_weight)
- out_dists = [ghmm.smoothing(t, z_prev, xs[t:]) for t in range(0, 4)]
- outs = [[d.mean(), d.variance()] for d in out_dists]
- run_outs = sess.run(outs)
- self.assertAllClose(expected_outs, run_outs)
-
- def test_covariance_matrices(self):
- with self.test_session() as sess:
- x_weight = np.array([4, 5, 6, 7], dtype=np.float32)
- sigma_x = np.array([5, 6, 7, 8], dtype=np.float32)
- z_weight = np.array([1, 2, 3], dtype=np.float32)
- sigma_z = np.array([1, 2, 3, 4], dtype=np.float32)
-
- z_cov, x_cov, z_x_cov = self._compute_covariance_matrices(
- x_weight, z_weight, sigma_x, sigma_z)
-
- ghmm = GaussianHMM(4,
- transition_variances=sigma_z,
- emission_variances=sigma_x,
- transition_weights=z_weight,
- emission_weights=x_weight)
- self.assertAllClose(z_cov, sess.run(ghmm.sigma_z))
- self.assertAllClose(x_cov, sess.run(ghmm.sigma_x))
- self.assertAllClose(z_x_cov, sess.run(ghmm.sigma_zx))
-
- def _compute_covariance_matrices(self, x_weight, z_weight, sigma_x, sigma_z):
- # Create z covariance matrix from the definitions.
- z_cov = np.zeros([4, 4])
- z_cov[0, 0] = sigma_z[0]
- for i in range(1, 4):
- z_cov[i, i] = (z_cov[i - 1, i - 1] * np.square(z_weight[i - 1]) +
- sigma_z[i])
- for i in range(4):
- for j in range(4):
- if i == j: continue
- min_ind = min(i, j)
- max_ind = max(i, j)
- weights = np.prod(z_weight[min_ind:max_ind])
- z_cov[i, j] = z_cov[min_ind, min_ind] * weights
- # Compute the x covariance matrix and the z-x covariance matrix.
- x_weights_outer = np.outer(x_weight, x_weight)
- x_cov = x_weights_outer * z_cov + np.diag(sigma_x)
- z_x_cov = x_weight * z_cov
- return z_cov, x_cov, z_x_cov
-
- def test_lookahead(self):
- x_weight = np.array([4, 5, 6, 7], dtype=np.float32)
- sigma_x = np.array([5, 6, 7, 8], dtype=np.float32)
- z_weight = np.array([1, 2, 3], dtype=np.float32)
- sigma_z = np.array([1, 2, 3, 4], dtype=np.float32)
- z_prev = np.array([1, 2], dtype=np.float32)
-
- with self.test_session() as sess:
- z_cov, x_cov, z_x_cov = self._compute_covariance_matrices(
- x_weight, z_weight, sigma_x, sigma_z)
-
- expected_outs = []
- for t in range(1, 4):
- sigma_12 = z_x_cov[t-1, t:]
- z_var = z_cov[t-1, t-1]
- mean = np.outer(z_prev, sigma_12/z_var)
- variance = x_cov[t:, t:] - np.outer(sigma_12, sigma_12)/ z_var
- expected_outs.append([mean, variance])
-
- ghmm = GaussianHMM(4,
- transition_variances=sigma_z,
- emission_variances=sigma_x,
- transition_weights=z_weight,
- emission_weights=x_weight)
- out_dists = [ghmm.lookahead(t, z_prev) for t in range(1, 4)]
- outs = [[d.mean(), d.covariance()] for d in out_dists]
- run_outs = sess.run(outs)
- self.assertAllClose(expected_outs, run_outs)
-
-
-class TrainableGHMMTest(tf.test.TestCase):
-
- def test_filtering_proposal(self):
- """Check that stashing the xs doesn't change the filtering distributions."""
- with self.test_session() as sess:
- ghmm = TrainableGaussianHMM(
- 3, "filtering",
- transition_variances=[1., 2., 3.],
- emission_variances=[4., 5., 6.],
- transition_weights=[7., 8.],
- emission_weights=[9., 10., 11])
- observations = tf.constant([[3., 4.],
- [3., 4.],
- [3., 4.]], dtype=tf.float32)
- ghmm.set_observations(observations, [3, 3])
- z_prev = tf.constant([1., 2.], dtype=tf.float32)
-
- proposals = [ghmm._filtering_proposal(t, z_prev) for t in range(3)]
- dist_params = [[p.mean(), p.variance()] for p in proposals]
-
- expected_outs = [[[27./85., 36./85.], [4./85., 4./85.]],
- [[95./205., 150./205.], [10./205., 10./205.]],
- [[147./369., 228./369.], [18./369., 18./369.]]]
- self.assertAllClose(expected_outs, sess.run(dist_params))
-
- def test_smoothing_proposal(self):
- with self.test_session() as sess:
- ghmm = TrainableGaussianHMM(
- 3, "smoothing",
- transition_variances=[1., 2., 3.],
- emission_variances=[4., 5., 6.])
- xs = tf.constant([[1., 2.],
- [3., 4.],
- [5., 6.]], dtype=tf.float32)
- ghmm.set_observations(xs, [3, 3])
- z_prev = tf.constant([1., 2.], dtype=tf.float32)
-
- proposals = [ghmm._smoothing_proposal(t, z_prev) for t in range(3)]
- dist_params = [[p.mean(), p.variance()] for p in proposals]
-
- expected_outs = [[[281./421., 410./421.], [292./421., 292./421.]],
- [[149./73., 222./73.], [90./73., 90./73.]],
- [[7./3., 10./3.], [2., 2.]]]
- self.assertAllClose(expected_outs, sess.run(dist_params))
-
-if __name__ == "__main__":
- tf.test.main()
diff --git a/research/fivo/fivo/models/srnn.py b/research/fivo/fivo/models/srnn.py
deleted file mode 100644
index cdfb560eedffccf8edf41dbab4e85bbd8bbfab46..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/models/srnn.py
+++ /dev/null
@@ -1,587 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""SRNN classes."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from collections import namedtuple
-import functools
-
-import sonnet as snt
-import tensorflow as tf
-
-from fivo.models import base
-
-
-SRNNState = namedtuple("SRNNState", "rnn_state latent_encoded")
-
-
-class SRNN(object):
- """Implementation of a Stochastic Recurrent Neural Network (SRNN).
-
- Introduced in "Sequential Neural Models with Stochastic Layers"
- by Fraccaro et al. https://arxiv.org/pdf/1605.07571.pdf.
-
- The SRNN is a sequence model similar to an RNN that uses stochastic latent
- variables to improve its representational power. It can be thought of as a
- sequential analogue to the variational auto-encoder (VAE).
-
- The SRNN has a deterministic RNN as its backbone, represented by the
- sequence of RNN hidden states h_t. The latent state is conditioned on
- the deterministic RNN states and previous latent state. Unlike the VRNN, the
- the RNN state is not conditioned on the previous latent state. The latent
- states have a Markov structure and it is assumed that
- p(z_t | z_{1:t-1}) = p(z_t | z_{t-1}).
-
- In this implementation of the SRNN the latent state z_t is Gaussian. The
- model's prior over z_t (also called the transition distribution) is
- distributed as Normal(mu_t, diag(sigma_t^2)) where mu_t and sigma_t are the
- mean and standard deviation output from a fully connected network that accepts
- the rnn hidden state h_t and previous latent state z_{t-1} as input.
-
- The emission distribution p(x_t|z_t, h_t) is conditioned on the latent state
- z_t as well as the current RNN hidden state h_t via a fully connected network.
-
- To increase the modeling power of the SRNN, two additional networks are
- used to extract features from the data and the latent state. Those networks
- are called data_encoder and latent_encoder respectively.
-
- For an example of how to call the SRNN's methods see sample_step.
-
- There are a few differences between this exposition and the paper. The main
- goal was to be consistent with the VRNN code. A few components are renamed.
- The backward RNN for approximating the posterior, g_phi_a in the paper, is the
- rev_rnn_cell. The forward RNN that conditions the latent distribution, d in
- the paper, is the rnn_cell. The paper doesn't name the NN's that serve as
- feature extractors, and we name them here as the data_encoder and
- latent_encoder.
- """
-
- def __init__(self,
- rnn_cell,
- data_encoder,
- latent_encoder,
- transition,
- emission,
- random_seed=None):
- """Create a SRNN.
-
- Args:
- rnn_cell: A subclass of tf.nn.rnn_cell.RNNCell that will form the
- deterministic backbone of the SRNN. The inputs to the RNN will be the
- the encoded input of the current timestep, a Tensor of shape
- [batch_size, encoded_data_size].
- data_encoder: A callable that accepts a batch of data x_t and
- 'encodes' it, e.g. runs it through a fully connected network. Must
- accept as argument the inputs x_t, a Tensor of the shape
- [batch_size, data_size] and return a Tensor of shape
- [batch_size, encoded_data_size]. This callable will be called multiple
- times in the SRNN cell so if scoping is not handled correctly then
- multiple copies of the variables in this network could be made. It is
- recommended to use a snt.nets.MLP module, which takes care of this for
- you.
- latent_encoder: A callable that accepts a latent state z_t and
- 'encodes' it, e.g. runs it through a fully connected network. Must
- accept as argument a Tensor of shape [batch_size, latent_size] and
- return a Tensor of shape [batch_size, encoded_latent_size].
- This callable must also have the property 'output_size' defined,
- returning encoded_latent_size.
- transition: A callable that implements the transition distribution
- p(z_t|h_t, z_t-1). Must accept as argument the previous RNN hidden state
- and previous encoded latent state then return a tf.distributions.Normal
- distribution conditioned on the input.
- emission: A callable that implements the emission distribution
- p(x_t|z_t, h_t). Must accept as arguments the encoded latent state
- and the RNN hidden state and return a subclass of
- tf.distributions.Distribution that can be used to evaluate the logprob
- of the targets.
- random_seed: The seed for the random ops. Sets the seed for sample_step.
- """
- self.random_seed = random_seed
- self.rnn_cell = rnn_cell
- self.data_encoder = data_encoder
- self.latent_encoder = latent_encoder
- self.encoded_z_size = latent_encoder.output_size
- self.state_size = (self.rnn_cell.state_size)
- self._transition = transition
- self._emission = emission
-
- def zero_state(self, batch_size, dtype):
- """The initial state of the SRNN.
-
- Contains the initial state of the RNN and the inital encoded latent.
-
- Args:
- batch_size: The batch size.
- dtype: The data type of the SRNN.
- Returns:
- zero_state: The initial state of the SRNN.
- """
- return SRNNState(
- rnn_state=self.rnn_cell.zero_state(batch_size, dtype),
- latent_encoded=tf.zeros(
- [batch_size, self.latent_encoder.output_size], dtype=dtype))
-
- def run_rnn(self, prev_rnn_state, inputs):
- """Runs the deterministic RNN for one step.
-
- Args:
- prev_rnn_state: The state of the RNN from the previous timestep.
- inputs: A Tensor of shape [batch_size, data_size], the current inputs to
- the model. Most often this is x_{t-1}, the previous token in the
- observation sequence.
- Returns:
- rnn_out: The output of the RNN.
- rnn_state: The new state of the RNN.
- """
- rnn_inputs = self.data_encoder(tf.to_float(inputs))
- rnn_out, rnn_state = self.rnn_cell(rnn_inputs, prev_rnn_state)
- return rnn_out, rnn_state
-
- def transition(self, rnn_out, prev_latent_encoded):
- """Computes the transition distribution p(z_t|h_t, z_{t-1}).
-
- Note that p(z_t | h_t, z_{t-1}) = p(z_t| z_{t-1}, x_{1:t-1})
-
- Args:
- rnn_out: The output of the rnn for the current timestep.
- prev_latent_encoded: Float Tensor of shape
- [batch_size, encoded_latent_size], the previous latent state z_{t-1}
- run through latent_encoder.
- Returns:
- p(z_t | h_t): A normal distribution with event shape
- [batch_size, latent_size].
- """
- return self._transition(rnn_out, prev_latent_encoded)
-
- def emission(self, latent, rnn_out):
- """Computes the emission distribution p(x_t | z_t, h_t).
-
- Note that p(x_t | z_t, h_t) = p(x_t | z_t, x_{1:t-1})
-
- Args:
- latent: The stochastic latent state z_t.
- rnn_out: The output of the rnn for the current timestep.
- Returns:
- p(x_t | z_t, h_t): A distribution with event shape
- [batch_size, data_size].
- latent_encoded: The latent state encoded with latent_encoder. Should be
- passed to transition() on the next timestep.
- """
- latent_encoded = self.latent_encoder(latent)
- return self._emission(latent_encoded, rnn_out), latent_encoded
-
- def sample_step(self, prev_state, inputs, unused_t):
- """Samples one output from the model.
-
- Args:
- prev_state: The previous state of the model, a SRNNState containing the
- previous rnn state and the previous encoded latent.
- inputs: A Tensor of shape [batch_size, data_size], the current inputs to
- the model. Most often this is x_{t-1}, the previous token in the
- observation sequence.
- unused_t: The current timestep. Not used currently.
- Returns:
- new_state: The next state of the model, a SRNNState.
- xt: A float Tensor of shape [batch_size, data_size], an output sampled
- from the emission distribution.
- """
- rnn_out, rnn_state = self.run_rnn(prev_state.rnn_state,
- inputs)
- p_zt = self.transition(rnn_out, prev_state.latent_encoded)
- zt = p_zt.sample(seed=self.random_seed)
- p_xt_given_zt, latent_encoded = self.emission(zt, rnn_out)
- xt = p_xt_given_zt.sample(seed=self.random_seed)
- new_state = SRNNState(rnn_state=rnn_state, latent_encoded=latent_encoded)
- return new_state, tf.to_float(xt)
-
-# pylint: disable=invalid-name
-# pylint thinks this is a top-level constant.
-TrainableSRNNState = namedtuple("TrainableSRNNState",
- SRNNState._fields + ("rnn_out",))
-# pylint: enable=g-invalid-name
-
-
-class TrainableSRNN(SRNN, base.ELBOTrainableSequenceModel):
- """A SRNN subclass with proposals and methods for training and evaluation.
-
- This class adds proposals used for training with importance-sampling based
- methods such as the ELBO. The model can be configured to propose from one
- of three proposals: a learned filtering proposal, a learned smoothing
- proposal, or the prior (i.e. the transition distribution).
-
- As described in the SRNN paper, the learned filtering proposal is
- parameterized by a fully connected neural network that accepts as input the
- current target x_t and the current rnn output h_t. The learned smoothing
- proposal is also given the hidden state of an RNN run in reverse over the
- inputs, so as to incorporate information about future observations.
-
- All learned proposals use the 'res_q' parameterization, meaning that instead
- of directly producing the mean of z_t, the proposal network predicts the
- 'residual' from the prior's mean. This is explored more in section 3.3 of
- https://arxiv.org/pdf/1605.07571.pdf.
-
- During training, the latent state z_t is sampled from the proposal and the
- reparameterization trick is used to provide low-variance gradients.
-
- Note that the SRNN paper refers to the proposals as the approximate posterior,
- but we match the VRNN convention of referring to it as the encoder.
- """
-
- def __init__(self,
- rnn_cell,
- data_encoder,
- latent_encoder,
- transition,
- emission,
- proposal_type,
- proposal=None,
- rev_rnn_cell=None,
- tilt=None,
- random_seed=None):
- """Create a trainable RNN.
-
- Args:
- rnn_cell: A subclass of tf.nn.rnn_cell.RNNCell that will form the
- deterministic backbone of the SRNN. The inputs to the RNN will be the
- the encoded input of the current timestep, a Tensor of shape
- [batch_size, encoded_data_size].
- data_encoder: A callable that accepts a batch of data x_t and
- 'encodes' it, e.g. runs it through a fully connected network. Must
- accept as argument the inputs x_t, a Tensor of the shape
- [batch_size, data_size] and return a Tensor of shape
- [batch_size, encoded_data_size]. This callable will be called multiple
- times in the SRNN cell so if scoping is not handled correctly then
- multiple copies of the variables in this network could be made. It is
- recommended to use a snt.nets.MLP module, which takes care of this for
- you.
- latent_encoder: A callable that accepts a latent state z_t and
- 'encodes' it, e.g. runs it through a fully connected network. Must
- accept as argument a Tensor of shape [batch_size, latent_size] and
- return a Tensor of shape [batch_size, encoded_latent_size].
- This callable must also have the property 'output_size' defined,
- returning encoded_latent_size.
- transition: A callable that implements the transition distribution
- p(z_t|h_t, z_t-1). Must accept as argument the previous RNN hidden state
- and previous encoded latent state then return a tf.distributions.Normal
- distribution conditioned on the input.
- emission: A callable that implements the emission distribution
- p(x_t|z_t, h_t). Must accept as arguments the encoded latent state
- and the RNN hidden state and return a subclass of
- tf.distributions.Distribution that can be used to evaluate the logprob
- of the targets.
- proposal_type: A string indicating the type of proposal to use. Can
- be either "filtering", "smoothing", or "prior". When proposal_type is
- "filtering" or "smoothing", proposal must be provided. When
- proposal_type is "smoothing", rev_rnn_cell must also be provided.
- proposal: A callable that implements the proposal q(z_t| h_t, x_{1:T}).
- If proposal_type is "filtering" then proposal must accept as arguments
- the current rnn output, the encoded target of the current timestep,
- and the mean of the prior. If proposal_type is "smoothing" then
- in addition to the current rnn output and the mean of the prior
- proposal must accept as arguments the output of the reverse rnn.
- proposal should return a tf.distributions.Normal distribution
- conditioned on its inputs. If proposal_type is "prior" this argument is
- ignored.
- rev_rnn_cell: A subclass of tf.nn.rnn_cell.RNNCell that will aggregate
- forward rnn outputs in the reverse direction. The inputs to the RNN
- will be the encoded reverse input of the current timestep, a Tensor of
- shape [batch_size, encoded_data_size].
- tilt: A callable that implements the log of a positive tilting function
- (ideally approximating log p(x_{t+1}|z_t, h_t). Must accept as arguments
- the encoded latent state and the RNN hidden state and return a subclass
- of tf.distributions.Distribution that can be used to evaluate the
- logprob of x_{t+1}. Optionally, None and then no tilt is used.
- random_seed: The seed for the random ops. Sets the seed for sample_step
- and __call__.
- """
- super(TrainableSRNN, self).__init__(
- rnn_cell, data_encoder, latent_encoder,
- transition, emission, random_seed=random_seed)
- self.rev_rnn_cell = rev_rnn_cell
- self._tilt = tilt
- assert proposal_type in ["filtering", "smoothing", "prior"]
- self._proposal = proposal
- self.proposal_type = proposal_type
- if proposal_type != "prior":
- assert proposal, "If not proposing from the prior, must provide proposal."
- if proposal_type == "smoothing":
- assert rev_rnn_cell, "Must provide rev_rnn_cell for smoothing proposal."
-
- def zero_state(self, batch_size, dtype):
- super_state = super(TrainableSRNN, self).zero_state(batch_size, dtype)
- return TrainableSRNNState(
- rnn_out=tf.zeros([batch_size, self.rnn_cell.output_size], dtype=dtype),
- **super_state._asdict())
-
- def set_observations(self, observations, seq_lengths):
- """Stores the model's observations.
-
- Stores the observations (inputs and targets) in TensorArrays and precomputes
- things for later like the reverse RNN output and encoded targets.
-
- Args:
- observations: The observations of the model, a tuple containing two
- Tensors of shape [max_seq_len, batch_size, data_size]. The Tensors
- should be the inputs and targets, respectively.
- seq_lengths: An int Tensor of shape [batch_size] containing the length
- of each sequence in observations.
- """
- inputs, targets = observations
- self.seq_lengths = seq_lengths
- self.max_seq_len = tf.reduce_max(seq_lengths)
- self.targets_ta = base.ta_for_tensor(targets, clear_after_read=False)
- targets_encoded = base.encode_all(targets, self.data_encoder)
- self.targets_encoded_ta = base.ta_for_tensor(targets_encoded,
- clear_after_read=False)
- inputs_encoded = base.encode_all(inputs, self.data_encoder)
- rnn_out, _ = tf.nn.dynamic_rnn(self.rnn_cell,
- inputs_encoded,
- time_major=True,
- dtype=tf.float32,
- scope="forward_rnn")
- self.rnn_ta = base.ta_for_tensor(rnn_out,
- clear_after_read=False)
- if self.rev_rnn_cell:
- targets_and_rnn_out = tf.concat([rnn_out, targets_encoded], 2)
- reversed_targets_and_rnn_out = tf.reverse_sequence(
- targets_and_rnn_out, seq_lengths, seq_axis=0, batch_axis=1)
- # Compute the reverse rnn over the targets.
- reverse_rnn_out, _ = tf.nn.dynamic_rnn(self.rev_rnn_cell,
- reversed_targets_and_rnn_out,
- time_major=True,
- dtype=tf.float32,
- scope="reverse_rnn")
- reverse_rnn_out = tf.reverse_sequence(reverse_rnn_out, seq_lengths,
- seq_axis=0, batch_axis=1)
- self.reverse_rnn_ta = base.ta_for_tensor(reverse_rnn_out,
- clear_after_read=False)
-
- def _filtering_proposal(self, rnn_out, prev_latent_encoded, prior, t):
- """Computes the filtering proposal distribution."""
- return self._proposal(rnn_out,
- prev_latent_encoded,
- self.targets_encoded_ta.read(t),
- prior_mu=prior.mean())
-
- def _smoothing_proposal(self, rnn_out, prev_latent_encoded, prior, t):
- """Computes the smoothing proposal distribution."""
- return self._proposal(rnn_out,
- prev_latent_encoded,
- smoothing_tensors=[self.reverse_rnn_ta.read(t)],
- prior_mu=prior.mean())
-
- def proposal(self, rnn_out, prev_latent_encoded, prior, t):
- """Computes the proposal distribution specified by proposal_type.
-
- Args:
- rnn_out: The output of the rnn for the current timestep.
- prev_latent_encoded: Float Tensor of shape
- [batch_size, encoded_latent_size], the previous latent state z_{t-1}
- run through latent_encoder.
- prior: A tf.distributions.Normal distribution representing the prior
- over z_t, p(z_t | z_{1:t-1}, x_{1:t-1}). Used for 'res_q'.
- t: A scalar int Tensor, the current timestep.
- """
- if self.proposal_type == "filtering":
- return self._filtering_proposal(rnn_out, prev_latent_encoded, prior, t)
- elif self.proposal_type == "smoothing":
- return self._smoothing_proposal(rnn_out, prev_latent_encoded, prior, t)
- elif self.proposal_type == "prior":
- return self.transition(rnn_out, prev_latent_encoded)
-
- def tilt(self, rnn_out, latent_encoded, targets):
- r_func = self._tilt(rnn_out, latent_encoded)
- return tf.reduce_sum(r_func.log_prob(targets), axis=-1)
-
- def propose_and_weight(self, state, t):
- """Runs the model and computes importance weights for one timestep.
-
- Runs the model and computes importance weights, sampling from the proposal
- instead of the transition/prior.
-
- Args:
- state: The previous state of the model, a TrainableSRNNState containing
- the previous rnn state, the previous rnn outs, and the previous encoded
- latent.
- t: A scalar integer Tensor, the current timestep.
- Returns:
- weights: A float Tensor of shape [batch_size].
- new_state: The new state of the model.
- """
- targets = self.targets_ta.read(t)
- rnn_out = self.rnn_ta.read(t)
- p_zt = self.transition(rnn_out, state.latent_encoded)
- q_zt = self.proposal(rnn_out, state.latent_encoded, p_zt, t)
- zt = q_zt.sample(seed=self.random_seed)
- p_xt_given_zt, latent_encoded = self.emission(zt, rnn_out)
- log_p_xt_given_zt = tf.reduce_sum(p_xt_given_zt.log_prob(targets), axis=-1)
- log_p_zt = tf.reduce_sum(p_zt.log_prob(zt), axis=-1)
- log_q_zt = tf.reduce_sum(q_zt.log_prob(zt), axis=-1)
- weights = log_p_zt + log_p_xt_given_zt - log_q_zt
- if self._tilt:
- prev_log_r = tf.cond(
- tf.greater(t, 0),
- lambda: self.tilt(state.rnn_out, state.latent_encoded, targets),
- lambda: 0.) # On the first step, prev_log_r = 0.
- log_r = tf.cond(
- tf.less(t + 1, self.max_seq_len),
- lambda: self.tilt(rnn_out, latent_encoded, self.targets_ta.read(t+1)),
- lambda: 0.)
- # On the last step, log_r = 0.
- log_r *= tf.to_float(t < self.seq_lengths - 1)
- weights += log_r - prev_log_r
-
- # This reshape is required because the TensorArray reports different shapes
- # than the initial state provides (where the first dimension is unknown).
- # The difference breaks the while_loop. Reshape prevents the error.
- rnn_out = tf.reshape(rnn_out, tf.shape(state.rnn_out))
-
- new_state = TrainableSRNNState(rnn_out=rnn_out,
- rnn_state=state.rnn_state, # unmodified
- latent_encoded=latent_encoded)
- return weights, new_state
-
-
-_DEFAULT_INITIALIZERS = {"w": tf.contrib.layers.xavier_initializer(),
- "b": tf.zeros_initializer()}
-
-
-def create_srnn(
- data_size,
- latent_size,
- emission_class,
- rnn_hidden_size=None,
- fcnet_hidden_sizes=None,
- encoded_data_size=None,
- encoded_latent_size=None,
- sigma_min=0.0,
- raw_sigma_bias=0.25,
- emission_bias_init=0.0,
- use_tilt=False,
- proposal_type="filtering",
- initializers=None,
- random_seed=None):
- """A factory method for creating SRNN cells.
-
- Args:
- data_size: The dimension of the vectors that make up the data sequences.
- latent_size: The size of the stochastic latent state of the SRNN.
- emission_class: The class of the emission distribution. Can be either
- ConditionalNormalDistribution or ConditionalBernoulliDistribution.
- rnn_hidden_size: The hidden state dimension of the RNN that forms the
- deterministic part of this SRNN. If None, then it defaults
- to latent_size.
- fcnet_hidden_sizes: A list of python integers, the size of the hidden
- layers of the fully connected networks that parameterize the conditional
- distributions of the SRNN. If None, then it defaults to one hidden
- layer of size latent_size.
- encoded_data_size: The size of the output of the data encoding network. If
- None, defaults to latent_size.
- encoded_latent_size: The size of the output of the latent state encoding
- network. If None, defaults to latent_size.
- sigma_min: The minimum value that the standard deviation of the
- distribution over the latent state can take.
- raw_sigma_bias: A scalar that is added to the raw standard deviation
- output from the neural networks that parameterize the prior and
- approximate posterior. Useful for preventing standard deviations close
- to zero.
- emission_bias_init: A bias to added to the raw output of the fully
- connected network that parameterizes the emission distribution. Useful
- for initalizing the mean of the distribution to a sensible starting point
- such as the mean of the training data. Only used with Bernoulli generative
- distributions.
- use_tilt: If true, create a SRNN with a tilting function.
- proposal_type: The type of proposal to use. Can be "filtering", "smoothing",
- or "prior".
- initializers: The variable intitializers to use for the fully connected
- networks and RNN cell. Must be a dictionary mapping the keys 'w' and 'b'
- to the initializers for the weights and biases. Defaults to xavier for
- the weights and zeros for the biases when initializers is None.
- random_seed: A random seed for the SRNN resampling operations.
- Returns:
- model: A TrainableSRNN object.
- """
- if rnn_hidden_size is None:
- rnn_hidden_size = latent_size
- if fcnet_hidden_sizes is None:
- fcnet_hidden_sizes = [latent_size]
- if encoded_data_size is None:
- encoded_data_size = latent_size
- if encoded_latent_size is None:
- encoded_latent_size = latent_size
- if initializers is None:
- initializers = _DEFAULT_INITIALIZERS
- data_encoder = snt.nets.MLP(
- output_sizes=fcnet_hidden_sizes + [encoded_data_size],
- initializers=initializers,
- name="data_encoder")
- latent_encoder = snt.nets.MLP(
- output_sizes=fcnet_hidden_sizes + [encoded_latent_size],
- initializers=initializers,
- name="latent_encoder")
- transition = base.ConditionalNormalDistribution(
- size=latent_size,
- hidden_layer_sizes=fcnet_hidden_sizes,
- sigma_min=sigma_min,
- raw_sigma_bias=raw_sigma_bias,
- initializers=initializers,
- name="prior")
- # Construct the emission distribution.
- if emission_class == base.ConditionalBernoulliDistribution:
- # For Bernoulli distributed outputs, we initialize the bias so that the
- # network generates on average the mean from the training set.
- emission_dist = functools.partial(base.ConditionalBernoulliDistribution,
- bias_init=emission_bias_init)
- else:
- emission_dist = base.ConditionalNormalDistribution
- emission = emission_dist(
- size=data_size,
- hidden_layer_sizes=fcnet_hidden_sizes,
- initializers=initializers,
- name="generative")
- # Construct the proposal distribution.
- if proposal_type in ["filtering", "smoothing"]:
- proposal = base.NormalApproximatePosterior(
- size=latent_size,
- hidden_layer_sizes=fcnet_hidden_sizes,
- sigma_min=sigma_min,
- raw_sigma_bias=raw_sigma_bias,
- initializers=initializers,
- smoothing=(proposal_type == "smoothing"),
- name="approximate_posterior")
- else:
- proposal = None
-
- if use_tilt:
- tilt = emission_dist(
- size=data_size,
- hidden_layer_sizes=fcnet_hidden_sizes,
- initializers=initializers,
- name="tilt")
- else:
- tilt = None
-
- rnn_cell = tf.nn.rnn_cell.LSTMCell(rnn_hidden_size,
- initializer=initializers["w"])
- rev_rnn_cell = tf.nn.rnn_cell.LSTMCell(rnn_hidden_size,
- initializer=initializers["w"])
- return TrainableSRNN(
- rnn_cell, data_encoder, latent_encoder, transition,
- emission, proposal_type, proposal=proposal, rev_rnn_cell=rev_rnn_cell,
- tilt=tilt, random_seed=random_seed)
diff --git a/research/fivo/fivo/models/srnn_test.py b/research/fivo/fivo/models/srnn_test.py
deleted file mode 100644
index 39e10da134d3834babcf2eef1bb3e97fce12a07a..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/models/srnn_test.py
+++ /dev/null
@@ -1,105 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests for fivo.models.srnn."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-from fivo.models import base
-from fivo.test_utils import create_srnn
-
-
-class SrnnTest(tf.test.TestCase):
-
- def test_srnn_normal_emission(self):
- self.run_srnn(base.ConditionalNormalDistribution, [-5.947752, -1.182961])
-
- def test_srnn_bernoulli_emission(self):
- self.run_srnn(base.ConditionalBernoulliDistribution, [-2.566631, -2.479234])
-
- def run_srnn(self, generative_class, gt_log_alpha):
- """Tests the SRNN.
-
- All test values are 'golden values' derived by running the code and copying
- the output.
-
- Args:
- generative_class: The class of the generative distribution to use.
- gt_log_alpha: The ground-truth value of log alpha.
- """
- tf.set_random_seed(1234)
- with self.test_session() as sess:
- batch_size = 2
- model, inputs, targets, _ = create_srnn(generative_class=generative_class,
- batch_size=batch_size,
- data_lengths=(1, 1),
- random_seed=1234)
- zero_state = model.zero_state(batch_size=batch_size, dtype=tf.float32)
- model.set_observations([inputs, targets], tf.convert_to_tensor([1, 1]))
- model_out = model.propose_and_weight(zero_state, 0)
- sess.run(tf.global_variables_initializer())
- log_alpha, state = sess.run(model_out)
- self.assertAllClose(
- state.latent_encoded,
- [[0.591787, 1.310583], [-1.523136, 0.953918]])
- self.assertAllClose(state.rnn_out,
- [[0.041675, -0.056038, -0.001823, 0.005224],
- [0.042925, -0.044619, 0.021401, 0.016998]])
- self.assertAllClose(log_alpha, gt_log_alpha)
-
- def test_srnn_with_tilt_normal_emission(self):
- self.run_srnn_with_tilt(base.ConditionalNormalDistribution, [-9.13577, -4.56725])
-
-
- def test_srnn_with_tilt_bernoulli_emission(self):
- self.run_srnn_with_tilt(base.ConditionalBernoulliDistribution, [-4.617461, -5.079248])
-
- def run_srnn_with_tilt(self, generative_class, gt_log_alpha):
- """Tests the SRNN with a tilting function.
-
- All test values are 'golden values' derived by running the code and copying
- the output.
-
- Args:
- generative_class: The class of the generative distribution to use.
- gt_log_alpha: The ground-truth value of log alpha.
- """
- tf.set_random_seed(1234)
- with self.test_session() as sess:
- batch_size = 2
- model, inputs, targets, _ = create_srnn(generative_class=generative_class,
- batch_size=batch_size,
- data_lengths=(3, 2),
- random_seed=1234,
- use_tilt=True)
- zero_state = model.zero_state(batch_size=batch_size, dtype=tf.float32)
- model.set_observations([inputs, targets], tf.convert_to_tensor([3, 2]))
- model_out = model.propose_and_weight(zero_state, 0)
- sess.run(tf.global_variables_initializer())
- log_alpha, state = sess.run(model_out)
- self.assertAllClose(
- state.latent_encoded,
- [[0.591787, 1.310583], [-1.523136, 0.953918]])
- self.assertAllClose(state.rnn_out,
- [[0.041675, -0.056038, -0.001823, 0.005224],
- [0.042925, -0.044619, 0.021401, 0.016998]])
- self.assertAllClose(log_alpha, gt_log_alpha)
-
-if __name__ == "__main__":
- tf.test.main()
diff --git a/research/fivo/fivo/models/vrnn.py b/research/fivo/fivo/models/vrnn.py
deleted file mode 100644
index 4e2552088c19f141a75d791d2be0d0a5238ed87c..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/models/vrnn.py
+++ /dev/null
@@ -1,572 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""VRNN classes."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from collections import namedtuple
-import functools
-
-import sonnet as snt
-import tensorflow as tf
-
-from fivo.models import base
-
-
-VRNNState = namedtuple("VRNNState", "rnn_state latent_encoded")
-
-
-class VRNN(object):
- """Implementation of a Variational Recurrent Neural Network (VRNN).
-
- Introduced in "A Recurrent Latent Variable Model for Sequential data"
- by Chung et al. https://arxiv.org/pdf/1506.02216.pdf.
-
- The VRNN is a sequence model similar to an RNN that uses stochastic latent
- variables to improve its representational power. It can be thought of as a
- sequential analogue to the variational auto-encoder (VAE).
-
- The VRNN has a deterministic RNN as its backbone, represented by the
- sequence of RNN hidden states h_t. At each timestep, the RNN hidden state h_t
- is conditioned on the previous sequence element, x_{t-1}, as well as the
- latent state from the previous timestep, z_{t-1}.
-
- In this implementation of the VRNN the latent state z_t is Gaussian. The
- model's prior over z_t (also called the transition distribution) is
- distributed as Normal(mu_t, diag(sigma_t^2)) where mu_t and sigma_t are the
- mean and standard deviation output from a fully connected network that accepts
- the rnn hidden state h_t as input.
-
- The emission distribution p(x_t|z_t, h_t) is conditioned on the latent state
- z_t as well as the current RNN hidden state h_t via a fully connected network.
-
- To increase the modeling power of the VRNN, two additional networks are
- used to extract features from the data and the latent state. Those networks
- are called data_encoder and latent_encoder respectively.
-
- For an example of how to call the VRNN's methods see sample_step.
-
- There are a few differences between this exposition and the paper.
- First, the indexing scheme for h_t is different than the paper's -- what the
- paper calls h_t we call h_{t+1}. This is the same notation used by Fraccaro
- et al. to describe the VRNN in the paper linked above. Also, the VRNN paper
- uses VAE terminology to refer to the different internal networks, so it
- refers to the emission distribution as the decoder. This implementation also
- renames the functions phi_x and phi_z in the paper to data_encoder and
- latent_encoder.
- """
-
- def __init__(self,
- rnn_cell,
- data_encoder,
- latent_encoder,
- transition,
- emission,
- random_seed=None):
- """Create a VRNN.
-
- Args:
- rnn_cell: A subclass of tf.nn.rnn_cell.RNNCell that will form the
- deterministic backbone of the VRNN. The inputs to the RNN will be the
- encoded latent state of the previous timestep with shape
- [batch_size, encoded_latent_size] as well as the encoded input of the
- current timestep, a Tensor of shape [batch_size, encoded_data_size].
- data_encoder: A callable that accepts a batch of data x_t and
- 'encodes' it, e.g. runs it through a fully connected network. Must
- accept as argument the inputs x_t, a Tensor of the shape
- [batch_size, data_size] and return a Tensor of shape
- [batch_size, encoded_data_size]. This callable will be called multiple
- times in the VRNN cell so if scoping is not handled correctly then
- multiple copies of the variables in this network could be made. It is
- recommended to use a snt.nets.MLP module, which takes care of this for
- you.
- latent_encoder: A callable that accepts a latent state z_t and
- 'encodes' it, e.g. runs it through a fully connected network. Must
- accept as argument a Tensor of shape [batch_size, latent_size] and
- return a Tensor of shape [batch_size, encoded_latent_size].
- This callable must also have the property 'output_size' defined,
- returning encoded_latent_size.
- transition: A callable that implements the transition distribution
- p(z_t|h_t). Must accept as argument the previous RNN hidden state and
- return a tf.distributions.Normal distribution conditioned on the input.
- emission: A callable that implements the emission distribution
- p(x_t|z_t, h_t). Must accept as arguments the encoded latent state
- and the RNN hidden state and return a subclass of
- tf.distributions.Distribution that can be used to evaluate the logprob
- of the targets.
- random_seed: The seed for the random ops. Sets the seed for sample_step.
- """
- self.random_seed = random_seed
- self.rnn_cell = rnn_cell
- self.data_encoder = data_encoder
- self.latent_encoder = latent_encoder
- self.encoded_z_size = latent_encoder.output_size
- self.state_size = (self.rnn_cell.state_size)
- self._transition = transition
- self._emission = emission
-
- def zero_state(self, batch_size, dtype):
- """The initial state of the VRNN.
-
- Contains the initial state of the RNN and the inital encoded latent.
-
- Args:
- batch_size: The batch size.
- dtype: The data type of the VRNN.
- Returns:
- zero_state: The initial state of the VRNN.
- """
- return VRNNState(
- rnn_state=self.rnn_cell.zero_state(batch_size, dtype),
- latent_encoded=tf.zeros(
- [batch_size, self.latent_encoder.output_size], dtype=dtype))
-
- def run_rnn(self, prev_rnn_state, prev_latent_encoded, inputs):
- """Runs the deterministic RNN for one step.
-
- Args:
- prev_rnn_state: The state of the RNN from the previous timestep.
- prev_latent_encoded: Float Tensor of shape
- [batch_size, encoded_latent_size], the previous latent state z_{t-1}
- run through latent_encoder.
- inputs: A Tensor of shape [batch_size, data_size], the current inputs to
- the model. Most often this is x_{t-1}, the previous token in the
- observation sequence.
- Returns:
- rnn_out: The output of the RNN.
- rnn_state: The new state of the RNN.
- """
- inputs_encoded = self.data_encoder(tf.to_float(inputs))
- rnn_inputs = tf.concat([inputs_encoded, prev_latent_encoded], axis=1)
- rnn_out, rnn_state = self.rnn_cell(rnn_inputs, prev_rnn_state)
- return rnn_out, rnn_state
-
- def transition(self, rnn_out):
- """Computes the transition distribution p(z_t|h_t).
-
- Note that p(z_t | h_t) = p(z_t| z_{1:t-1}, x_{1:t-1})
-
- Args:
- rnn_out: The output of the rnn for the current timestep.
- Returns:
- p(z_t | h_t): A normal distribution with event shape
- [batch_size, latent_size].
- """
- return self._transition(rnn_out)
-
- def emission(self, latent, rnn_out):
- """Computes the emission distribution p(x_t | z_t, h_t).
-
- Note that p(x_t | z_t, h_t) = p(x_t | z_{1:t}, x_{1:t-1}).
-
- Args:
- latent: The stochastic latent state z_t.
- rnn_out: The output of the rnn for the current timestep.
- Returns:
- p(x_t | z_t, h_t): A distribution with event shape
- [batch_size, data_size].
- latent_encoded: The latent state encoded with latent_encoder. Should be
- passed to run_rnn on the next timestep.
- """
- latent_encoded = self.latent_encoder(latent)
- return self._emission(latent_encoded, rnn_out), latent_encoded
-
- def sample_step(self, prev_state, inputs, unused_t):
- """Samples one output from the model.
-
- Args:
- prev_state: The previous state of the model, a VRNNState containing the
- previous rnn state and the previous encoded latent.
- inputs: A Tensor of shape [batch_size, data_size], the current inputs to
- the model. Most often this is x_{t-1}, the previous token in the
- observation sequence.
- unused_t: The current timestep. Not used currently.
- Returns:
- new_state: The next state of the model, a VRNNState.
- xt: A float Tensor of shape [batch_size, data_size], an output sampled
- from the emission distribution.
- """
- rnn_out, rnn_state = self.run_rnn(prev_state.rnn_state,
- prev_state.latent_encoded,
- inputs)
- p_zt = self.transition(rnn_out)
- zt = p_zt.sample(seed=self.random_seed)
- p_xt_given_zt, latent_encoded = self.emission(zt, rnn_out)
- xt = p_xt_given_zt.sample(seed=self.random_seed)
- new_state = VRNNState(rnn_state=rnn_state, latent_encoded=latent_encoded)
- return new_state, tf.to_float(xt)
-
-# pylint: disable=invalid-name
-# pylint thinks this is a top-level constant.
-TrainableVRNNState = namedtuple("TrainableVRNNState",
- VRNNState._fields + ("rnn_out",))
-# pylint: enable=g-invalid-name
-
-
-class TrainableVRNN(VRNN, base.ELBOTrainableSequenceModel):
- """A VRNN subclass with proposals and methods for training and evaluation.
-
- This class adds proposals used for training with importance-sampling based
- methods such as the ELBO. The model can be configured to propose from one
- of three proposals: a learned filtering proposal, a learned smoothing
- proposal, or the prior (i.e. the transition distribution).
-
- As described in the VRNN paper, the learned filtering proposal is
- parameterized by a fully connected neural network that accepts as input the
- current target x_t and the current rnn output h_t. The learned smoothing
- proposal is also given the hidden state of an RNN run in reverse over the
- inputs, so as to incorporate information about future observations. This
- smoothing proposal is not described in the VRNN paper.
-
- All learned proposals use the 'res_q' parameterization, meaning that instead
- of directly producing the mean of z_t, the proposal network predicts the
- 'residual' from the prior's mean. This is explored more in section 3.3 of
- https://arxiv.org/pdf/1605.07571.pdf.
-
- During training, the latent state z_t is sampled from the proposal and the
- reparameterization trick is used to provide low-variance gradients.
-
- Note that the VRNN paper uses VAE terminology to refer to the different
- internal networks, so the proposal is referred to as the encoder.
- """
-
- def __init__(self,
- rnn_cell,
- data_encoder,
- latent_encoder,
- transition,
- emission,
- proposal_type,
- proposal=None,
- rev_rnn_cell=None,
- tilt=None,
- random_seed=None):
- """Create a trainable RNN.
-
- Args:
- rnn_cell: A subclass of tf.nn.rnn_cell.RNNCell that will form the
- deterministic backbone of the VRNN. The inputs to the RNN will be the
- encoded latent state of the previous timestep with shape
- [batch_size, encoded_latent_size] as well as the encoded input of the
- current timestep, a Tensor of shape [batch_size, encoded_data_size].
- data_encoder: A callable that accepts a batch of data x_t and
- 'encodes' it, e.g. runs it through a fully connected network. Must
- accept as argument the inputs x_t, a Tensor of the shape
- [batch_size, data_size] and return a Tensor of shape
- [batch_size, encoded_data_size]. This callable will be called multiple
- times in the VRNN cell so if scoping is not handled correctly then
- multiple copies of the variables in this network could be made. It is
- recommended to use a snt.nets.MLP module, which takes care of this for
- you.
- latent_encoder: A callable that accepts a latent state z_t and
- 'encodes' it, e.g. runs it through a fully connected network. Must
- accept as argument a Tensor of shape [batch_size, latent_size] and
- return a Tensor of shape [batch_size, encoded_latent_size].
- This callable must also have the property 'output_size' defined,
- returning encoded_latent_size.
- transition: A callable that implements the transition distribution
- p(z_t|h_t). Must accept as argument the previous RNN hidden state and
- return a tf.distributions.Normal distribution conditioned on the input.
- emission: A callable that implements the emission distribution
- p(x_t|z_t, h_t). Must accept as arguments the encoded latent state
- and the RNN hidden state and return a subclass of
- tf.distributions.Distribution that can be used to evaluate the logprob
- of the targets.
- proposal_type: A string indicating the type of proposal to use. Can
- be either "filtering", "smoothing", or "prior". When proposal_type is
- "filtering" or "smoothing", proposal must be provided. When
- proposal_type is "smoothing", rev_rnn_cell must also be provided.
- proposal: A callable that implements the proposal q(z_t| h_t, x_{1:T}).
- If proposal_type is "filtering" then proposal must accept as arguments
- the current rnn output, the encoded target of the current timestep,
- and the mean of the prior. If proposal_type is "smoothing" then
- in addition to the current rnn output and the mean of the prior
- proposal must accept as arguments the output of the reverse rnn.
- proposal should return a tf.distributions.Normal distribution
- conditioned on its inputs. If proposal_type is "prior" this argument is
- ignored.
- rev_rnn_cell: A subclass of tf.nn.rnn_cell.RNNCell that will aggregate
- observation statistics in the reverse direction. The inputs to the RNN
- will be the encoded reverse input of the current timestep, a Tensor of
- shape [batch_size, encoded_data_size].
- tilt: A callable that implements the log of a positive tilting function
- (ideally approximating log p(x_{t+1}|z_t, h_t). Must accept as arguments
- the encoded latent state and the RNN hidden state and return a subclass
- of tf.distributions.Distribution that can be used to evaluate the
- logprob of x_{t+1}. Optionally, None and then no tilt is used.
- random_seed: The seed for the random ops. Sets the seed for sample_step
- and __call__.
- """
- super(TrainableVRNN, self).__init__(
- rnn_cell, data_encoder, latent_encoder,
- transition, emission, random_seed=random_seed)
- self.rev_rnn_cell = rev_rnn_cell
- self._tilt = tilt
- assert proposal_type in ["filtering", "smoothing", "prior"]
- self._proposal = proposal
- self.proposal_type = proposal_type
- if proposal_type != "prior":
- assert proposal, "If not proposing from the prior, must provide proposal."
- if proposal_type == "smoothing":
- assert rev_rnn_cell, "Must provide rev_rnn_cell for smoothing proposal."
-
- def zero_state(self, batch_size, dtype):
- super_state = super(TrainableVRNN, self).zero_state(batch_size, dtype)
- return TrainableVRNNState(
- rnn_out=tf.zeros([batch_size, self.rnn_cell.output_size], dtype=dtype),
- **super_state._asdict())
-
- def set_observations(self, observations, seq_lengths):
- """Stores the model's observations.
-
- Stores the observations (inputs and targets) in TensorArrays and precomputes
- things for later like the reverse RNN output and encoded targets.
-
- Args:
- observations: The observations of the model, a tuple containing two
- Tensors of shape [max_seq_len, batch_size, data_size]. The Tensors
- should be the inputs and targets, respectively.
- seq_lengths: An int Tensor of shape [batch_size] containing the length
- of each sequence in observations.
- """
- inputs, targets = observations
- self.seq_lengths = seq_lengths
- self.max_seq_len = tf.reduce_max(seq_lengths)
- self.inputs_ta = base.ta_for_tensor(inputs, clear_after_read=False)
- self.targets_ta = base.ta_for_tensor(targets, clear_after_read=False)
- targets_encoded = base.encode_all(targets, self.data_encoder)
- self.targets_encoded_ta = base.ta_for_tensor(targets_encoded,
- clear_after_read=False)
- if self.rev_rnn_cell:
- reverse_targets_encoded = tf.reverse_sequence(
- targets_encoded, seq_lengths, seq_axis=0, batch_axis=1)
- # Compute the reverse rnn over the targets.
- reverse_rnn_out, _ = tf.nn.dynamic_rnn(self.rev_rnn_cell,
- reverse_targets_encoded,
- time_major=True,
- dtype=tf.float32)
- reverse_rnn_out = tf.reverse_sequence(reverse_rnn_out, seq_lengths,
- seq_axis=0, batch_axis=1)
- self.reverse_rnn_ta = base.ta_for_tensor(reverse_rnn_out,
- clear_after_read=False)
-
- def _filtering_proposal(self, rnn_out, prior, t):
- """Computes the filtering proposal distribution."""
- return self._proposal(rnn_out,
- self.targets_encoded_ta.read(t),
- prior_mu=prior.mean())
-
- def _smoothing_proposal(self, rnn_out, prior, t):
- """Computes the smoothing proposal distribution."""
- return self._proposal(rnn_out,
- smoothing_tensors=[self.reverse_rnn_ta.read(t)],
- prior_mu=prior.mean())
-
- def proposal(self, rnn_out, prior, t):
- """Computes the proposal distribution specified by proposal_type.
-
- Args:
- rnn_out: The output of the rnn for the current timestep.
- prior: A tf.distributions.Normal distribution representing the prior
- over z_t, p(z_t | z_{1:t-1}, x_{1:t-1}). Used for 'res_q'.
- t: A scalar int Tensor, the current timestep.
- """
- if self.proposal_type == "filtering":
- return self._filtering_proposal(rnn_out, prior, t)
- elif self.proposal_type == "smoothing":
- return self._smoothing_proposal(rnn_out, prior, t)
- elif self.proposal_type == "prior":
- return self.transition(rnn_out)
-
- def tilt(self, rnn_out, latent_encoded, targets):
- r_func = self._tilt(rnn_out, latent_encoded)
- return tf.reduce_sum(r_func.log_prob(targets), axis=-1)
-
- def propose_and_weight(self, state, t):
- """Runs the model and computes importance weights for one timestep.
-
- Runs the model and computes importance weights, sampling from the proposal
- instead of the transition/prior.
-
- Args:
- state: The previous state of the model, a TrainableVRNNState containing
- the previous rnn state, the previous rnn outs, and the previous encoded
- latent.
- t: A scalar integer Tensor, the current timestep.
- Returns:
- weights: A float Tensor of shape [batch_size].
- new_state: The new state of the model.
- """
- inputs = self.inputs_ta.read(t)
- targets = self.targets_ta.read(t)
- rnn_out, next_rnn_state = self.run_rnn(state.rnn_state,
- state.latent_encoded,
- inputs)
- p_zt = self.transition(rnn_out)
- q_zt = self.proposal(rnn_out, p_zt, t)
- zt = q_zt.sample(seed=self.random_seed)
- p_xt_given_zt, latent_encoded = self.emission(zt, rnn_out)
- log_p_xt_given_zt = tf.reduce_sum(p_xt_given_zt.log_prob(targets), axis=-1)
- log_p_zt = tf.reduce_sum(p_zt.log_prob(zt), axis=-1)
- log_q_zt = tf.reduce_sum(q_zt.log_prob(zt), axis=-1)
- weights = log_p_zt + log_p_xt_given_zt - log_q_zt
- if self._tilt:
- prev_log_r = tf.cond(
- tf.greater(t, 0),
- lambda: self.tilt(state.rnn_out, state.latent_encoded, targets),
- lambda: 0.) # On the first step, prev_log_r = 0.
- log_r = tf.cond(
- tf.less(t + 1, self.max_seq_len),
- lambda: self.tilt(rnn_out, latent_encoded, self.targets_ta.read(t+1)),
- lambda: 0.)
- # On the last step, log_r = 0.
- log_r *= tf.to_float(t < self.seq_lengths - 1)
- weights += log_r - prev_log_r
- new_state = TrainableVRNNState(rnn_state=next_rnn_state,
- rnn_out=rnn_out,
- latent_encoded=latent_encoded)
- return weights, new_state
-
-
-_DEFAULT_INITIALIZERS = {"w": tf.contrib.layers.xavier_initializer(),
- "b": tf.zeros_initializer()}
-
-
-def create_vrnn(
- data_size,
- latent_size,
- emission_class,
- rnn_hidden_size=None,
- fcnet_hidden_sizes=None,
- encoded_data_size=None,
- encoded_latent_size=None,
- sigma_min=0.0,
- raw_sigma_bias=0.25,
- emission_bias_init=0.0,
- use_tilt=False,
- proposal_type="filtering",
- initializers=None,
- random_seed=None):
- """A factory method for creating VRNN cells.
-
- Args:
- data_size: The dimension of the vectors that make up the data sequences.
- latent_size: The size of the stochastic latent state of the VRNN.
- emission_class: The class of the emission distribution. Can be either
- ConditionalNormalDistribution or ConditionalBernoulliDistribution.
- rnn_hidden_size: The hidden state dimension of the RNN that forms the
- deterministic part of this VRNN. If None, then it defaults
- to latent_size.
- fcnet_hidden_sizes: A list of python integers, the size of the hidden
- layers of the fully connected networks that parameterize the conditional
- distributions of the VRNN. If None, then it defaults to one hidden
- layer of size latent_size.
- encoded_data_size: The size of the output of the data encoding network. If
- None, defaults to latent_size.
- encoded_latent_size: The size of the output of the latent state encoding
- network. If None, defaults to latent_size.
- sigma_min: The minimum value that the standard deviation of the
- distribution over the latent state can take.
- raw_sigma_bias: A scalar that is added to the raw standard deviation
- output from the neural networks that parameterize the prior and
- approximate posterior. Useful for preventing standard deviations close
- to zero.
- emission_bias_init: A bias to added to the raw output of the fully
- connected network that parameterizes the emission distribution. Useful
- for initalizing the mean of the distribution to a sensible starting point
- such as the mean of the training data. Only used with Bernoulli generative
- distributions.
- use_tilt: If true, create a VRNN with a tilting function.
- proposal_type: The type of proposal to use. Can be "filtering", "smoothing",
- or "prior".
- initializers: The variable intitializers to use for the fully connected
- networks and RNN cell. Must be a dictionary mapping the keys 'w' and 'b'
- to the initializers for the weights and biases. Defaults to xavier for
- the weights and zeros for the biases when initializers is None.
- random_seed: A random seed for the VRNN resampling operations.
- Returns:
- model: A TrainableVRNN object.
- """
- if rnn_hidden_size is None:
- rnn_hidden_size = latent_size
- if fcnet_hidden_sizes is None:
- fcnet_hidden_sizes = [latent_size]
- if encoded_data_size is None:
- encoded_data_size = latent_size
- if encoded_latent_size is None:
- encoded_latent_size = latent_size
- if initializers is None:
- initializers = _DEFAULT_INITIALIZERS
- data_encoder = snt.nets.MLP(
- output_sizes=fcnet_hidden_sizes + [encoded_data_size],
- initializers=initializers,
- name="data_encoder")
- latent_encoder = snt.nets.MLP(
- output_sizes=fcnet_hidden_sizes + [encoded_latent_size],
- initializers=initializers,
- name="latent_encoder")
- transition = base.ConditionalNormalDistribution(
- size=latent_size,
- hidden_layer_sizes=fcnet_hidden_sizes,
- sigma_min=sigma_min,
- raw_sigma_bias=raw_sigma_bias,
- initializers=initializers,
- name="prior")
- # Construct the emission distribution.
- if emission_class == base.ConditionalBernoulliDistribution:
- # For Bernoulli distributed outputs, we initialize the bias so that the
- # network generates on average the mean from the training set.
- emission_dist = functools.partial(base.ConditionalBernoulliDistribution,
- bias_init=emission_bias_init)
- else:
- emission_dist = base.ConditionalNormalDistribution
- emission = emission_dist(
- size=data_size,
- hidden_layer_sizes=fcnet_hidden_sizes,
- initializers=initializers,
- name="generative")
- # Construct the proposal distribution.
- if proposal_type in ["filtering", "smoothing"]:
- proposal = base.NormalApproximatePosterior(
- size=latent_size,
- hidden_layer_sizes=fcnet_hidden_sizes,
- sigma_min=sigma_min,
- raw_sigma_bias=raw_sigma_bias,
- initializers=initializers,
- smoothing=(proposal_type == "smoothing"),
- name="approximate_posterior")
- else:
- proposal = None
-
- if use_tilt:
- tilt = emission_dist(
- size=data_size,
- hidden_layer_sizes=fcnet_hidden_sizes,
- initializers=initializers,
- name="tilt")
- else:
- tilt = None
-
- rnn_cell = tf.nn.rnn_cell.LSTMCell(rnn_hidden_size,
- initializer=initializers["w"])
- rev_rnn_cell = tf.nn.rnn_cell.LSTMCell(rnn_hidden_size,
- initializer=initializers["w"])
- return TrainableVRNN(
- rnn_cell, data_encoder, latent_encoder, transition,
- emission, proposal_type, proposal=proposal, rev_rnn_cell=rev_rnn_cell,
- tilt=tilt, random_seed=random_seed)
diff --git a/research/fivo/fivo/models/vrnn_test.py b/research/fivo/fivo/models/vrnn_test.py
deleted file mode 100644
index 2d9bde3d5b6c6f66a82bd331cf50a87737864239..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/models/vrnn_test.py
+++ /dev/null
@@ -1,137 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests for fivo.models.vrnn."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-
-import tensorflow as tf
-
-from fivo.models import base
-from fivo.test_utils import create_vrnn
-
-
-class VrnnTest(tf.test.TestCase):
-
- def test_vrnn_normal_emission(self):
- self.run_vrnn(base.ConditionalNormalDistribution, [-4.509767, -3.242221])
-
- def test_vrnn_bernoulli_emission(self):
- self.run_vrnn(base.ConditionalBernoulliDistribution, [-2.63812733, -2.02216434]),
-
- def run_vrnn(self, generative_class, gt_log_p_x_given_z):
- """Tests the VRNN.
-
- All test values are 'golden values' derived by running the code and copying
- the output.
-
- Args:
- generative_class: The class of the generative distribution to use.
- gt_log_p_x_given_z: The ground-truth value of log p(x|z).
- """
- tf.set_random_seed(1234)
- with self.test_session() as sess:
- batch_size = 2
- model, inputs, targets, _ = create_vrnn(generative_class=generative_class,
- batch_size=batch_size,
- data_lengths=(1, 1),
- random_seed=1234)
- zero_state = model.zero_state(batch_size=batch_size, dtype=tf.float32)
- model.set_observations([inputs, targets], tf.convert_to_tensor([1, 1]))
- model_out = model.propose_and_weight(zero_state, 0)
- sess.run(tf.global_variables_initializer())
- log_alpha, state = sess.run(model_out)
- rnn_state, latent_state, rnn_out = state
- self.assertAllClose(
- rnn_state.c,
- [[-0.15014534, 0.0143046, 0.00160489, -0.12899463],
- [-0.25015137, 0.09377634, -0.05000039, -0.17123522]])
- self.assertAllClose(
- rnn_state.h,
- [[-0.06842659, 0.00760155, 0.00096106, -0.05434214],
- [-0.1109542, 0.0441804, -0.03121299, -0.07882939]]
- )
- self.assertAllClose(
- latent_state,
- [[0.025241, 0.122011, 1.066661, 0.316209, -0.25369, 0.108215,
- -1.501128, -0.440111, -0.40447, -0.156649, 1.206028],
- [0.066824, 0.519937, 0.610973, 0.977739, -0.121889, -0.223429,
- -0.32687, -0.578763, -0.56965, 0.751886, 0.681606]]
- )
- self.assertAllClose(rnn_out, [[-0.068427, 0.007602, 0.000961, -0.054342],
- [-0.110954, 0.04418, -0.031213, -0.078829]])
- gt_log_q_z = [-8.0895052, -6.75819111]
- gt_log_p_z = [-7.246827, -6.512877]
- gt_log_alpha = (np.array(gt_log_p_z) +
- np.array(gt_log_p_x_given_z) -
- np.array(gt_log_q_z))
- self.assertAllClose(log_alpha, gt_log_alpha)
-
- def test_vrnn_with_tilt_normal_emission(self):
- self.run_vrnn_with_tilt(base.ConditionalNormalDistribution, [-5.198263, -6.31686])
-
- def test_vrnn_with_tilt_bernoulli_emission(self):
- self.run_vrnn_with_tilt(base.ConditionalBernoulliDistribution, [-4.66985, -3.802245])
-
- def run_vrnn_with_tilt(self, generative_class, gt_log_alpha):
- """Tests the VRNN with a tilting function.
-
- All test values are 'golden values' derived by running the code and copying
- the output.
-
- Args:
- generative_class: The class of the generative distribution to use.
- gt_log_alpha: The ground-truth value of log alpha.
- """
- tf.set_random_seed(1234)
- with self.test_session() as sess:
- batch_size = 2
- model, inputs, targets, _ = create_vrnn(generative_class=generative_class,
- batch_size=batch_size,
- data_lengths=(3, 2),
- random_seed=1234,
- use_tilt=True)
- zero_state = model.zero_state(batch_size=batch_size, dtype=tf.float32)
- model.set_observations([inputs, targets], tf.convert_to_tensor([3, 2]))
- model_out = model.propose_and_weight(zero_state, 0)
- sess.run(tf.global_variables_initializer())
- log_alpha, state = sess.run(model_out)
- rnn_state, latent_state, rnn_out = state
- self.assertAllClose(
- rnn_state.c,
- [[-0.15014534, 0.0143046, 0.00160489, -0.12899463],
- [-0.25015137, 0.09377634, -0.05000039, -0.17123522]])
- self.assertAllClose(
- rnn_state.h,
- [[-0.06842659, 0.00760155, 0.00096106, -0.05434214],
- [-0.1109542, 0.0441804, -0.03121299, -0.07882939]]
- )
- self.assertAllClose(
- latent_state,
- [[0.025241, 0.122011, 1.066661, 0.316209, -0.25369, 0.108215,
- -1.501128, -0.440111, -0.40447, -0.156649, 1.206028],
- [0.066824, 0.519937, 0.610973, 0.977739, -0.121889, -0.223429,
- -0.32687, -0.578763, -0.56965, 0.751886, 0.681606]]
- )
- self.assertAllClose(rnn_out, [[-0.068427, 0.007602, 0.000961, -0.054342],
- [-0.110954, 0.04418, -0.031213, -0.078829]])
- self.assertAllClose(log_alpha, gt_log_alpha)
-
-if __name__ == "__main__":
- tf.test.main()
diff --git a/research/fivo/fivo/nested_utils.py b/research/fivo/fivo/nested_utils.py
deleted file mode 100644
index ef956a80c40d55331a3acbfe78111e099559ddea..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/nested_utils.py
+++ /dev/null
@@ -1,139 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""A set of utils for dealing with nested lists and tuples of Tensors."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import itertools
-import tensorflow as tf
-
-from tensorflow.python.util import nest
-
-
-def map_nested(map_fn, nested):
- """Executes map_fn on every element in a (potentially) nested structure.
-
- Args:
- map_fn: A callable to execute on each element in 'nested'.
- nested: A potentially nested combination of sequence objects. Sequence
- objects include tuples, lists, namedtuples, and all subclasses of
- collections.Sequence except strings. See nest.is_sequence for details.
- For example [1, ('hello', 4.3)] is a nested structure containing elements
- 1, 'hello', and 4.3.
- Returns:
- out_structure: A potentially nested combination of sequence objects with the
- same structure as the 'nested' input argument. out_structure
- contains the result of applying map_fn to each element in 'nested'. For
- example map_nested(lambda x: x+1, [1, (3, 4.3)]) returns [2, (4, 5.3)].
- """
- out = map(map_fn, nest.flatten(nested))
- return nest.pack_sequence_as(nested, out)
-
-
-def tile_tensors(tensors, multiples):
- """Tiles a set of Tensors.
-
- Args:
- tensors: A potentially nested tuple or list of Tensors with rank
- greater than or equal to the length of 'multiples'. The Tensors do not
- need to have the same rank, but their rank must not be dynamic.
- multiples: A python list of ints indicating how to tile each Tensor
- in 'tensors'. Similar to the 'multiples' argument to tf.tile.
- Returns:
- tiled_tensors: A potentially nested tuple or list of Tensors with the same
- structure as the 'tensors' input argument. Contains the result of
- applying tf.tile to each Tensor in 'tensors'. When the rank of a Tensor
- in 'tensors' is greater than the length of multiples, multiples is padded
- at the end with 1s. For example when tiling a 4-dimensional Tensor with
- multiples [3, 4], multiples would be padded to [3, 4, 1, 1] before tiling.
- """
- def tile_fn(x):
- return tf.tile(x, multiples + [1] * (x.shape.ndims - len(multiples)))
-
- return map_nested(tile_fn, tensors)
-
-
-def where_tensors(condition, x_tensors, y_tensors):
- """Performs a tf.where operation on a two sets of Tensors.
-
- Args:
- condition: The condition tensor to use for the where operation.
- x_tensors: A potentially nested tuple or list of Tensors.
- y_tensors: A potentially nested tuple or list of Tensors. Must have the
- same structure as x_tensors.
- Returns:
- whered_tensors: A potentially nested tuple or list of Tensors with the
- same structure as the 'tensors' input argument. Contains the result of
- applying tf.where(condition, x, y) on each pair of elements in x_tensors
- and y_tensors.
- """
- flat_x = nest.flatten(x_tensors)
- flat_y = nest.flatten(y_tensors)
- result = [tf.where(condition, x, y) for x, y in
- itertools.izip(flat_x, flat_y)]
-
- return nest.pack_sequence_as(x_tensors, result)
-
-
-def gather_tensors(tensors, indices):
- """Performs a tf.gather operation on a set of Tensors.
-
- Args:
- tensors: A potentially nested tuple or list of Tensors.
- indices: The indices to use for the gather operation.
- Returns:
- gathered_tensors: A potentially nested tuple or list of Tensors with the
- same structure as the 'tensors' input argument. Contains the result of
- applying tf.gather(x, indices) on each element x in 'tensors'.
- """
- return map_nested(lambda x: tf.gather(x, indices), tensors)
-
-
-def tas_for_tensors(tensors, length, **kwargs):
- """Unstacks a set of Tensors into TensorArrays.
-
- Args:
- tensors: A potentially nested tuple or list of Tensors with length in the
- first dimension greater than or equal to the 'length' input argument.
- length: The desired length of the TensorArrays.
- **kwargs: Keyword args for TensorArray constructor.
- Returns:
- tensorarrays: A potentially nested tuple or list of TensorArrays with the
- same structure as 'tensors'. Contains the result of unstacking each Tensor
- in 'tensors'.
- """
- def map_fn(x):
- ta = tf.TensorArray(x.dtype, length,
- name=x.name.split(':')[0] + '_ta', **kwargs)
- return ta.unstack(x[:length, :])
- return map_nested(map_fn, tensors)
-
-
-def read_tas(tas, index):
- """Performs a read operation on a set of TensorArrays.
-
- Args:
- tas: A potentially nested tuple or list of TensorArrays with length greater
- than 'index'.
- index: The location to read from.
- Returns:
- read_tensors: A potentially nested tuple or list of Tensors with the same
- structure as the 'tas' input argument. Contains the result of
- performing a read operation at 'index' on each TensorArray in 'tas'.
- """
- return map_nested(lambda ta: ta.read(index), tas)
diff --git a/research/fivo/fivo/nested_utils_test.py b/research/fivo/fivo/nested_utils_test.py
deleted file mode 100644
index 87991dd79cdb29d12944f9afa3fd0c5178dc4eb5..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/nested_utils_test.py
+++ /dev/null
@@ -1,125 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests for fivo.nested_utils."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-import tensorflow as tf
-nest = tf.contrib.framework.nest
-
-from fivo import nested_utils
-
-# An example namedtuple for use in the following tests.
-ExampleTuple = collections.namedtuple('ExampleTuple', ['a', 'b'])
-
-
-class NestedUtilsTest(tf.test.TestCase):
-
- def test_map_nested_works_on_nested_structures(self):
- """Check that map_nested works with nested structures."""
- original = [1, (2, 3.2, (4., ExampleTuple(5, 6)))]
- expected = [2, (3, 4.2, (5., ExampleTuple(6, 7)))]
- out = nested_utils.map_nested(lambda x: x+1, original)
- self.assertEqual(expected, out)
-
- def test_map_nested_works_on_single_objects(self):
- """Check that map_nested works with raw objects."""
- original = 1
- expected = 2
- out = nested_utils.map_nested(lambda x: x+1, original)
- self.assertEqual(expected, out)
-
- def test_map_nested_works_on_flat_lists(self):
- """Check that map_nested works with a flat list."""
- original = [1, 2, 3]
- expected = [2, 3, 4]
- out = nested_utils.map_nested(lambda x: x+1, original)
- self.assertEqual(expected, out)
-
- def test_tile_tensors(self):
- """Checks that tile_tensors correctly tiles tensors of different ranks."""
- a = tf.range(20)
- b = tf.reshape(a, [2, 10])
- c = tf.reshape(a, [2, 2, 5])
- a_tiled = tf.tile(a, [3])
- b_tiled = tf.tile(b, [3, 1])
- c_tiled = tf.tile(c, [3, 1, 1])
- tensors = [a, (b, ExampleTuple(c, c))]
- expected_tensors = [a_tiled, (b_tiled, ExampleTuple(c_tiled, c_tiled))]
- tiled = nested_utils.tile_tensors(tensors, [3])
- nest.assert_same_structure(expected_tensors, tiled)
- with self.test_session() as sess:
- expected, out = sess.run([expected_tensors, tiled])
- expected = nest.flatten(expected)
- out = nest.flatten(out)
- # Check that the tiling is correct.
- for x, y in zip(expected, out):
- self.assertAllClose(x, y)
-
- def test_gather_tensors(self):
- a = tf.reshape(tf.range(20), [5, 4])
- inds = [0, 0, 1, 4]
- a_gathered = tf.gather(a, inds)
- tensors = [a, (a, ExampleTuple(a, a))]
- gt_gathered = [a_gathered, (a_gathered,
- ExampleTuple(a_gathered, a_gathered))]
- gathered = nested_utils.gather_tensors(tensors, inds)
- nest.assert_same_structure(gt_gathered, gathered)
- with self.test_session() as sess:
- gt, out = sess.run([gt_gathered, gathered])
- gt = nest.flatten(gt)
- out = nest.flatten(out)
- # Check that the gathering is correct.
- for x, y in zip(gt, out):
- self.assertAllClose(x, y)
-
- def test_tas_for_tensors(self):
- a = tf.reshape(tf.range(20), [5, 4])
- tensors = [a, (a, ExampleTuple(a, a))]
- tas = nested_utils.tas_for_tensors(tensors, 5)
- nest.assert_same_structure(tensors, tas)
- # We can't pass TensorArrays to sess.run so instead we turn then back into
- # tensors to check that they were created correctly.
- stacked = nested_utils.map_nested(lambda x: x.stack(), tas)
- with self.test_session() as sess:
- gt, out = sess.run([tensors, stacked])
- gt = nest.flatten(gt)
- out = nest.flatten(out)
- # Check that the tas were created correctly.
- for x, y in zip(gt, out):
- self.assertAllClose(x, y)
-
- def test_read_tas(self):
- a = tf.reshape(tf.range(20), [5, 4])
- a_read = a[3, :]
- tensors = [a, (a, ExampleTuple(a, a))]
- gt_read = [a_read, (a_read, ExampleTuple(a_read, a_read))]
- tas = nested_utils.tas_for_tensors(tensors, 5)
- tas_read = nested_utils.read_tas(tas, 3)
- nest.assert_same_structure(tas, tas_read)
- with self.test_session() as sess:
- gt, out = sess.run([gt_read, tas_read])
- gt = nest.flatten(gt)
- out = nest.flatten(out)
- # Check that the tas were read correctly.
- for x, y in zip(gt, out):
- self.assertAllClose(x, y)
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/fivo/fivo/runners.py b/research/fivo/fivo/runners.py
deleted file mode 100644
index ec6fb91bf51fa2c7c44d7402e635d257f80c3f7a..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/runners.py
+++ /dev/null
@@ -1,489 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""High-level code for creating and running FIVO-related Tensorflow graphs.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import os
-import time
-
-import numpy as np
-import tensorflow as tf
-
-from fivo import bounds
-from fivo import smc
-
-from fivo.data import datasets
-from fivo.models import base
-from fivo.models import srnn
-from fivo.models import vrnn
-
-
-def create_dataset_and_model(config, split, shuffle, repeat):
- """Creates the dataset and model for a given config.
-
- Args:
- config: A configuration object with config values accessible as properties.
- Most likely a FLAGS object. This function expects the properties
- batch_size, dataset_path, dataset_type, and latent_size to be defined.
- split: The dataset split to load.
- shuffle: If true, shuffle the dataset randomly.
- repeat: If true, repeat the dataset endlessly.
- Returns:
- inputs: A batch of input sequences represented as a dense Tensor of shape
- [time, batch_size, data_dimension].
- targets: A batch of target sequences represented as a dense Tensor of
- shape [time, batch_size, data_dimension].
- lens: An int Tensor of shape [batch_size] representing the lengths of each
- sequence in the batch.
- model: A vrnn.VRNNCell model object.
- Raises:
- ValueError: if the config is invalid.
- """
- sigma_min = 0.0
- if config.dataset_type == "pianoroll":
- inputs, targets, lengths, mean = datasets.create_pianoroll_dataset(
- config.dataset_path, split, config.batch_size, shuffle=shuffle,
- repeat=repeat)
- # Convert the mean of the training set to logit space so it can be used to
- # initialize the bias of the generative distribution.
- emission_bias_init = -tf.log(
- 1. / tf.clip_by_value(mean, 0.0001, 0.9999) - 1)
- emission_distribution_class = base.ConditionalBernoulliDistribution
- elif config.dataset_type == "speech":
- inputs, targets, lengths = datasets.create_speech_dataset(
- config.dataset_path, config.batch_size,
- samples_per_timestep=config.data_dimension, prefetch_buffer_size=1,
- shuffle=False, repeat=False)
- # There is no bias for the generative distribution because the test set
- # is assumed to be already standardized with the training set statistics.
- mean = None
- emission_bias_init = None
- emission_distribution_class = base.ConditionalNormalDistribution
- if config.model == "vrnn":
- model = vrnn.create_vrnn(inputs.get_shape().as_list()[2],
- config.latent_size,
- emission_distribution_class,
- emission_bias_init=emission_bias_init,
- proposal_type=config.proposal_type,
- sigma_min=sigma_min,
- raw_sigma_bias=0.5,
- use_tilt=(config.bound == "fivo-aux"))
- elif config.model == "srnn":
- model = srnn.create_srnn(inputs.get_shape().as_list()[2],
- config.latent_size,
- emission_distribution_class,
- emission_bias_init=emission_bias_init,
- proposal_type=config.proposal_type,
- sigma_min=sigma_min,
- raw_sigma_bias=0.5,
- use_tilt=(config.bound == "fivo-aux"))
- else:
- raise ValueError("model flag: %s is unrecognized" % config.model)
- return inputs, targets, lengths, model, mean
-
-
-def restore_checkpoint_if_exists(saver, sess, logdir):
- """Looks for a checkpoint and restores the session from it if found.
-
- Args:
- saver: A tf.train.Saver for restoring the session.
- sess: A TensorFlow session.
- logdir: The directory to look for checkpoints in.
- Returns:
- True if a checkpoint was found and restored, False otherwise.
- """
- checkpoint = tf.train.get_checkpoint_state(logdir)
- if checkpoint:
- checkpoint_name = os.path.basename(checkpoint.model_checkpoint_path)
- full_checkpoint_path = os.path.join(logdir, checkpoint_name)
- saver.restore(sess, full_checkpoint_path)
- return True
- return False
-
-
-def wait_for_checkpoint(saver, sess, logdir):
- """Loops until the session is restored from a checkpoint in logdir.
-
- Args:
- saver: A tf.train.Saver for restoring the session.
- sess: A TensorFlow session.
- logdir: The directory to look for checkpoints in.
- """
- while not restore_checkpoint_if_exists(saver, sess, logdir):
- tf.logging.info("Checkpoint not found in %s, sleeping for 60 seconds."
- % logdir)
- time.sleep(60)
-
-
-def run_train(config, create_dataset_and_model_fn=create_dataset_and_model):
- """Runs training for a sequential latent variable model.
-
- Args:
- config: A configuration object with config values accessible as properties.
- Most likely a FLAGS object. For a list of expected properties and their
- meaning see the flags defined in fivo.py.
- create_dataset_and_model_fn: If present, calls this function to create a
- dataset and model instead of create_dataset_and_model() above. The
- signature must be the same.
- """
-
- def create_logging_hook(step, bound_value):
- """Creates a logging hook that prints the bound value periodically."""
- bound_label = config.bound + " bound"
- if config.normalize_by_seq_len:
- bound_label += " per timestep"
- else:
- bound_label += " per sequence"
- def summary_formatter(log_dict):
- return "Step %d, %s: %f" % (
- log_dict["step"], bound_label, log_dict["bound_value"])
- logging_hook = tf.train.LoggingTensorHook(
- {"step": step, "bound_value": bound_value},
- every_n_iter=config.summarize_every,
- formatter=summary_formatter)
- return logging_hook
-
- def create_loss():
- """Creates the loss to be optimized.
-
- Returns:
- bound: A float Tensor containing the value of the bound that is
- being optimized.
- loss: A float Tensor that when differentiated yields the gradients
- to apply to the model. Should be optimized via gradient descent.
- """
- inputs, targets, lengths, model, _ = create_dataset_and_model_fn(
- config, split="train", shuffle=True, repeat=True)
- # Compute lower bounds on the log likelihood.
- if config.bound == "elbo":
- ll_per_seq, _, _ = bounds.iwae(
- model, (inputs, targets), lengths, num_samples=1,
- parallel_iterations=config.parallel_iterations
- )
- elif config.bound == "iwae":
- ll_per_seq, _, _ = bounds.iwae(
- model, (inputs, targets), lengths, num_samples=config.num_samples,
- parallel_iterations=config.parallel_iterations
- )
- elif config.bound in ("fivo", "fivo-aux"):
- if config.resampling_type == "relaxed":
- ll_per_seq, _, _, _ = bounds.fivo(
- model, (inputs, targets),
- lengths,
- num_samples=config.num_samples,
- resampling_criterion=smc.ess_criterion,
- resampling_type=config.resampling_type,
- random_seed=config.random_seed,
- relaxed_resampling_temperature=config.
- relaxed_resampling_temperature,
- parallel_iterations=config.parallel_iterations
- )
- else:
- ll_per_seq, _, _, _ = bounds.fivo(
- model, (inputs, targets), lengths, num_samples=config.num_samples,
- resampling_criterion=smc.ess_criterion,
- resampling_type=config.resampling_type,
- random_seed=config.random_seed,
- parallel_iterations=config.parallel_iterations
- )
- # Compute loss scaled by number of timesteps.
- ll_per_t = tf.reduce_mean(ll_per_seq / tf.to_float(lengths))
- ll_per_seq = tf.reduce_mean(ll_per_seq)
-
- tf.summary.scalar("train_ll_per_seq", ll_per_seq)
- tf.summary.scalar("train_ll_per_t", ll_per_t)
-
- if config.normalize_by_seq_len:
- return ll_per_t, -ll_per_t
- else:
- return ll_per_seq, -ll_per_seq
-
- def create_graph():
- """Creates the training graph."""
- global_step = tf.train.get_or_create_global_step()
- bound, loss = create_loss()
- opt = tf.train.AdamOptimizer(config.learning_rate)
- grads = opt.compute_gradients(loss, var_list=tf.trainable_variables())
- train_op = opt.apply_gradients(grads, global_step=global_step)
- return bound, train_op, global_step
-
- device = tf.train.replica_device_setter(ps_tasks=config.ps_tasks)
- with tf.Graph().as_default():
- if config.random_seed: tf.set_random_seed(config.random_seed)
- with tf.device(device):
- bound, train_op, global_step = create_graph()
- log_hook = create_logging_hook(global_step, bound)
- start_training = not config.stagger_workers
- with tf.train.MonitoredTrainingSession(
- master=config.master,
- is_chief=config.task == 0,
- hooks=[log_hook],
- checkpoint_dir=config.logdir,
- save_checkpoint_secs=120,
- save_summaries_steps=config.summarize_every,
- log_step_count_steps=config.summarize_every) as sess:
- cur_step = -1
- while not sess.should_stop() and cur_step <= config.max_steps:
- if config.task > 0 and not start_training:
- cur_step = sess.run(global_step)
- tf.logging.info("task %d not active yet, sleeping at step %d" %
- (config.task, cur_step))
- time.sleep(30)
- if cur_step >= config.task * 1000:
- start_training = True
- else:
- _, cur_step = sess.run([train_op, global_step])
-
-
-def run_eval(config, create_dataset_and_model_fn=create_dataset_and_model):
- """Runs evaluation for a sequential latent variable model.
-
- This method runs only one evaluation over the dataset, writes summaries to
- disk, and then terminates. It does not loop indefinitely.
-
- Args:
- config: A configuration object with config values accessible as properties.
- Most likely a FLAGS object. For a list of expected properties and their
- meaning see the flags defined in fivo.py.
- create_dataset_and_model_fn: If present, calls this function to create a
- dataset and model instead of create_dataset_and_model() above. The
- signature must be the same.
- """
-
- def create_graph():
- """Creates the evaluation graph.
-
- Returns:
- lower_bounds: A tuple of float Tensors containing the values of the 3
- evidence lower bounds, summed across the batch.
- total_batch_length: The total number of timesteps in the batch, summed
- across batch examples.
- batch_size: The batch size.
- global_step: The global step the checkpoint was loaded from.
- """
- global_step = tf.train.get_or_create_global_step()
- inputs, targets, lengths, model, _ = create_dataset_and_model_fn(
- config, split=config.split, shuffle=False, repeat=False)
- # Compute lower bounds on the log likelihood.
- elbo_ll_per_seq, _, _ = bounds.iwae(
- model, (inputs, targets), lengths, num_samples=1,
- parallel_iterations=config.parallel_iterations
- )
- iwae_ll_per_seq, _, _ = bounds.iwae(
- model, (inputs, targets), lengths, num_samples=config.num_samples,
- parallel_iterations=config.parallel_iterations
- )
- # The resampling type should only be used for training, so we ignore it.
- fivo_ll_per_seq, _, _, _ = bounds.fivo(
- model, (inputs, targets), lengths, num_samples=config.num_samples,
- resampling_criterion=smc.ess_criterion, random_seed=config.random_seed,
- parallel_iterations=config.parallel_iterations
- )
- elbo_ll = tf.reduce_sum(elbo_ll_per_seq)
- iwae_ll = tf.reduce_sum(iwae_ll_per_seq)
- fivo_ll = tf.reduce_sum(fivo_ll_per_seq)
- batch_size = tf.shape(lengths)[0]
- total_batch_length = tf.reduce_sum(lengths)
- return ((elbo_ll, iwae_ll, fivo_ll), total_batch_length, batch_size,
- global_step)
-
- def average_bounds_over_dataset(lower_bounds, total_batch_length, batch_size,
- sess):
- """Computes the values of the bounds, averaged over the datset.
-
- Args:
- lower_bounds: Tuple of float Tensors containing the values of the bounds
- evaluated on a single batch.
- total_batch_length: Integer Tensor that represents the total number of
- timesteps in the current batch.
- batch_size: Integer Tensor containing the batch size. This can vary if the
- requested batch_size does not evenly divide the size of the dataset.
- sess: A TensorFlow Session object.
- Returns:
- ll_per_t: A length 3 numpy array of floats containing each bound's average
- value, normalized by the total number of timesteps in the datset. Can
- be interpreted as a lower bound on the average log likelihood per
- timestep in the dataset.
- ll_per_seq: A length 3 numpy array of floats containing each bound's
- average value, normalized by the number of sequences in the dataset.
- Can be interpreted as a lower bound on the average log likelihood per
- sequence in the datset.
- """
- total_ll = np.zeros(3, dtype=np.float64)
- total_n_elems = 0.0
- total_length = 0.0
- while True:
- try:
- outs = sess.run([lower_bounds, batch_size, total_batch_length])
- except tf.errors.OutOfRangeError:
- break
- total_ll += outs[0]
- total_n_elems += outs[1]
- total_length += outs[2]
- ll_per_t = total_ll / total_length
- ll_per_seq = total_ll / total_n_elems
- return ll_per_t, ll_per_seq
-
- def summarize_lls(lls_per_t, lls_per_seq, summary_writer, step):
- """Creates log-likelihood lower bound summaries and writes them to disk.
-
- Args:
- lls_per_t: An array of 3 python floats, contains the values of the
- evaluated bounds normalized by the number of timesteps.
- lls_per_seq: An array of 3 python floats, contains the values of the
- evaluated bounds normalized by the number of sequences.
- summary_writer: A tf.SummaryWriter.
- step: The current global step.
- """
- def scalar_summary(name, value):
- value = tf.Summary.Value(tag=name, simple_value=value)
- return tf.Summary(value=[value])
-
- for i, bound in enumerate(["elbo", "iwae", "fivo"]):
- per_t_summary = scalar_summary("%s/%s_ll_per_t" % (config.split, bound),
- lls_per_t[i])
- per_seq_summary = scalar_summary("%s/%s_ll_per_seq" %
- (config.split, bound),
- lls_per_seq[i])
- summary_writer.add_summary(per_t_summary, global_step=step)
- summary_writer.add_summary(per_seq_summary, global_step=step)
- summary_writer.flush()
-
- with tf.Graph().as_default():
- if config.random_seed: tf.set_random_seed(config.random_seed)
- lower_bounds, total_batch_length, batch_size, global_step = create_graph()
- summary_dir = config.logdir + "/" + config.split
- summary_writer = tf.summary.FileWriter(
- summary_dir, flush_secs=15, max_queue=100)
- saver = tf.train.Saver()
- with tf.train.SingularMonitoredSession() as sess:
- wait_for_checkpoint(saver, sess, config.logdir)
- step = sess.run(global_step)
- tf.logging.info("Model restored from step %d, evaluating." % step)
- ll_per_t, ll_per_seq = average_bounds_over_dataset(
- lower_bounds, total_batch_length, batch_size, sess)
- summarize_lls(ll_per_t, ll_per_seq, summary_writer, step)
- tf.logging.info("%s elbo ll/t: %f, iwae ll/t: %f fivo ll/t: %f",
- config.split, ll_per_t[0], ll_per_t[1], ll_per_t[2])
- tf.logging.info("%s elbo ll/seq: %f, iwae ll/seq: %f fivo ll/seq: %f",
- config.split, ll_per_seq[0], ll_per_seq[1], ll_per_seq[2])
-
-
-def run_sample(config, create_dataset_and_model_fn=create_dataset_and_model):
- """Sample from the model. Only pianorolls and pose datasets are supported."""
-
- def sample_from_model(model, initial_state, initial_inputs, mean):
- """Samples a sequence of outputs from the model.
-
- The mean must be supplied -- if it isn't the results will be incorrect.
-
- Args:
- model: A model with sample_step implemented. See models/vrnn.py for an
- example.
- initial_state: The initial state of the model.
- initial_inputs: The initial inputs to feed into the model.
- mean: The mean of the training set, a Tensor of shape [data_dimension].
- Returns:
- samples: A Tensor of shape [sample_length, batch_size, num_timesteps,
- data_dimension] containing the samples from the model.
- """
- initial_state, initial_output = model.sample_step(initial_state,
- initial_inputs, 0)
- output_ta = tf.TensorArray(size=config.sample_length,
- dtype=tf.float32,
- dynamic_size=False,
- clear_after_read=True)
- output_ta = output_ta.write(0, initial_output)
- t0 = tf.constant(1, dtype=tf.int32)
-
- def sample_step(t, state, prev_outputs, output_ta):
- state, output = model.sample_step(state, prev_outputs, t)
- output_ta = output_ta.write(t, output)
- centered_output = output - mean[tf.newaxis, :]
- return t+1, state, centered_output, output_ta
-
- def sample_predicate(t, *unused_args):
- return t < config.sample_length
-
- _, _, _, output_ta = tf.while_loop(
- sample_predicate,
- sample_step,
- loop_vars=(t0, initial_state, initial_output, output_ta),
- parallel_iterations=config.parallel_iterations
- )
- samples = output_ta.stack()
- samples = tf.reshape(samples, [config.sample_length, config.batch_size,
- config.num_samples, config.data_dimension])
- return samples
-
- def create_graph():
- """Creates the graph to sample from the model.
-
- First, the model is conditioned on a prefix by sampling a batch of data
- and trimming it to prefix_length. The configured bound is used to do the
- conditioning. Then the final state from the conditioning is used to sample
- from the model.
-
- Returns:
- samples: A Tensor of shape [sample_length, batch_size,
- num_samples, data_dimension] representing samples from the model.
- prefixes: A Tensor of shape [prefix_length, batch_size, data_dimension]
- representing the prefixes the model was conditioned on.
- """
- inputs, targets, lengths, model, mean = create_dataset_and_model_fn(
- config, split=config.split, shuffle=True, repeat=True)
- input_prefixes = inputs[:config.prefix_length]
- target_prefixes = targets[:config.prefix_length]
- prefix_lengths = tf.ones_like(lengths) * config.prefix_length
- if config.bound == "elbo":
- _, _, state = bounds.iwae(
- model, (input_prefixes, target_prefixes),
- prefix_lengths, num_samples=1)
- elif config.bound == "iwae":
- _, _, state = bounds.iwae(
- model, (input_prefixes, target_prefixes),
- prefix_lengths, num_samples=config.num_samples)
- elif config.bound == "fivo":
- _, _, _, state = bounds.fivo(
- model, (input_prefixes, target_prefixes), prefix_lengths,
- num_samples=config.num_samples,
- resampling_criterion=smc.ess_criterion,
- random_seed=config.random_seed)
- sample_inputs = tf.tile(inputs[config.prefix_length],
- [config.num_samples, 1])
- samples = sample_from_model(model, state, sample_inputs, mean)
- return samples, target_prefixes
-
- with tf.Graph().as_default():
- if config.random_seed:
- tf.set_random_seed(config.random_seed)
- samples, prefixes = create_graph()
- if config.sample_out_dir:
- out_dir = config.sample_our_dir
- else:
- out_dir = config.logdir
- if not tf.gfile.Exists(out_dir):
- tf.gfile.MakeDirs(out_dir)
- with tf.train.SingularMonitoredSession(
- checkpoint_dir=config.logdir) as sess:
- samples_out, prefixes_out = sess.run([samples, prefixes])
- with tf.gfile.Open(os.path.join(out_dir, "samples.npz"), "w") as fout:
- np.save(fout, {"prefixes": prefixes_out, "samples": samples_out})
diff --git a/research/fivo/fivo/runners_test.py b/research/fivo/fivo/runners_test.py
deleted file mode 100644
index eb050c0a0b38b2511f3d2fb9ec846e63ead3b5ac..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/runners_test.py
+++ /dev/null
@@ -1,242 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests for fivo.runners"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import numpy as np
-import tensorflow as tf
-
-from fivo import runners
-from fivo.models import base
-from fivo.models import vrnn
-
-FLAGS = tf.app.flags.FLAGS
-
-
-class RunnersTest(tf.test.TestCase):
-
- def default_config(self):
- class Config(object):
- pass
- config = Config()
- config.model = "vrnn"
- config.latent_size = 64
- config.batch_size = 4
- config.num_samples = 4
- config.resampling_type = "multinomial"
- config.normalize_by_seq_len = True
- config.learning_rate = 0.0001
- config.max_steps = int(1e6)
- config.summarize_every = 50
- # Master must be "" to prevent state from persisting between sessions.
- config.master = ""
- config.task = 0
- config.ps_tasks = 0
- config.stagger_workers = True
- config.random_seed = 1234
- config.parallel_iterations = 1
- config.dataset_type = "pianoroll"
- config.data_dimension = None
- config.dataset_path = os.path.join(
- os.path.dirname(os.path.realpath(__file__)),
- "test_data", "tiny_pianoroll.pkl")
- config.proposal_type = "filtering"
- return config
-
- def run_training_one_step(self, bound, dataset_type, data_dimension,
- dataset_filename, dir_prefix, resampling_type,
- model, batch_size=2, num_samples=3,
- create_dataset_and_model_fn=(runners.create_dataset_and_model)):
- config = self.default_config()
- config.model = model
- config.resampling_type = resampling_type
- config.relaxed_resampling_temperature = 0.5
- config.bound = bound
- config.split = "train"
- config.dataset_type = dataset_type
- config.dataset_path = os.path.join(
- os.path.dirname(os.path.realpath(__file__)),
- "test_data",
- dataset_filename)
- config.max_steps = 1
- config.batch_size = batch_size
- config.num_samples = num_samples
- config.latent_size = 4
- config.data_dimension = data_dimension
- config.logdir = os.path.join(tf.test.get_temp_dir(), "%s-%s-%s-%s" %
- (dir_prefix, bound, dataset_type, model))
- runners.run_train(config,
- create_dataset_and_model_fn=create_dataset_and_model_fn)
- return config
-
- def dummmy_dataset_and_model_fn(self, *unused_args, **unused_kwargs):
- # We ignore the arguments in the dummy but need to preserve prototype.
- batch_elements = 5
- sequence_length = 4
- data_dimensions = 3
- dataset = tf.data.Dataset.from_tensors(
- tf.zeros((sequence_length, batch_elements, data_dimensions),
- dtype=tf.float32))
- inputs = dataset.make_one_shot_iterator().get_next()
- targets = tf.zeros_like(inputs)
- lengths = tf.constant([sequence_length] * batch_elements)
- mean = tf.constant((0.0, 0.0, 0.0))
- model = vrnn.create_vrnn(data_dimensions, 1,
- base.ConditionalNormalDistribution)
- return inputs, targets, lengths, model, mean
-
- def test_training_one_step_fivo_pianoroll_vrnn(self):
- self.run_training_one_step("fivo", "pianoroll", 88, "tiny_pianoroll.pkl",
- "test-training", "multinomial", "vrnn")
-
- def test_training_one_step_iwae_pianoroll_vrnn(self):
- self.run_training_one_step("iwae", "pianoroll", 88, "tiny_pianoroll.pkl",
- "test-training", "multinomial", "vrnn")
-
- def test_training_one_step_elbo_pianoroll_vrnn(self):
- self.run_training_one_step("elbo", "pianoroll", 88, "tiny_pianoroll.pkl",
- "test-training", "multinomial", "vrnn")
-
- def test_training_one_step_fivo_speech_vrnn(self):
- self.run_training_one_step("fivo", "speech", 2, "tiny_speech_dataset.tfrecord",
- "test-training", "multinomial", "vrnn")
-
- def test_training_one_step_iwae_speech_vrnn(self):
- self.run_training_one_step("iwae", "speech", 2, "tiny_speech_dataset.tfrecord",
- "test-training", "multinomial", "vrnn")
-
- def test_training_one_step_elbo_speech_vrnn(self):
- self.run_training_one_step("elbo", "speech", 2, "tiny_speech_dataset.tfrecord",
- "test-training", "multinomial", "vrnn")
-
- def test_training_one_step_fivo_pianoroll_srnn(self):
- self.run_training_one_step("fivo", "pianoroll", 88, "tiny_pianoroll.pkl",
- "test-training", "multinomial", "srnn")
-
- def test_training_one_step_iwae_pianoroll_srnn(self):
- self.run_training_one_step("iwae", "pianoroll", 88, "tiny_pianoroll.pkl",
- "test-training", "multinomial", "srnn")
-
- def test_training_one_step_elbo_pianoroll_srnn(self):
- self.run_training_one_step("elbo", "pianoroll", 88, "tiny_pianoroll.pkl",
- "test-training", "multinomial", "srnn")
-
- def test_training_one_step_fivo_speech_srnn(self):
- self.run_training_one_step("fivo", "speech", 2, "tiny_speech_dataset.tfrecord",
- "test-training", "multinomial", "srnn")
-
- def test_training_one_step_iwae_speech_srnn(self):
- self.run_training_one_step("iwae", "speech", 2, "tiny_speech_dataset.tfrecord",
- "test-training", "multinomial", "srnn")
-
- def test_training_one_step_elbo_speech_srnn(self):
- self.run_training_one_step("elbo", "speech", 2, "tiny_speech_dataset.tfrecord",
- "test-training", "multinomial", "srnn")
-
- def test_training_one_step_fivo_pianoroll_vrnn_relaxed(self):
- self.run_training_one_step("fivo", "pianoroll", 88, "tiny_pianoroll.pkl",
- "test-training", "relaxed", "vrnn")
-
- def test_training_one_step_iwae_pianoroll_vrnn_relaxed(self):
- self.run_training_one_step("iwae", "pianoroll", 88, "tiny_pianoroll.pkl",
- "test-training", "relaxed", "vrnn")
-
- def test_training_one_step_elbo_pianoroll_vrnn_relaxed(self):
- self.run_training_one_step("elbo", "pianoroll", 88, "tiny_pianoroll.pkl",
- "test-training", "relaxed", "vrnn")
-
- def test_training_one_step_fivo_pianoroll_srnn_relaxed(self):
- self.run_training_one_step("fivo", "pianoroll", 88, "tiny_pianoroll.pkl",
- "test-training", "relaxed", "srnn")
-
- def test_training_one_step_iwae_pianoroll_srnn_relaxed(self):
- self.run_training_one_step("iwae", "pianoroll", 88, "tiny_pianoroll.pkl",
- "test-training", "relaxed", "srnn")
-
- def test_training_one_step_elbo_pianoroll_srnn_relaxed(self):
- self.run_training_one_step("elbo", "pianoroll", 88, "tiny_pianoroll.pkl",
- "test-training", "relaxed", "srnn")
-
- def test_eval_vrnn(self):
- self.run_eval("vrnn")
-
- def test_eval_srnn(self):
- self.run_eval("srnn")
-
- def run_eval(self, model):
- config = self.run_training_one_step(
- "fivo", "pianoroll", 88, "tiny_pianoroll.pkl", "test-eval-" + model,
- "multinomial", model)
- config.split = "train"
- runners.run_eval(config)
-
- def test_sampling_vrnn(self):
- self.run_sampling("vrnn")
-
- def test_sampling_srnn(self):
- self.run_sampling("srnn")
-
- def run_sampling(self, model):
- """Test sampling from the model."""
- config = self.run_training_one_step(
- "fivo", "pianoroll", 88, "tiny_pianoroll.pkl", "test-sampling", "multinomial",
- model)
- config.prefix_length = 3
- config.sample_length = 6
- config.split = "train"
- config.sample_out_dir = None
-
- runners.run_sample(config)
- unused_samples = np.load(os.path.join(config.logdir, "samples.npz"))
-
- def test_training_with_custom_fn(self):
- self.run_training_one_step(
- "fivo", "pianoroll", 3, "tiny_pianoroll.pkl",
- "test-training-custom-fn", "multinomial", "vrnn", batch_size=5,
- create_dataset_and_model_fn=self.dummmy_dataset_and_model_fn)
-
- def test_eval_with_custom_fn(self):
- config = self.run_training_one_step(
- "fivo", "pianoroll", 1, "tiny_pianoroll.pkl",
- "test-eval-custom-fn", "multinomial", "vrnn", batch_size=1,
- create_dataset_and_model_fn=self.dummmy_dataset_and_model_fn)
- config.split = "train"
- runners.run_eval(
- config,
- create_dataset_and_model_fn=self.dummmy_dataset_and_model_fn)
-
- def test_sampling_with_custom_fn(self):
- config = self.run_training_one_step(
- "fivo", "pianoroll", 3, "tiny_pianoroll.pkl",
- "test-sample-custom-fn", "multinomial", "vrnn", batch_size=5,
- create_dataset_and_model_fn=self.dummmy_dataset_and_model_fn)
- config.prefix_length = 2
- config.sample_length = 3
- config.split = "train"
- config.sample_out_dir = None
-
- runners.run_sample(
- config,
- create_dataset_and_model_fn=self.dummmy_dataset_and_model_fn)
- unused_samples = np.load(os.path.join(config.logdir, "samples.npz"))
-
-
-if __name__ == "__main__":
- tf.test.main()
diff --git a/research/fivo/fivo/smc.py b/research/fivo/fivo/smc.py
deleted file mode 100644
index 25d4969043e2cb8bc2c2c7a3770d3d2dfcca0bef..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/smc.py
+++ /dev/null
@@ -1,338 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Implementation of sequential Monte Carlo algorithms.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-import fivo.nested_utils as nested
-
-
-def ess_criterion(log_weights, unused_t):
- """A criterion that resamples based on effective sample size."""
- num_particles = tf.shape(log_weights)[0]
- # Calculate the effective sample size.
- ess_num = 2 * tf.reduce_logsumexp(log_weights, axis=0)
- ess_denom = tf.reduce_logsumexp(2 * log_weights, axis=0)
- log_ess = ess_num - ess_denom
- return log_ess <= tf.log(tf.to_float(num_particles) / 2.0)
-
-
-def never_resample_criterion(log_weights, unused_t):
- """A criterion that never resamples."""
- batch_size = tf.shape(log_weights)[1]
- return tf.cast(tf.zeros([batch_size]), tf.bool)
-
-
-def always_resample_criterion(log_weights, unused_t):
- """A criterion resamples at every timestep."""
- batch_size = tf.shape(log_weights)[1]
- return tf.cast(tf.ones([batch_size]), tf.bool)
-
-
-def multinomial_resampling(log_weights, states, num_particles, batch_size,
- random_seed=None):
- """Resample states with multinomial resampling.
-
- Args:
- log_weights: A [num_particles, batch_size] Tensor representing a batch
- of batch_size logits for num_particles-ary Categorical distribution.
- states: A nested list of [batch_size*num_particles, data_size] Tensors that
- will be resampled from the groups of every num_particles-th row.
- num_particles: The number of particles/samples.
- batch_size: The batch size.
- random_seed: The random seed to pass to the resampling operations in
- the particle filter. Mainly useful for testing.
-
- Returns:
- resampled_states: A nested list of [batch_size*num_particles, data_size]
- Tensors resampled via multinomial sampling.
- """
- # Calculate the ancestor indices via resampling. Because we maintain the
- # log unnormalized weights, we pass the weights in as logits, allowing
- # the distribution object to apply a softmax and normalize them.
- resampling_parameters = tf.transpose(log_weights, perm=[1, 0])
- resampling_dist = tf.contrib.distributions.Categorical(
- logits=resampling_parameters)
- ancestors = tf.stop_gradient(
- resampling_dist.sample(sample_shape=num_particles, seed=random_seed))
-
- # Because the batch is flattened, we must modify ancestor_inds to index the
- # proper samples. The particles in the ith filter are distributed every
- # batch_size rows in the batch, and offset i rows from the top. So, to
- # correct the indices we multiply by the batch_size and add the proper offset.
- # Crucially, when ancestor_inds is flattened the layout of the batch is
- # maintained.
- offset = tf.expand_dims(tf.range(batch_size), 0)
- ancestor_inds = tf.reshape(ancestors * batch_size + offset, [-1])
-
- resampled_states = nested.gather_tensors(states, ancestor_inds)
- return resampled_states
-
-
-def _blend_tensor(blending_weights, tensor, num_particles, batch_size):
- """Blend tensor according to the weights.
-
- The first dimension of tensor is actually a 2d index compacted to a 1d
- index and similarly for blended_tensor. So if we index these Tensors
- by [(i, j), k], then
-
- blended_tensor[(i, j), k] =
- sum_l tensor[(l, j), :] * blending_weights[i, j, l].
-
- Args:
- blending_weights: [num_particles, batch_size, num_particles] weights where
- the indices represent [sample index, batch index, blending weight index].
- tensor: [num_particles * batch_size, state_dim] Tensor to be blended.
- num_particles: The number of particles/samples.
- batch_size: The batch size.
-
- Returns:
- blended_tensor: [num_particles*batch_size, state_dim] blended Tensor.
- """
- # tensor is currently [num_particles * batch_size, state_dim], so we reshape
- # it to [num_particles, batch_size, state_dim]. Then, transpose it to
- # [batch_size, state_size, num_particles].
- tensor = tf.transpose(
- tf.reshape(tensor, [num_particles, batch_size, -1]), perm=[1, 2, 0])
- blending_weights = tf.transpose(blending_weights, perm=[1, 2, 0])
- # blendeding_weights is [batch index, blending weight index, sample index].
- # Multiplying these gives a matrix of size [batch_size, state_size,
- # num_particles].
- tensor = tf.matmul(tensor, blending_weights)
- # transpose the tensor to be [num_particles, batch_size, state_size]
- # and then reshape it to match the original format.
- tensor = tf.reshape(tf.transpose(tensor, perm=[2, 0, 1]),
- [num_particles*batch_size, -1])
- return tensor
-
-
-def relaxed_resampling(log_weights, states, num_particles, batch_size,
- temperature=0.5, random_seed=None):
- """Resample states with relaxed resampling.
-
- Draw soft "ancestors" using the Gumbel-Softmax distribution.
-
- Args:
- log_weights: A [num_particles, batch_size] Tensor representing a batch
- of batch_size logits for num_particles-ary Categorical distribution.
- states: A nested list of [batch_size * num_particles, d] Tensors that will
- be resampled from the groups of every num_particles-th row.
- num_particles: The number of particles/samples.
- batch_size: The batch size.
- temperature: The temperature used for the relaxed one hot distribution.
- random_seed: The random seed to pass to the resampling operations in
- the particle filter. Mainly useful for testing.
-
- Returns:
- resampled_states: A nested list of [batch_size * num_particles, d]
- Tensors resampled via multinomial sampling.
- """
- # log_weights are [num_particles, batch_size], so we transpose to get a
- # set of batch_size distributions over [0, num_particles).
- resampling_parameters = tf.transpose(log_weights, perm=[1, 0])
- resampling_dist = tf.contrib.distributions.RelaxedOneHotCategorical(
- temperature,
- logits=resampling_parameters)
-
- # Sample num_particles samples from the distribution, resulting in a
- # [num_particles, batch_size, num_particles] Tensor that represents a set of
- # [num_particles, batch_size] blending weights. The dimensions represent
- # [particle index, batch index, blending weight index].
- ancestors = resampling_dist.sample(sample_shape=num_particles,
- seed=random_seed)
- def map_fn(tensor):
- return _blend_tensor(ancestors, tensor, num_particles, batch_size)
-
- resampled_states = nested.map_nested(map_fn, states)
- return resampled_states
-
-
-def smc(
- transition_fn,
- num_steps,
- num_particles=1,
- resampling_criterion=ess_criterion,
- resampling_fn=multinomial_resampling,
- loop_fn=None,
- parallel_iterations=30,
- swap_memory=True):
- """Run a sequential Monte Carlo (SMC) algorithm.
-
- This method runs an SMC algorithm that evolves systems of particles
- using the supplied transition function for the specified number of steps. The
- particles are optionally resampled using resampling_fn when indicated by
- resampling_criterion.
-
- Args:
- transition_fn: A callable that propogates a batch of particles one step.
- Must accept as arguments a batch of particle states and the current
- timestep. Must return the particle states one timestep in the future, the
- incremental weights of each particle as a [num_samples*batch_size] float
- Tensor, and optionally a set of arguments to pass to the loop_fn. If
- the loop args are not provided, they will be set to None. Before the
- first timestep transition_fn will be called with the arguments None, -1
- and should return the initial particle states.
- num_steps: A [batch_size] Tensor of ints representing the number of steps
- to run each filter for.
- num_particles: A scalar int, the number of particles to use in each filter.
- resampling_criterion: The resampling criterion to use for this particle
- filter. Must accept the current log weights and timestep and
- return a boolean Tensor of shape [batch_size] indicating whether each
- particle filter should resample. See ess_criterion and related functions
- for examples. When resampling_criterion is never_resample_criterion,
- resampling_fn is ignored and never called.
- resampling_fn: A callable that performs the resampling operation. Must
- accept as arguments the log weights, particle states, num_particles,
- and batch_size and return the resampled particle states. See
- multinomial_resampling and relaxed_resampling for examples.
- loop_fn: A callable that performs operations on the weights and
- particle states, useful for accumulating and processing state that
- shouldn't be resampled. At each timestep after (possibly) resampling
- loop_fn will be called with the previous loop_state, a set of arguments
- produced by transition_fn called loop_args, the resampled particle states,
- the current log weights as [num_particles, batch_size] float Tensor, a
- [batch_size] float Tensor representing whether or not each filter
- resampled, the current mask indicating which filters are active, and the
- current timestep. It must return the next loop state. Before the first
- timestep loop_fn will be called with the arguments None, None, None, None,
- -1 and must return the initial loop state. The loop state can be a
- possibly nested structure of Tensors and TensorArrays.
- parallel_iterations: The number of parallel iterations to use for the
- internal while loop. Note that values greater than 1 can introduce
- non-determinism even when resampling is deterministic.
- swap_memory: Whether GPU-CPU memory swapping should be enabled for the
- internal while loop.
-
- Returns:
- log_z_hat: A Tensor of shape [batch_size] containing an estimate of the log
- normalizing constant that converts between the unormalized target
- distribution (as defined by the weights) and the true target distribution.
- log_weights: A Tensor of shape [max_num_steps, batch_size, num_particles]
- containing the log weights at each timestep of the particle filter.
- Will not be valid for timesteps past the supplied num_steps.
- resampled: A float Tensor of shape [max_num_steps, batch_size] indicating
- when the particle filters resampled. Will be 1.0 on timesteps when
- resampling occurred and 0.0 on timesteps when it did not.
- final_loop_state: The final state returned by loop_fn. If loop_fn is None
- then 0 will be returned.
- """
- # batch_size represents the number of particle filters running in parallel.
- batch_size = tf.shape(num_steps)[0]
- # Create a TensorArray where element t is the [num_particles*batch_size]
- # sequence mask for timestep t.
- max_num_steps = tf.reduce_max(num_steps)
- seq_mask = tf.transpose(
- tf.sequence_mask(num_steps, maxlen=max_num_steps, dtype=tf.float32),
- perm=[1, 0])
- seq_mask = tf.tile(seq_mask, [1, num_particles])
- mask_ta = tf.TensorArray(seq_mask.dtype,
- max_num_steps,
- name='mask_ta')
- mask_ta = mask_ta.unstack(seq_mask)
- # Initialize the state.
- t0 = tf.constant(0, tf.int32)
- init_particle_state = transition_fn(None, -1)
-
- def transition(*args):
- transition_outs = transition_fn(*args)
- if len(transition_outs) == 2:
- return transition_outs + (None,)
- else:
- return transition_outs
-
- if loop_fn is None:
- loop_fn = lambda *args: 0
-
- init_loop_state = loop_fn(None, None, None, None, None, None, -1)
- init_states = (init_particle_state, init_loop_state)
- ta_names = ['log_weights', 'resampled']
- tas = [tf.TensorArray(tf.float32, max_num_steps, name='%s_ta' % n)
- for n in ta_names]
- log_weights_acc = tf.zeros([num_particles, batch_size], dtype=tf.float32)
- log_z_hat_acc = tf.zeros([batch_size], dtype=tf.float32)
-
- def while_predicate(t, *unused_args):
- return t < max_num_steps
-
- def while_step(t, state, tas, log_weights_acc, log_z_hat_acc):
- """Implements one timestep of the particle filter."""
- particle_state, loop_state = state
- cur_mask = nested.read_tas(mask_ta, t)
- # Propagate the particles one step.
- log_alpha, new_particle_state, loop_args = transition(particle_state, t)
- # Update the current weights with the incremental weights.
- log_alpha *= cur_mask
- log_alpha = tf.reshape(log_alpha, [num_particles, batch_size])
- log_weights_acc += log_alpha
-
- should_resample = resampling_criterion(log_weights_acc, t)
-
- if resampling_criterion == never_resample_criterion:
- resampled = tf.to_float(should_resample)
- else:
- # Compute the states as if we did resample.
- resampled_states = resampling_fn(
- log_weights_acc,
- new_particle_state,
- num_particles,
- batch_size)
- # Decide whether or not we should resample; don't resample if we are past
- # the end of a sequence.
- should_resample = tf.logical_and(should_resample,
- cur_mask[:batch_size] > 0.)
- float_should_resample = tf.to_float(should_resample)
- new_particle_state = nested.where_tensors(
- tf.tile(should_resample, [num_particles]),
- resampled_states,
- new_particle_state)
- resampled = float_should_resample
-
- new_loop_state = loop_fn(loop_state, loop_args, new_particle_state,
- log_weights_acc, resampled, cur_mask, t)
- # Update log Z hat.
- log_z_hat_update = tf.reduce_logsumexp(
- log_weights_acc, axis=0) - tf.log(tf.to_float(num_particles))
- # If it is the last timestep, always add the update.
- log_z_hat_acc += tf.cond(t < max_num_steps - 1,
- lambda: log_z_hat_update * resampled,
- lambda: log_z_hat_update)
- # Update the TensorArrays before we reset the weights so that we capture
- # the incremental weights and not zeros.
- ta_updates = [log_weights_acc, resampled]
- new_tas = [ta.write(t, x) for ta, x in zip(tas, ta_updates)]
- # For the particle filters that resampled, reset weights to zero.
- log_weights_acc *= (1. - tf.tile(resampled[tf.newaxis, :],
- [num_particles, 1]))
- new_state = (new_particle_state, new_loop_state)
- return t + 1, new_state, new_tas, log_weights_acc, log_z_hat_acc
-
- _, final_state, tas, _, log_z_hat = tf.while_loop(
- while_predicate,
- while_step,
- loop_vars=(t0, init_states, tas, log_weights_acc, log_z_hat_acc),
- parallel_iterations=parallel_iterations,
- swap_memory=swap_memory)
-
- log_weights, resampled = [x.stack() for x in tas]
- log_weights = tf.transpose(log_weights, perm=[0, 2, 1])
- final_particle_state, final_loop_state = final_state
- return (log_z_hat, log_weights, resampled,
- final_particle_state, final_loop_state)
diff --git a/research/fivo/fivo/smc_test.py b/research/fivo/fivo/smc_test.py
deleted file mode 100644
index ae32a62f21e037252bda44e3e1f47e007c9b7b9b..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/smc_test.py
+++ /dev/null
@@ -1,241 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests for fivo.smc."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import scipy
-import tensorflow as tf
-
-from fivo import smc
-
-lse = scipy.special.logsumexp
-
-
-def _simple_transition_fn(state, unused_t):
- if state is None:
- return tf.zeros([4], dtype=tf.float32)
- return tf.constant([5., 4., 1., 0.5]), tf.zeros([4], dtype=tf.float32)
-
-
-def _resample_at_step_criterion(step):
- """A criterion that resamples once at a specific timestep."""
- def criterion(log_weights, t):
- batch_size = tf.shape(log_weights)[1]
- return tf.fill([batch_size], tf.equal(t, step))
- return criterion
-
-
-class SMCTest(tf.test.TestCase):
-
- def test_never_resampling(self):
- """Test that never_resample_criterion makes smc not resample.
-
- Also test that the weights and log_z_hat are computed correctly when never
- resampling.
- """
- tf.set_random_seed(1234)
- with self.test_session() as sess:
- outs = smc.smc(
- _simple_transition_fn,
- num_steps=tf.convert_to_tensor([5, 3]),
- num_particles=2,
- resampling_criterion=smc.never_resample_criterion)
- log_z_hat, weights, resampled = sess.run(outs[0:3])
- gt_weights = np.array(
- [[[5, 1], [4, .5]],
- [[10, 2], [8, 1]],
- [[15, 3], [12, 1.5]],
- [[20, 4], [12, 1.5]],
- [[25, 5], [12, 1.5]]],
- dtype=np.float32)
- gt_log_z_hat = np.array(
- [lse([25, 5]) - np.log(2),
- lse([12, 1.5]) - np.log(2)],
- dtype=np.float32)
- self.assertAllClose(gt_log_z_hat, log_z_hat)
- self.assertAllClose(gt_weights, weights)
- self.assertAllEqual(np.zeros_like(resampled), resampled)
-
- def test_always_resampling(self):
- """Test always_resample_criterion makes smc always resample.
-
- Past a sequence end the filter should not resample, however.
- Also check that weights and log_z_hat estimate are correct.
- """
- tf.set_random_seed(1234)
- with self.test_session() as sess:
- outs = smc.smc(
- _simple_transition_fn,
- num_steps=tf.convert_to_tensor([5, 3]),
- num_particles=2,
- resampling_criterion=smc.always_resample_criterion)
- log_z_hat, weights, resampled = sess.run(outs[0:3])
- gt_weights = np.array(
- [[[5, 1], [4, .5]],
- [[5, 1], [4, .5]],
- [[5, 1], [4, .5]],
- [[5, 1], [0., 0.]],
- [[5, 1], [0., 0.]]],
- dtype=np.float32)
- gt_log_z_hat = np.array(
- [5*lse([5, 1]) - 5*np.log(2),
- 3*lse([4, .5]) - 3*np.log(2)],
- dtype=np.float32)
- gt_resampled = np.array(
- [[1, 1], [1, 1], [1, 1], [1, 0], [1, 0]],
- dtype=np.float32)
- self.assertAllClose(gt_log_z_hat, log_z_hat)
- self.assertAllClose(gt_weights, weights)
- self.assertAllEqual(gt_resampled, resampled)
-
- def test_weights_reset_when_resampling_at_sequence_end(self):
- """Test that the weights are reset when resampling at the sequence end.
-
- When resampling happens on the last timestep of a sequence the weights
- should be set to zero on the next timestep and remain zero afterwards.
- """
- tf.set_random_seed(1234)
- with self.test_session() as sess:
- outs = smc.smc(
- _simple_transition_fn,
- num_steps=tf.convert_to_tensor([5, 3]),
- num_particles=2,
- resampling_criterion=_resample_at_step_criterion(2))
- log_z_hat, weights, resampled = sess.run(outs[0:3])
- gt_log_z = np.array(
- [lse([15, 3]) + lse([10, 2]) - 2*np.log(2),
- lse([12, 1.5]) - np.log(2)],
- dtype=np.float32)
- gt_resampled = np.array(
- [[0, 0], [0, 0], [1, 1], [0, 0], [0, 0]],
- dtype=np.float32)
- gt_weights = np.array(
- [[[5, 1], [4, .5]],
- [[10, 2], [8, 1]],
- [[15, 3], [12, 1.5]],
- [[5, 1], [0, 0]],
- [[10, 2], [0, 0]]],
- dtype=np.float32)
- self.assertAllClose(gt_log_z, log_z_hat)
- self.assertAllEqual(gt_resampled, resampled)
- self.assertAllEqual(gt_weights, weights)
-
- def test_weights_not_updated_past_sequence_end(self):
- """Test that non-zero weights are not updated past the end of a sequence."""
- tf.set_random_seed(1234)
- with self.test_session() as sess:
- outs = smc.smc(
- _simple_transition_fn,
- num_steps=tf.convert_to_tensor([6, 4]),
- num_particles=2,
- resampling_criterion=_resample_at_step_criterion(1))
- log_z_hat, weights, resampled = sess.run(outs[0:3])
- gt_log_z_hat = np.array(
- [lse([10, 2]) + lse([20, 4]) - 2*np.log(2),
- lse([8, 1]) + lse([8, 1]) - 2*np.log(2)],
- dtype=np.float32)
- # Ensure that we only resample on the 2nd timestep.
- gt_resampled = np.array(
- [[0, 0], [1, 1], [0, 0], [0, 0], [0, 0], [0, 0]],
- dtype=np.float32)
- # Ensure that the weights after the end of the sequence don't change.
- # Ensure that the weights after resampling before the end of the sequence
- # do change.
- gt_weights = np.array(
- [[[5, 1], [4, .5]],
- [[10, 2], [8, 1]],
- [[5, 1], [4, .5]],
- [[10, 2], [8, 1]],
- [[15, 3], [8, 1]],
- [[20, 4], [8, 1]]],
- dtype=np.float32)
- self.assertAllClose(gt_log_z_hat, log_z_hat)
- self.assertAllEqual(gt_resampled, resampled)
- self.assertAllEqual(gt_weights, weights)
-
- def test_resampling_on_max_num_steps(self):
- """Test that everything is correct when resampling on step max_num_steps.
-
- When resampling on step max_num_steps (i.e. the last step of the longest
- sequence), ensure that there are no off-by-one errors preventing resampling
- and also that the weights are not updated.
- """
- tf.set_random_seed(1234)
- with self.test_session() as sess:
- outs = smc.smc(
- _simple_transition_fn,
- num_steps=tf.convert_to_tensor([4, 2]),
- num_particles=2,
- resampling_criterion=_resample_at_step_criterion(3))
- log_z_hat, weights, resampled = sess.run(outs[0:3])
- gt_log_z_hat = np.array(
- [lse([20, 4]) - np.log(2),
- lse([8, 1]) - np.log(2)],
- dtype=np.float32)
- # Ensure that we only resample on the 3rd timestep and that the second
- # filter doesn't resample at all because it is only run for 2 steps.
- gt_resampled = np.array(
- [[0, 0], [0, 0], [0, 0], [1, 0]],
- dtype=np.float32)
- gt_weights = np.array(
- [[[5, 1], [4, .5]],
- [[10, 2], [8, 1]],
- [[15, 3], [8, 1]],
- [[20, 4], [8, 1]]],
- dtype=np.float32)
- self.assertAllClose(gt_log_z_hat, log_z_hat)
- self.assertAllEqual(gt_resampled, resampled)
- self.assertAllEqual(gt_weights, weights)
-
- def test_multinomial_resampling(self):
- """Test that mulitnomial resampling selects the correct states."""
- tf.set_random_seed(1234)
- with self.test_session() as sess:
- # Setup input.
- inf = 1000.0 # Very large value in log space.
- num_samples = 2
- batch_size = 2
- log_weights = tf.convert_to_tensor([[inf, 0], [0, inf]])
- states = tf.convert_to_tensor([1, 2, 3, 4])
- # Run test.
- resampled_states = smc.multinomial_resampling(
- log_weights, states, num_samples, batch_size, random_seed=0)
- resampled_states_values = sess.run(resampled_states)
- self.assertAllEqual(resampled_states_values, [1, 4, 1, 4])
-
- def test_blend_tensor(self):
- """Test that relaxed resampling blends the correct states."""
- tf.set_random_seed(1234)
- with self.test_session() as sess:
- # Setup input.
- num_samples = 2
- batch_size = 2
- blending_weights = tf.convert_to_tensor(
- [[[0.5, 0.5], [0.25, 0.75]], [[0.75, 0.25], [0.5, 0.5]]])
- states = tf.convert_to_tensor([4., 8., 12., 16.])
- # Run test.
- blended_states = smc._blend_tensor(blending_weights, states,
- num_samples, batch_size)
- blended_states_values = sess.run(blended_states)
- self.assertAllClose(blended_states_values[:, 0], [8., 14., 6., 12.])
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/fivo/fivo/test_data/tiny_pianoroll.pkl b/research/fivo/fivo/test_data/tiny_pianoroll.pkl
deleted file mode 100644
index c5501c6ceac1a6601b5f1be4c422be4f2c1baa86..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/test_data/tiny_pianoroll.pkl
+++ /dev/null
@@ -1,10979 +0,0 @@
-(dp1
-S'train_mean'
-p2
-cnumpy.core.multiarray
-_reconstruct
-p3
-(cnumpy
-ndarray
-p4
-(I0
-tS'b'
-tRp5
-(I1
-(I88
-tcnumpy
-dtype
-p6
-(S'f8'
-I0
-I1
-tRp7
-(I3
-S'<'
-NNNI-1
-I-1
-I0
-tbI00
-S'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9e0^X\xbez,?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x9e0^X\xbez\x00\x00\x00\x00\x00\x00\x00\x00\xde\xecw\x04\xe1\xe8\x90?\\\x9c\xe1\x08\xef\x9c@?\\\x9c\xe1\x08\xef\x9cp?Y\xfb\xb4\x11\x0b\x05\x80?&\xc3MBx\xf6}?\xb4+\xe5\xc8#\xea\x94?}\xe6\x9f\xb0\xd6\x8bf?`\xa9\xbfQ\xa9\xec\xac?\x9d\xc4\xac\x06\xe8\xc2\x90?&\xc3MBx\xf6\x9d?\x02\xd8b\xa3\xaco\x97?\xb0\x8a\xb8\xd1?R\x94?\xbeMQ\x11F\x93\xc7?\x1bt\x16\x0b\xf6v\x80?\x85\xf0\xec;\xa0\xa2\xb3?"\xb6o\xf9\xbd\xa6\xb1?,\xf4as_\\\xb6?\xbf\xe7\xa3\x08\xb2b\xbb?\xa7\xa72\xec\x93\x8a\x92?\x07%\xfd\x05\x13\xe2\xd1?\xaaY\xa4\xa0X\xec\xab?\x1f\x81\xf4S\xb0\xc6\xbc?\x92t\x9f\x180\x02\xb6?\xa2\xf4\xea\x80\x99\xe7\xbb?jm=\xe14\xe4\xd4?\xab\xb4\x105N\xda\x8e?F\xfc\xc6,\x7f\x1b\xcb?^\xfe\'\x9d\\S\xc0?\xf30P\x95%;\xc6?4=\x95a\x9fT\xc4?\xfe\x80]\x83\xdd\xfb\x90?R\xf4\xe9\xaa\xe2\xb1\xda?\xe5\xe4\xa9\x1b\x94\xf4\xa7?\xcbH\xf6\xb3J\xed\xbe?v\xa4F\xc2\x0e\\\xb5?\xe3\xc1I\xea\x9c\x1f\xb9?\xca\x8f\x9bf\xbeM\xd1?\\\x9c\xe1\x08\xef\x9cp?\xdeG\xe4\x98\xd6\xd6\xc3?M\x99\x8c\xaf<9\xaf?BJUx\xba\xb9\xb1?\xb2R\xacnA9\xb0?\x83(\xf9\x9e\x9e\xbbg?@pFg\xa2\xc7\xaf?\x80\x87\xcc\xa7\xba#g?+\x99\xf5\xdein\x83?}\xe6\x9f\xb0\xd6\x8bf?b\xde:\xf7\xb6\xccQ?\x83(\xf9\x9e\x9e\xbbW?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
-tbsS'train'
-p8
-(lp9
-(lp10
-(cnumpy.core.multiarray
-scalar
-p11
-(g6
-(S'i8'
-I0
-I1
-tRp12
-(I3
-S'<'
-NNNI-1
-I-1
-I0
-tbS'<\x00\x00\x00\x00\x00\x00\x00'
-tRp13
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp14
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp15
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp16
-tp17
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp18
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp19
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp20
-tp21
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp22
-g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp23
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp24
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp25
-tp26
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp27
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp28
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp29
-tp30
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp31
-g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp32
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp33
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp34
-tp35
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp36
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp37
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp38
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp39
-tp40
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp41
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp42
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp43
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp44
-tp45
-a(g11
-(g12
-S':\x00\x00\x00\x00\x00\x00\x00'
-tRp46
-g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp47
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp48
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp49
-tp50
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp51
-g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp52
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp53
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp54
-tp55
-a(g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp56
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp57
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp58
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp59
-tp60
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp61
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp62
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp63
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp64
-tp65
-a(g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp66
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp67
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp68
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp69
-tp70
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp71
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp72
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp73
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp74
-tp75
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp76
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp77
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp78
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp79
-tp80
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp81
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp82
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp83
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp84
-tp85
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp86
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp87
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp88
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp89
-tp90
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp91
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp92
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp93
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp94
-tp95
-a(g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp96
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp97
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp98
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp99
-tp100
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp101
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp102
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp103
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp104
-tp105
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp106
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp107
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp108
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp109
-tp110
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp111
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp112
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp113
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp114
-tp115
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp116
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp117
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp118
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp119
-tp120
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp121
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp122
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp123
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp124
-tp125
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp126
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp127
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp128
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp129
-tp130
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp131
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp132
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp133
-tp134
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp135
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp136
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp137
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp138
-tp139
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp140
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp141
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp142
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp143
-tp144
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp145
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp146
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp147
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp148
-tp149
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp150
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp151
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp152
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp153
-tp154
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp155
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp156
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp157
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp158
-tp159
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp160
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp161
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp162
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp163
-tp164
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp165
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp166
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp167
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp168
-tp169
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp170
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp171
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp172
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp173
-tp174
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp175
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp176
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp177
-tp178
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp179
-g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp180
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp181
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp182
-tp183
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp184
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp185
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp186
-tp187
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp188
-g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp189
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp190
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp191
-tp192
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp193
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp194
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp195
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp196
-tp197
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp198
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp199
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp200
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp201
-tp202
-a(g11
-(g12
-S':\x00\x00\x00\x00\x00\x00\x00'
-tRp203
-g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp204
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp205
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp206
-tp207
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp208
-g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp209
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp210
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp211
-tp212
-a(g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp213
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp214
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp215
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp216
-tp217
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp218
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp219
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp220
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp221
-tp222
-a(g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp223
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp224
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp225
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp226
-tp227
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp228
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp229
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp230
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp231
-tp232
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp233
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp234
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp235
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp236
-tp237
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp238
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp239
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp240
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp241
-tp242
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp243
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp244
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp245
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp246
-tp247
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp248
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp249
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp250
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp251
-tp252
-a(g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp253
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp254
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp255
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp256
-tp257
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp258
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp259
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp260
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp261
-tp262
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp263
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp264
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp265
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp266
-tp267
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp268
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp269
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp270
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp271
-tp272
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp273
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp274
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp275
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp276
-tp277
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp278
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp279
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp280
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp281
-tp282
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp283
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp284
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp285
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp286
-tp287
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp288
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp289
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp290
-tp291
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp292
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp293
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp294
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp295
-tp296
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp297
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp298
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp299
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp300
-tp301
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp302
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp303
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp304
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp305
-tp306
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp307
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp308
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp309
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp310
-tp311
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp312
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp313
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp314
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp315
-tp316
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp317
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp318
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp319
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp320
-tp321
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp322
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp323
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp324
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp325
-tp326
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp327
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp328
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp329
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp330
-tp331
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp332
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp333
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp334
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp335
-tp336
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp337
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp338
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp339
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp340
-tp341
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp342
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp343
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp344
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp345
-tp346
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp347
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp348
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp349
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp350
-tp351
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp352
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp353
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp354
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp355
-tp356
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp357
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp358
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp359
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp360
-tp361
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp362
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp363
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp364
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp365
-tp366
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp367
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp368
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp369
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp370
-tp371
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp372
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp373
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp374
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp375
-tp376
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp377
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp378
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp379
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp380
-tp381
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp382
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp383
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp384
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp385
-tp386
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp387
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp388
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp389
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp390
-tp391
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp392
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp393
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp394
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp395
-tp396
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp397
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp398
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp399
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp400
-tp401
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp402
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp403
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp404
-tp405
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp406
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp407
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp408
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp409
-tp410
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp411
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp412
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp413
-tp414
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp415
-g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp416
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp417
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp418
-tp419
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp420
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp421
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp422
-tp423
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp424
-g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp425
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp426
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp427
-tp428
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp429
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp430
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp431
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp432
-tp433
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp434
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp435
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp436
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp437
-tp438
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp439
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp440
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp441
-tp442
-a(g11
-(g12
-S'=\x00\x00\x00\x00\x00\x00\x00'
-tRp443
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp444
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp445
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp446
-tp447
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp448
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp449
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp450
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp451
-tp452
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp453
-g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp454
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp455
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp456
-tp457
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp458
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp459
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp460
-tp461
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp462
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp463
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp464
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp465
-tp466
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp467
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp468
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp469
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp470
-tp471
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp472
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp473
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp474
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp475
-tp476
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp477
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp478
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp479
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp480
-tp481
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp482
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp483
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp484
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp485
-tp486
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp487
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp488
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp489
-tp490
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp491
-g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp492
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp493
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp494
-tp495
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp496
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp497
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp498
-tp499
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp500
-g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp501
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp502
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp503
-tp504
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp505
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp506
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp507
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp508
-tp509
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp510
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp511
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp512
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp513
-tp514
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp515
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp516
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp517
-tp518
-a(g11
-(g12
-S'=\x00\x00\x00\x00\x00\x00\x00'
-tRp519
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp520
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp521
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp522
-tp523
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp524
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp525
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp526
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp527
-tp528
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp529
-g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp530
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp531
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp532
-tp533
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp534
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp535
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp536
-tp537
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp538
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp539
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp540
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp541
-tp542
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp543
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp544
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp545
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp546
-tp547
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp548
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp549
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp550
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp551
-tp552
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp553
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp554
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp555
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp556
-tp557
-a(g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp558
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp559
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp560
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp561
-tp562
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp563
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp564
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp565
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp566
-tp567
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp568
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp569
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp570
-tp571
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp572
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp573
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp574
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp575
-tp576
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp577
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp578
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp579
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp580
-tp581
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp582
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp583
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp584
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp585
-tp586
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp587
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp588
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp589
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp590
-tp591
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp592
-g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp593
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp594
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp595
-tp596
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp597
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp598
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp599
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp600
-tp601
-a(g11
-(g12
-S'8\x00\x00\x00\x00\x00\x00\x00'
-tRp602
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp603
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp604
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp605
-tp606
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp607
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp608
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp609
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp610
-tp611
-a(g11
-(g12
-S'6\x00\x00\x00\x00\x00\x00\x00'
-tRp612
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp613
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp614
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp615
-tp616
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp617
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp618
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp619
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp620
-tp621
-a(g11
-(g12
-S'0\x00\x00\x00\x00\x00\x00\x00'
-tRp622
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp623
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp624
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp625
-tp626
-a(g11
-(g12
-S'0\x00\x00\x00\x00\x00\x00\x00'
-tRp627
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp628
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp629
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp630
-tp631
-a(g11
-(g12
-S'0\x00\x00\x00\x00\x00\x00\x00'
-tRp632
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp633
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp634
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp635
-tp636
-a(g11
-(g12
-S'0\x00\x00\x00\x00\x00\x00\x00'
-tRp637
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp638
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp639
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp640
-tp641
-aa(lp642
-(g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp643
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp644
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp645
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp646
-tp647
-a(g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp648
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp649
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp650
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp651
-tp652
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp653
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp654
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp655
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp656
-tp657
-a(g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp658
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp659
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp660
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp661
-tp662
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp663
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp664
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp665
-g11
-(g12
-S'W\x00\x00\x00\x00\x00\x00\x00'
-tRp666
-tp667
-a(g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp668
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp669
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp670
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp671
-tp672
-a(g11
-(g12
-S'?\x00\x00\x00\x00\x00\x00\x00'
-tRp673
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp674
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp675
-tp676
-a(g11
-(g12
-S'8\x00\x00\x00\x00\x00\x00\x00'
-tRp677
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp678
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp679
-tp680
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp681
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp682
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp683
-g11
-(g12
-S'W\x00\x00\x00\x00\x00\x00\x00'
-tRp684
-tp685
-a(g11
-(g12
-S'=\x00\x00\x00\x00\x00\x00\x00'
-tRp686
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp687
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp688
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp689
-tp690
-a(g11
-(g12
-S'?\x00\x00\x00\x00\x00\x00\x00'
-tRp691
-g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp692
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp693
-g11
-(g12
-S'W\x00\x00\x00\x00\x00\x00\x00'
-tRp694
-tp695
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp696
-g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp697
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp698
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp699
-tp700
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp701
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp702
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp703
-tp704
-a(g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp705
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp706
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp707
-tp708
-a(g11
-(g12
-S'?\x00\x00\x00\x00\x00\x00\x00'
-tRp709
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp710
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp711
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp712
-tp713
-a(g11
-(g12
-S'8\x00\x00\x00\x00\x00\x00\x00'
-tRp714
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp715
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp716
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp717
-tp718
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp719
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp720
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp721
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp722
-tp723
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp724
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp725
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp726
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp727
-tp728
-a(g11
-(g12
-S'=\x00\x00\x00\x00\x00\x00\x00'
-tRp729
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp730
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp731
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp732
-tp733
-a(g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp734
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp735
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp736
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp737
-tp738
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp739
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp740
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp741
-g11
-(g12
-S'W\x00\x00\x00\x00\x00\x00\x00'
-tRp742
-tp743
-a(g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp744
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp745
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp746
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp747
-tp748
-a(g11
-(g12
-S'?\x00\x00\x00\x00\x00\x00\x00'
-tRp749
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp750
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp751
-tp752
-a(g11
-(g12
-S'8\x00\x00\x00\x00\x00\x00\x00'
-tRp753
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp754
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp755
-tp756
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp757
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp758
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp759
-g11
-(g12
-S'W\x00\x00\x00\x00\x00\x00\x00'
-tRp760
-tp761
-a(g11
-(g12
-S'=\x00\x00\x00\x00\x00\x00\x00'
-tRp762
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp763
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp764
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp765
-tp766
-a(g11
-(g12
-S'?\x00\x00\x00\x00\x00\x00\x00'
-tRp767
-g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp768
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp769
-g11
-(g12
-S'W\x00\x00\x00\x00\x00\x00\x00'
-tRp770
-tp771
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp772
-g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp773
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp774
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp775
-tp776
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp777
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp778
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp779
-tp780
-a(g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp781
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp782
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp783
-tp784
-a(g11
-(g12
-S'?\x00\x00\x00\x00\x00\x00\x00'
-tRp785
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp786
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp787
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp788
-tp789
-a(g11
-(g12
-S'8\x00\x00\x00\x00\x00\x00\x00'
-tRp790
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp791
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp792
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp793
-tp794
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp795
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp796
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp797
-g11
-(g12
-S'\\\x00\x00\x00\x00\x00\x00\x00'
-tRp798
-tp799
-a(g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp800
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp801
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp802
-g11
-(g12
-S'Z\x00\x00\x00\x00\x00\x00\x00'
-tRp803
-tp804
-a(g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp805
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp806
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp807
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp808
-tp809
-a(g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp810
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp811
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp812
-g11
-(g12
-S'W\x00\x00\x00\x00\x00\x00\x00'
-tRp813
-tp814
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp815
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp816
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp817
-tp818
-a(g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp819
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp820
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp821
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp822
-tp823
-a(g11
-(g12
-S'=\x00\x00\x00\x00\x00\x00\x00'
-tRp824
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp825
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp826
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp827
-tp828
-a(g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp829
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp830
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp831
-g11
-(g12
-S'W\x00\x00\x00\x00\x00\x00\x00'
-tRp832
-tp833
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp834
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp835
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp836
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp837
-tp838
-a(g11
-(g12
-S'?\x00\x00\x00\x00\x00\x00\x00'
-tRp839
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp840
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp841
-g11
-(g12
-S'Z\x00\x00\x00\x00\x00\x00\x00'
-tRp842
-tp843
-a(g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp844
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp845
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp846
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp847
-tp848
-a(g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp849
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp850
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp851
-g11
-(g12
-S'W\x00\x00\x00\x00\x00\x00\x00'
-tRp852
-tp853
-a(g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp854
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp855
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp856
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp857
-tp858
-a(g11
-(g12
-S'?\x00\x00\x00\x00\x00\x00\x00'
-tRp859
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp860
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp861
-g11
-(g12
-S'W\x00\x00\x00\x00\x00\x00\x00'
-tRp862
-tp863
-a(g11
-(g12
-S'?\x00\x00\x00\x00\x00\x00\x00'
-tRp864
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp865
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp866
-g11
-(g12
-S'W\x00\x00\x00\x00\x00\x00\x00'
-tRp867
-tp868
-a(g11
-(g12
-S'?\x00\x00\x00\x00\x00\x00\x00'
-tRp869
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp870
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp871
-g11
-(g12
-S'W\x00\x00\x00\x00\x00\x00\x00'
-tRp872
-tp873
-a(g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp874
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp875
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp876
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp877
-tp878
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp879
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp880
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp881
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp882
-tp883
-a(g11
-(g12
-S'?\x00\x00\x00\x00\x00\x00\x00'
-tRp884
-g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp885
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp886
-g11
-(g12
-S'W\x00\x00\x00\x00\x00\x00\x00'
-tRp887
-tp888
-a(g11
-(g12
-S'=\x00\x00\x00\x00\x00\x00\x00'
-tRp889
-g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp890
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp891
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp892
-tp893
-a(g11
-(g12
-S'?\x00\x00\x00\x00\x00\x00\x00'
-tRp894
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp895
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp896
-g11
-(g12
-S'Z\x00\x00\x00\x00\x00\x00\x00'
-tRp897
-tp898
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp899
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp900
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp901
-g11
-(g12
-S'\\\x00\x00\x00\x00\x00\x00\x00'
-tRp902
-tp903
-a(g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp904
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp905
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp906
-g11
-(g12
-S'Z\x00\x00\x00\x00\x00\x00\x00'
-tRp907
-tp908
-a(g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp909
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp910
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp911
-g11
-(g12
-S'W\x00\x00\x00\x00\x00\x00\x00'
-tRp912
-tp913
-a(g11
-(g12
-S'F\x00\x00\x00\x00\x00\x00\x00'
-tRp914
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp915
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp916
-g11
-(g12
-S'Z\x00\x00\x00\x00\x00\x00\x00'
-tRp917
-tp918
-a(g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp919
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp920
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp921
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp922
-tp923
-a(g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp924
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp925
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp926
-g11
-(g12
-S'W\x00\x00\x00\x00\x00\x00\x00'
-tRp927
-tp928
-a(g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp929
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp930
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp931
-g11
-(g12
-S'\\\x00\x00\x00\x00\x00\x00\x00'
-tRp932
-tp933
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp934
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp935
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp936
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp937
-tp938
-a(g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp939
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp940
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp941
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp942
-tp943
-a(g11
-(g12
-S'8\x00\x00\x00\x00\x00\x00\x00'
-tRp944
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp945
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp946
-g11
-(g12
-S'W\x00\x00\x00\x00\x00\x00\x00'
-tRp947
-tp948
-a(g11
-(g12
-S'=\x00\x00\x00\x00\x00\x00\x00'
-tRp949
-g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp950
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp951
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp952
-tp953
-a(g11
-(g12
-S'=\x00\x00\x00\x00\x00\x00\x00'
-tRp954
-g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp955
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp956
-g11
-(g12
-S'U\x00\x00\x00\x00\x00\x00\x00'
-tRp957
-tp958
-aa(lp959
-(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp960
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp961
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp962
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp963
-tp964
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp965
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp966
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp967
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp968
-tp969
-a(g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp970
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp971
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp972
-tp973
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp974
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp975
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp976
-g11
-(g12
-S']\x00\x00\x00\x00\x00\x00\x00'
-tRp977
-tp978
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp979
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp980
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp981
-g11
-(g12
-S']\x00\x00\x00\x00\x00\x00\x00'
-tRp982
-tp983
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp984
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp985
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp986
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp987
-tp988
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp989
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp990
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp991
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp992
-tp993
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp994
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp995
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp996
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp997
-tp998
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp999
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1000
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1001
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp1002
-tp1003
-a(g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1004
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1005
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1006
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp1007
-tp1008
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1009
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1010
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1011
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp1012
-tp1013
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1014
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1015
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1016
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1017
-tp1018
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1019
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1020
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1021
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp1022
-tp1023
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1024
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1025
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1026
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1027
-tp1028
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1029
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1030
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1031
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1032
-tp1033
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1034
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1035
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1036
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1037
-tp1038
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1039
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1040
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1041
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1042
-tp1043
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1044
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1045
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1046
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1047
-tp1048
-a(g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1049
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1050
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1051
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1052
-tp1053
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1054
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1055
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1056
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp1057
-tp1058
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1059
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1060
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1061
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp1062
-tp1063
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1064
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1065
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1066
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1067
-tp1068
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1069
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1070
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1071
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1072
-tp1073
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1074
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1075
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1076
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1077
-tp1078
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1079
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1080
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1081
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1082
-tp1083
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1084
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1085
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1086
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp1087
-tp1088
-a(g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1089
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1090
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1091
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp1092
-tp1093
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1094
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1095
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1096
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp1097
-tp1098
-a(g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1099
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1100
-g11
-(g12
-S'Z\x00\x00\x00\x00\x00\x00\x00'
-tRp1101
-tp1102
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1103
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1104
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1105
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp1106
-tp1107
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1108
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1109
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1110
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp1111
-tp1112
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1113
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1114
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1115
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp1116
-tp1117
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1118
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1119
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1120
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp1121
-tp1122
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1123
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1124
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1125
-g11
-(g12
-S']\x00\x00\x00\x00\x00\x00\x00'
-tRp1126
-tp1127
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1128
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1129
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp1130
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp1131
-tp1132
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1133
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1134
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp1135
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp1136
-tp1137
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1138
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp1139
-g11
-(g12
-S'W\x00\x00\x00\x00\x00\x00\x00'
-tRp1140
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp1141
-tp1142
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1143
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1144
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1145
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp1146
-tp1147
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1148
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1149
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1150
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp1151
-tp1152
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1153
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1154
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1155
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp1156
-tp1157
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1158
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1159
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1160
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp1161
-tp1162
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1163
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1164
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1165
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1166
-tp1167
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1168
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1169
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1170
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp1171
-tp1172
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1173
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1174
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1175
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1176
-tp1177
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1178
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1179
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1180
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1181
-tp1182
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1183
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1184
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1185
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1186
-tp1187
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1188
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1189
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1190
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1191
-tp1192
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1193
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1194
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1195
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1196
-tp1197
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1198
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1199
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1200
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1201
-tp1202
-aa(lp1203
-(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp1204
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1205
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1206
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1207
-tp1208
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1209
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1210
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1211
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1212
-tp1213
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1214
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1215
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1216
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1217
-tp1218
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1219
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1220
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1221
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1222
-tp1223
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1224
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1225
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1226
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1227
-tp1228
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1229
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1230
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1231
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1232
-tp1233
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1234
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1235
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1236
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1237
-tp1238
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1239
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1240
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1241
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1242
-tp1243
-a(g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp1244
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1245
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1246
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1247
-tp1248
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1249
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1250
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1251
-tp1252
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1253
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1254
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1255
-tp1256
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1257
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1258
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1259
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1260
-tp1261
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1262
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1263
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1264
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1265
-tp1266
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1267
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1268
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1269
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1270
-tp1271
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1272
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1273
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1274
-tp1275
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1276
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1277
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1278
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1279
-tp1280
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1281
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1282
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1283
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1284
-tp1285
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1286
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1287
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1288
-tp1289
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1290
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1291
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1292
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1293
-tp1294
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1295
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1296
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1297
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1298
-tp1299
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1300
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1301
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1302
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1303
-tp1304
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1305
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1306
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1307
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1308
-tp1309
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1310
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1311
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1312
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1313
-tp1314
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1315
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1316
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1317
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1318
-tp1319
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp1320
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1321
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1322
-tp1323
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1324
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1325
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1326
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1327
-tp1328
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp1329
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1330
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1331
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp1332
-tp1333
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1334
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1335
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1336
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1337
-tp1338
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1339
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1340
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1341
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1342
-tp1343
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1344
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1345
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1346
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1347
-tp1348
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1349
-g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp1350
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1351
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1352
-tp1353
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1354
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1355
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1356
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1357
-tp1358
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1359
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1360
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1361
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1362
-tp1363
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1364
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1365
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1366
-tp1367
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1368
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1369
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1370
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1371
-tp1372
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1373
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1374
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1375
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1376
-tp1377
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1378
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1379
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1380
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp1381
-tp1382
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1383
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1384
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1385
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1386
-tp1387
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1388
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1389
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1390
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1391
-tp1392
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1393
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1394
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1395
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1396
-tp1397
-a(g11
-(g12
-S'=\x00\x00\x00\x00\x00\x00\x00'
-tRp1398
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1399
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1400
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1401
-tp1402
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1403
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1404
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1405
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1406
-tp1407
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1408
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1409
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp1410
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1411
-tp1412
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp1413
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1414
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp1415
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp1416
-tp1417
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1418
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1419
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1420
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1421
-tp1422
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1423
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1424
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1425
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1426
-tp1427
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1428
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1429
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1430
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1431
-tp1432
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1433
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1434
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1435
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1436
-tp1437
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1438
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1439
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1440
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1441
-tp1442
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1443
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1444
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1445
-tp1446
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1447
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1448
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1449
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1450
-tp1451
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1452
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1453
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1454
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1455
-tp1456
-a(g11
-(g12
-S'8\x00\x00\x00\x00\x00\x00\x00'
-tRp1457
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1458
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1459
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1460
-tp1461
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp1462
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1463
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1464
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1465
-tp1466
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp1467
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1468
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1469
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1470
-tp1471
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp1472
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1473
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1474
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1475
-tp1476
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp1477
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1478
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1479
-tp1480
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1481
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1482
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1483
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1484
-tp1485
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp1486
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1487
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1488
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1489
-tp1490
-a(g11
-(g12
-S'5\x00\x00\x00\x00\x00\x00\x00'
-tRp1491
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1492
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1493
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1494
-tp1495
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1496
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1497
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1498
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1499
-tp1500
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1501
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1502
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1503
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1504
-tp1505
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1506
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1507
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1508
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1509
-tp1510
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1511
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1512
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1513
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1514
-tp1515
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1516
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1517
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1518
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1519
-tp1520
-aa(lp1521
-(g11
-(g12
-S'0\x00\x00\x00\x00\x00\x00\x00'
-tRp1522
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1523
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1524
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1525
-tp1526
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1527
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1528
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1529
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1530
-tp1531
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp1532
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1533
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1534
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp1535
-tp1536
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1537
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1538
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1539
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1540
-tp1541
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1542
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1543
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1544
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1545
-tp1546
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1547
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1548
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1549
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1550
-tp1551
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1552
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1553
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1554
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1555
-tp1556
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1557
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1558
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1559
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1560
-tp1561
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1562
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1563
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1564
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1565
-tp1566
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1567
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1568
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1569
-tp1570
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1571
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1572
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1573
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1574
-tp1575
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1576
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1577
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1578
-tp1579
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1580
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1581
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1582
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1583
-tp1584
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1585
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1586
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1587
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1588
-tp1589
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1590
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1591
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1592
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1593
-tp1594
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1595
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1596
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1597
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1598
-tp1599
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1600
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1601
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1602
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1603
-tp1604
-a(g11
-(g12
-S'0\x00\x00\x00\x00\x00\x00\x00'
-tRp1605
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1606
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1607
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1608
-tp1609
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp1610
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1611
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1612
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1613
-tp1614
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1615
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1616
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1617
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1618
-tp1619
-a(g11
-(g12
-S'5\x00\x00\x00\x00\x00\x00\x00'
-tRp1620
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1621
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1622
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1623
-tp1624
-a(g11
-(g12
-S'4\x00\x00\x00\x00\x00\x00\x00'
-tRp1625
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1626
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1627
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1628
-tp1629
-a(g11
-(g12
-S'2\x00\x00\x00\x00\x00\x00\x00'
-tRp1630
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1631
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1632
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1633
-tp1634
-a(g11
-(g12
-S'0\x00\x00\x00\x00\x00\x00\x00'
-tRp1635
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1636
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1637
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1638
-tp1639
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1640
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1641
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1642
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1643
-tp1644
-a(g11
-(g12
-S'5\x00\x00\x00\x00\x00\x00\x00'
-tRp1645
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1646
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1647
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1648
-tp1649
-a(g11
-(g12
-S'4\x00\x00\x00\x00\x00\x00\x00'
-tRp1650
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1651
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp1652
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1653
-tp1654
-a(g11
-(g12
-S'2\x00\x00\x00\x00\x00\x00\x00'
-tRp1655
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1656
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1657
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1658
-tp1659
-a(g11
-(g12
-S'4\x00\x00\x00\x00\x00\x00\x00'
-tRp1660
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1661
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1662
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1663
-tp1664
-a(g11
-(g12
-S'5\x00\x00\x00\x00\x00\x00\x00'
-tRp1665
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1666
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1667
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1668
-tp1669
-a(g11
-(g12
-S'4\x00\x00\x00\x00\x00\x00\x00'
-tRp1670
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1671
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1672
-tp1673
-a(g11
-(g12
-S'5\x00\x00\x00\x00\x00\x00\x00'
-tRp1674
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1675
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1676
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1677
-tp1678
-a(g11
-(g12
-S'2\x00\x00\x00\x00\x00\x00\x00'
-tRp1679
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1680
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1681
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1682
-tp1683
-a(g11
-(g12
-S'0\x00\x00\x00\x00\x00\x00\x00'
-tRp1684
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1685
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1686
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1687
-tp1688
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1689
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1690
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1691
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1692
-tp1693
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp1694
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1695
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1696
-tp1697
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1698
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1699
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1700
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1701
-tp1702
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp1703
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1704
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1705
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1706
-tp1707
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp1708
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1709
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1710
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp1711
-tp1712
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1713
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1714
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1715
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1716
-tp1717
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1718
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1719
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1720
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1721
-tp1722
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1723
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1724
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1725
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1726
-tp1727
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1728
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1729
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1730
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1731
-tp1732
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1733
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1734
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1735
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1736
-tp1737
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1738
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1739
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1740
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1741
-tp1742
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1743
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1744
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1745
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1746
-tp1747
-a(g11
-(g12
-S'5\x00\x00\x00\x00\x00\x00\x00'
-tRp1748
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1749
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1750
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1751
-tp1752
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1753
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1754
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1755
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1756
-tp1757
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1758
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1759
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1760
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1761
-tp1762
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1763
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1764
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1765
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1766
-tp1767
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1768
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1769
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1770
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1771
-tp1772
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1773
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1774
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1775
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp1776
-tp1777
-a(g11
-(g12
-S'4\x00\x00\x00\x00\x00\x00\x00'
-tRp1778
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1779
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1780
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp1781
-tp1782
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1783
-g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp1784
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1785
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1786
-tp1787
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1788
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1789
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1790
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1791
-tp1792
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp1793
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1794
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1795
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1796
-tp1797
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp1798
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1799
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1800
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1801
-tp1802
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1803
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1804
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1805
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1806
-tp1807
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1808
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1809
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1810
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1811
-tp1812
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1813
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1814
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1815
-tp1816
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1817
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1818
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1819
-tp1820
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1821
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1822
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1823
-tp1824
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1825
-g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp1826
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1827
-tp1828
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp1829
-g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1830
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1831
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1832
-tp1833
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp1834
-g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1835
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1836
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1837
-tp1838
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp1839
-g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1840
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1841
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1842
-tp1843
-a(g11
-(g12
-S'4\x00\x00\x00\x00\x00\x00\x00'
-tRp1844
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1845
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1846
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp1847
-tp1848
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp1849
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1850
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp1851
-tp1852
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1853
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1854
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1855
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp1856
-tp1857
-a(g11
-(g12
-S'5\x00\x00\x00\x00\x00\x00\x00'
-tRp1858
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1859
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1860
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1861
-tp1862
-a(g11
-(g12
-S'4\x00\x00\x00\x00\x00\x00\x00'
-tRp1863
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1864
-g11
-(g12
-S'I\x00\x00\x00\x00\x00\x00\x00'
-tRp1865
-tp1866
-a(g11
-(g12
-S'2\x00\x00\x00\x00\x00\x00\x00'
-tRp1867
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1868
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1869
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1870
-tp1871
-a(g11
-(g12
-S'=\x00\x00\x00\x00\x00\x00\x00'
-tRp1872
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1873
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1874
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1875
-tp1876
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp1877
-g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1878
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1879
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1880
-tp1881
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp1882
-g11
-(g12
-S'=\x00\x00\x00\x00\x00\x00\x00'
-tRp1883
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1884
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1885
-tp1886
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1887
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1888
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1889
-tp1890
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp1891
-g11
-(g12
-S'=\x00\x00\x00\x00\x00\x00\x00'
-tRp1892
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1893
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1894
-tp1895
-a(g11
-(g12
-S'2\x00\x00\x00\x00\x00\x00\x00'
-tRp1896
-g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1897
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1898
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1899
-tp1900
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp1901
-g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1902
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1903
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1904
-tp1905
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1906
-g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1907
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1908
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1909
-tp1910
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp1911
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1912
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1913
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1914
-tp1915
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp1916
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1917
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1918
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1919
-tp1920
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp1921
-g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp1922
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1923
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1924
-tp1925
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1926
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1927
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1928
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1929
-tp1930
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp1931
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1932
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1933
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1934
-tp1935
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1936
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1937
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1938
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1939
-tp1940
-a(g11
-(g12
-S'2\x00\x00\x00\x00\x00\x00\x00'
-tRp1941
-g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp1942
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1943
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1944
-tp1945
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1946
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1947
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1948
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1949
-tp1950
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1951
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1952
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1953
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp1954
-tp1955
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp1956
-g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1957
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp1958
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1959
-tp1960
-a(g11
-(g12
-S'4\x00\x00\x00\x00\x00\x00\x00'
-tRp1961
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1962
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1963
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp1964
-tp1965
-a(g11
-(g12
-S'4\x00\x00\x00\x00\x00\x00\x00'
-tRp1966
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1967
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1968
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1969
-tp1970
-a(g11
-(g12
-S'0\x00\x00\x00\x00\x00\x00\x00'
-tRp1971
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1972
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1973
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp1974
-tp1975
-a(g11
-(g12
-S'5\x00\x00\x00\x00\x00\x00\x00'
-tRp1976
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1977
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1978
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1979
-tp1980
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp1981
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1982
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp1983
-tp1984
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp1985
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1986
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp1987
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1988
-tp1989
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp1990
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp1991
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1992
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp1993
-tp1994
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp1995
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp1996
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp1997
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp1998
-tp1999
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2000
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2001
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2002
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2003
-tp2004
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2005
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2006
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2007
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2008
-tp2009
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2010
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2011
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2012
-tp2013
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2014
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2015
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2016
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2017
-tp2018
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2019
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2020
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2021
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2022
-tp2023
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2024
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2025
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2026
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2027
-tp2028
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2029
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2030
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2031
-tp2032
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2033
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2034
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2035
-tp2036
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp2037
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2038
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2039
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2040
-tp2041
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2042
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2043
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2044
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2045
-tp2046
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2047
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2048
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2049
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2050
-tp2051
-a(g11
-(g12
-S'5\x00\x00\x00\x00\x00\x00\x00'
-tRp2052
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2053
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2054
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2055
-tp2056
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2057
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2058
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2059
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2060
-tp2061
-a(g11
-(g12
-S'0\x00\x00\x00\x00\x00\x00\x00'
-tRp2062
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2063
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2064
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2065
-tp2066
-a(g11
-(g12
-S'0\x00\x00\x00\x00\x00\x00\x00'
-tRp2067
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2068
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2069
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2070
-tp2071
-a(g11
-(g12
-S'0\x00\x00\x00\x00\x00\x00\x00'
-tRp2072
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2073
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2074
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2075
-tp2076
-aa(lp2077
-(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2078
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2079
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2080
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2081
-tp2082
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2083
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2084
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2085
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2086
-tp2087
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2088
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2089
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2090
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2091
-tp2092
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2093
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2094
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2095
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2096
-tp2097
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2098
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2099
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2100
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2101
-tp2102
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2103
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2104
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2105
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2106
-tp2107
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2108
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2109
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2110
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2111
-tp2112
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2113
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2114
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2115
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2116
-tp2117
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2118
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2119
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2120
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2121
-tp2122
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2123
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2124
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2125
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2126
-tp2127
-a(g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp2128
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2129
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2130
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2131
-tp2132
-a(g11
-(g12
-S'?\x00\x00\x00\x00\x00\x00\x00'
-tRp2133
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp2134
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2135
-tp2136
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2137
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2138
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2139
-tp2140
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2141
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2142
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2143
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2144
-tp2145
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2146
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2147
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp2148
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2149
-tp2150
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2151
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2152
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2153
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2154
-tp2155
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2156
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2157
-g11
-(g12
-S'P\x00\x00\x00\x00\x00\x00\x00'
-tRp2158
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2159
-tp2160
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2161
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2162
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2163
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2164
-tp2165
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2166
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2167
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2168
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2169
-tp2170
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp2171
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2172
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2173
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2174
-tp2175
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2176
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2177
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2178
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2179
-tp2180
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp2181
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp2182
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2183
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2184
-tp2185
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp2186
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp2187
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2188
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2189
-tp2190
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2191
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2192
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2193
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2194
-tp2195
-a(g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp2196
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2197
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2198
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2199
-tp2200
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2201
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2202
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2203
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp2204
-tp2205
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2206
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2207
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2208
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2209
-tp2210
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2211
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2212
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2213
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2214
-tp2215
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2216
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2217
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2218
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2219
-tp2220
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2221
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2222
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2223
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2224
-tp2225
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2226
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2227
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2228
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2229
-tp2230
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2231
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2232
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2233
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2234
-tp2235
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2236
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2237
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2238
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2239
-tp2240
-aa(lp2241
-(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2242
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2243
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2244
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2245
-tp2246
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp2247
-g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp2248
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2249
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2250
-tp2251
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2252
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2253
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2254
-tp2255
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp2256
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2257
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2258
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2259
-tp2260
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2261
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2262
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2263
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2264
-tp2265
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2266
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2267
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2268
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2269
-tp2270
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp2271
-g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp2272
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2273
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2274
-tp2275
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2276
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2277
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2278
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2279
-tp2280
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2281
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2282
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2283
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2284
-tp2285
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2286
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2287
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2288
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2289
-tp2290
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2291
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2292
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2293
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2294
-tp2295
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2296
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2297
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2298
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2299
-tp2300
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2301
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2302
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2303
-tp2304
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp2305
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2306
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2307
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2308
-tp2309
-a(g11
-(g12
-S'2\x00\x00\x00\x00\x00\x00\x00'
-tRp2310
-g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp2311
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2312
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2313
-tp2314
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2315
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2316
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2317
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2318
-tp2319
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2320
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2321
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2322
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2323
-tp2324
-a(g11
-(g12
-S'5\x00\x00\x00\x00\x00\x00\x00'
-tRp2325
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2326
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2327
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2328
-tp2329
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2330
-g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp2331
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2332
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2333
-tp2334
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp2335
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2336
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2337
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2338
-tp2339
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2340
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2341
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2342
-tp2343
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2344
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2345
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2346
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2347
-tp2348
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2349
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2350
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2351
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2352
-tp2353
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2354
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2355
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2356
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2357
-tp2358
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2359
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2360
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2361
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2362
-tp2363
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp2364
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2365
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2366
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2367
-tp2368
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp2369
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2370
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2371
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2372
-tp2373
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2374
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2375
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2376
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2377
-tp2378
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2379
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2380
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2381
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2382
-tp2383
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2384
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2385
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2386
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2387
-tp2388
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2389
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2390
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2391
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2392
-tp2393
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp2394
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2395
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2396
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2397
-tp2398
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp2399
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2400
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2401
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2402
-tp2403
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp2404
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2405
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2406
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2407
-tp2408
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2409
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2410
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2411
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2412
-tp2413
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2414
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2415
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2416
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2417
-tp2418
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp2419
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2420
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2421
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2422
-tp2423
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp2424
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2425
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2426
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2427
-tp2428
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2429
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2430
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2431
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2432
-tp2433
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2434
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2435
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2436
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2437
-tp2438
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2439
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2440
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2441
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2442
-tp2443
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp2444
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2445
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2446
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2447
-tp2448
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp2449
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2450
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2451
-tp2452
-a(g11
-(g12
-S'5\x00\x00\x00\x00\x00\x00\x00'
-tRp2453
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2454
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2455
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2456
-tp2457
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2458
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2459
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2460
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2461
-tp2462
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2463
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2464
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2465
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2466
-tp2467
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2468
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2469
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2470
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2471
-tp2472
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp2473
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2474
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2475
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2476
-tp2477
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp2478
-g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp2479
-g11
-(g12
-S'K\x00\x00\x00\x00\x00\x00\x00'
-tRp2480
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2481
-tp2482
-a(g11
-(g12
-S'=\x00\x00\x00\x00\x00\x00\x00'
-tRp2483
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2484
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2485
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2486
-tp2487
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2488
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2489
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2490
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2491
-tp2492
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp2493
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2494
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2495
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2496
-tp2497
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2498
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2499
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2500
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2501
-tp2502
-a(g11
-(g12
-S'6\x00\x00\x00\x00\x00\x00\x00'
-tRp2503
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2504
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2505
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2506
-tp2507
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2508
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2509
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2510
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2511
-tp2512
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2513
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2514
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2515
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2516
-tp2517
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2518
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2519
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2520
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2521
-tp2522
-aa(lp2523
-(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2524
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2525
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2526
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp2527
-tp2528
-a(g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2529
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2530
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2531
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp2532
-tp2533
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2534
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2535
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2536
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp2537
-tp2538
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2539
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2540
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2541
-g11
-(g12
-S']\x00\x00\x00\x00\x00\x00\x00'
-tRp2542
-tp2543
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2544
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2545
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2546
-g11
-(g12
-S']\x00\x00\x00\x00\x00\x00\x00'
-tRp2547
-tp2548
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2549
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2550
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2551
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp2552
-tp2553
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2554
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2555
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2556
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp2557
-tp2558
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2559
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2560
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2561
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp2562
-tp2563
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2564
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2565
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2566
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2567
-tp2568
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2569
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2570
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2571
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp2572
-tp2573
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2574
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2575
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2576
-tp2577
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2578
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2579
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2580
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2581
-tp2582
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2583
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2584
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2585
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2586
-tp2587
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2588
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2589
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2590
-tp2591
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2592
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2593
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2594
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2595
-tp2596
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2597
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2598
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2599
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2600
-tp2601
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2602
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2603
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2604
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2605
-tp2606
-a(g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2607
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2608
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2609
-tp2610
-a(g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2611
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2612
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2613
-tp2614
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2615
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2616
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2617
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2618
-tp2619
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2620
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2621
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2622
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2623
-tp2624
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2625
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2626
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2627
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2628
-tp2629
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2630
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2631
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2632
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2633
-tp2634
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2635
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2636
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2637
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2638
-tp2639
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2640
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2641
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2642
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2643
-tp2644
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2645
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2646
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2647
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2648
-tp2649
-a(g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2650
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2651
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2652
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp2653
-tp2654
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2655
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2656
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2657
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp2658
-tp2659
-a(g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2660
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2661
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2662
-g11
-(g12
-S'Z\x00\x00\x00\x00\x00\x00\x00'
-tRp2663
-tp2664
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2665
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2666
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2667
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp2668
-tp2669
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2670
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2671
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2672
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp2673
-tp2674
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2675
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2676
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2677
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp2678
-tp2679
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2680
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2681
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2682
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp2683
-tp2684
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2685
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2686
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2687
-g11
-(g12
-S']\x00\x00\x00\x00\x00\x00\x00'
-tRp2688
-tp2689
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2690
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2691
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2692
-g11
-(g12
-S'[\x00\x00\x00\x00\x00\x00\x00'
-tRp2693
-tp2694
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2695
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2696
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2697
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp2698
-tp2699
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2700
-g11
-(g12
-S'R\x00\x00\x00\x00\x00\x00\x00'
-tRp2701
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2702
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2703
-tp2704
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp2705
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2706
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2707
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp2708
-tp2709
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp2710
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2711
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2712
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp2713
-tp2714
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp2715
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2716
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2717
-g11
-(g12
-S'Y\x00\x00\x00\x00\x00\x00\x00'
-tRp2718
-tp2719
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2720
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2721
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2722
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2723
-tp2724
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2725
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2726
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2727
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2728
-tp2729
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2730
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2731
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2732
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp2733
-tp2734
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2735
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2736
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2737
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2738
-tp2739
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2740
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2741
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2742
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2743
-tp2744
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2745
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2746
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2747
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2748
-tp2749
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2750
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2751
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2752
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2753
-tp2754
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2755
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2756
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2757
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2758
-tp2759
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2760
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2761
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2762
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2763
-tp2764
-aa(lp2765
-(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2766
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2767
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2768
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2769
-tp2770
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2771
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2772
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2773
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2774
-tp2775
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2776
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2777
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2778
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2779
-tp2780
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2781
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2782
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2783
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2784
-tp2785
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp2786
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2787
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2788
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2789
-tp2790
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2791
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2792
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2793
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2794
-tp2795
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2796
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2797
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2798
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2799
-tp2800
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2801
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2802
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2803
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2804
-tp2805
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2806
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2807
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2808
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2809
-tp2810
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2811
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2812
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2813
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2814
-tp2815
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2816
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2817
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2818
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2819
-tp2820
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2821
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2822
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2823
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2824
-tp2825
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2826
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2827
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2828
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2829
-tp2830
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2831
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2832
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2833
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2834
-tp2835
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2836
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2837
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2838
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2839
-tp2840
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp2841
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2842
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2843
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2844
-tp2845
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp2846
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2847
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2848
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2849
-tp2850
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2851
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2852
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2853
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2854
-tp2855
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2856
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2857
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2858
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2859
-tp2860
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp2861
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2862
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2863
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2864
-tp2865
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2866
-g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp2867
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2868
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2869
-tp2870
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2871
-g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp2872
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2873
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2874
-tp2875
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2876
-g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp2877
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2878
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2879
-tp2880
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2881
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2882
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2883
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2884
-tp2885
-a(g11
-(g12
-S'?\x00\x00\x00\x00\x00\x00\x00'
-tRp2886
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2887
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp2888
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2889
-tp2890
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2891
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp2892
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2893
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2894
-tp2895
-a(g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp2896
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2897
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp2898
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2899
-tp2900
-a(g11
-(g12
-S'D\x00\x00\x00\x00\x00\x00\x00'
-tRp2901
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2902
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2903
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2904
-tp2905
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2906
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2907
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2908
-tp2909
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp2910
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2911
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2912
-tp2913
-a(g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2914
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2915
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2916
-tp2917
-a(g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2918
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2919
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp2920
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2921
-tp2922
-a(g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp2923
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2924
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2925
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2926
-tp2927
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2928
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2929
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2930
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2931
-tp2932
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp2933
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp2934
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2935
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2936
-tp2937
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp2938
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2939
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2940
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2941
-tp2942
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2943
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2944
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2945
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2946
-tp2947
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2948
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2949
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2950
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2951
-tp2952
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2953
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2954
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2955
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2956
-tp2957
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp2958
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp2959
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2960
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2961
-tp2962
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp2963
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2964
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2965
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2966
-tp2967
-a(g11
-(g12
-S'8\x00\x00\x00\x00\x00\x00\x00'
-tRp2968
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2969
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2970
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2971
-tp2972
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp2973
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp2974
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2975
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp2976
-tp2977
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp2978
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2979
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp2980
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2981
-tp2982
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2983
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2984
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2985
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2986
-tp2987
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp2988
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2989
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp2990
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp2991
-tp2992
-a(g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2993
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp2994
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp2995
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp2996
-tp2997
-a(g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp2998
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp2999
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3000
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp3001
-tp3002
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3003
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp3004
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp3005
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp3006
-tp3007
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp3008
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp3009
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3010
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp3011
-tp3012
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp3013
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3014
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp3015
-g11
-(g12
-S'X\x00\x00\x00\x00\x00\x00\x00'
-tRp3016
-tp3017
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp3018
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp3019
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp3020
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp3021
-tp3022
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp3023
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp3024
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3025
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp3026
-tp3027
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp3028
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp3029
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3030
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp3031
-tp3032
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp3033
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3034
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3035
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp3036
-tp3037
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp3038
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3039
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp3040
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3041
-tp3042
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp3043
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3044
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp3045
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp3046
-tp3047
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp3048
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3049
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3050
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp3051
-tp3052
-a(g11
-(g12
-S'6\x00\x00\x00\x00\x00\x00\x00'
-tRp3053
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3054
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp3055
-g11
-(g12
-S'V\x00\x00\x00\x00\x00\x00\x00'
-tRp3056
-tp3057
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp3058
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3059
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp3060
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp3061
-tp3062
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp3063
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3064
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3065
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp3066
-tp3067
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp3068
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3069
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp3070
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp3071
-tp3072
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp3073
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3074
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp3075
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp3076
-tp3077
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp3078
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3079
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp3080
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp3081
-tp3082
-aa(lp3083
-(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp3084
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp3085
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3086
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3087
-tp3088
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp3089
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3090
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3091
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp3092
-tp3093
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp3094
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp3095
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3096
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp3097
-tp3098
-a(g11
-(g12
-S';\x00\x00\x00\x00\x00\x00\x00'
-tRp3099
-g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp3100
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3101
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3102
-tp3103
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp3104
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp3105
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3106
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3107
-tp3108
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp3109
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp3110
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp3111
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp3112
-tp3113
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp3114
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3115
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3116
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp3117
-tp3118
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3119
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp3120
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3121
-tp3122
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3123
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp3124
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3125
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3126
-tp3127
-a(g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp3128
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3129
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp3130
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp3131
-tp3132
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3133
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3134
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3135
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp3136
-tp3137
-a(g11
-(g12
-S'B\x00\x00\x00\x00\x00\x00\x00'
-tRp3138
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3139
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp3140
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp3141
-tp3142
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3143
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3144
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3145
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp3146
-tp3147
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp3148
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp3149
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3150
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp3151
-tp3152
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp3153
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3154
-g11
-(g12
-S'N\x00\x00\x00\x00\x00\x00\x00'
-tRp3155
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp3156
-tp3157
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp3158
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp3159
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3160
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3161
-tp3162
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3163
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp3164
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3165
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3166
-tp3167
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp3168
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3169
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp3170
-g11
-(g12
-S'T\x00\x00\x00\x00\x00\x00\x00'
-tRp3171
-tp3172
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp3173
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp3174
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3175
-g11
-(g12
-S'S\x00\x00\x00\x00\x00\x00\x00'
-tRp3176
-tp3177
-a(g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp3178
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp3179
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3180
-g11
-(g12
-S'Q\x00\x00\x00\x00\x00\x00\x00'
-tRp3181
-tp3182
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp3183
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp3184
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp3185
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3186
-tp3187
-a(g11
-(g12
-S'>\x00\x00\x00\x00\x00\x00\x00'
-tRp3188
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp3189
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3190
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp3191
-tp3192
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp3193
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3194
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3195
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp3196
-tp3197
-a(g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3198
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp3199
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3200
-tp3201
-a(g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp3202
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp3203
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp3204
-g11
-(g12
-S'O\x00\x00\x00\x00\x00\x00\x00'
-tRp3205
-tp3206
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp3207
-g11
-(g12
-S'E\x00\x00\x00\x00\x00\x00\x00'
-tRp3208
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3209
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp3210
-tp3211
-a(g11
-(g12
-S'<\x00\x00\x00\x00\x00\x00\x00'
-tRp3212
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3213
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3214
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp3215
-tp3216
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp3217
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3218
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3219
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3220
-tp3221
-a(g11
-(g12
-S'9\x00\x00\x00\x00\x00\x00\x00'
-tRp3222
-g11
-(g12
-S'A\x00\x00\x00\x00\x00\x00\x00'
-tRp3223
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3224
-g11
-(g12
-S'M\x00\x00\x00\x00\x00\x00\x00'
-tRp3225
-tp3226
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp3227
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3228
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3229
-g11
-(g12
-S'L\x00\x00\x00\x00\x00\x00\x00'
-tRp3230
-tp3231
-a(g11
-(g12
-S'7\x00\x00\x00\x00\x00\x00\x00'
-tRp3232
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3233
-g11
-(g12
-S'G\x00\x00\x00\x00\x00\x00\x00'
-tRp3234
-g11
-(g12
-S'J\x00\x00\x00\x00\x00\x00\x00'
-tRp3235
-tp3236
-a(g11
-(g12
-S'0\x00\x00\x00\x00\x00\x00\x00'
-tRp3237
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp3238
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3239
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3240
-tp3241
-a(g11
-(g12
-S'0\x00\x00\x00\x00\x00\x00\x00'
-tRp3242
-g11
-(g12
-S'@\x00\x00\x00\x00\x00\x00\x00'
-tRp3243
-g11
-(g12
-S'C\x00\x00\x00\x00\x00\x00\x00'
-tRp3244
-g11
-(g12
-S'H\x00\x00\x00\x00\x00\x00\x00'
-tRp3245
-tp3246
-aas.
\ No newline at end of file
diff --git a/research/fivo/fivo/test_data/tiny_speech_dataset.tfrecord b/research/fivo/fivo/test_data/tiny_speech_dataset.tfrecord
deleted file mode 100644
index 93fe8791b631da35b9d03d37e6494cc7c50cb55d..0000000000000000000000000000000000000000
Binary files a/research/fivo/fivo/test_data/tiny_speech_dataset.tfrecord and /dev/null differ
diff --git a/research/fivo/fivo/test_utils.py b/research/fivo/fivo/test_utils.py
deleted file mode 100644
index 48bbd3d483c45457b82b12ac1587d4c314b79f49..0000000000000000000000000000000000000000
--- a/research/fivo/fivo/test_utils.py
+++ /dev/null
@@ -1,144 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Utilities for testing FIVO.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-from fivo.models import base
-from fivo.models import srnn
-from fivo.models import vrnn
-
-
-def create_vrnn(generative_class=base.ConditionalNormalDistribution,
- batch_size=2, data_size=3, rnn_hidden_size=4,
- latent_size=5, fcnet_hidden_size=7, encoded_data_size=9,
- encoded_latent_size=11, num_timesteps=7, data_lengths=(7, 4),
- use_tilt=False, random_seed=None):
- """Creates a VRNN and some dummy data to feed it for testing purposes.
-
- Args:
- generative_class: The class of the generative distribution.
- batch_size: The number of elements per batch.
- data_size: The dimension of the vectors that make up the data sequences.
- rnn_hidden_size: The hidden state dimension of the RNN that forms the
- deterministic part of this VRNN.
- latent_size: The size of the stochastic latent state of the VRNN.
- fcnet_hidden_size: The size of the hidden layer of the fully connected
- networks that parameterize the conditional probability distributions
- of the VRNN.
- encoded_data_size: The size of the output of the data encoding network.
- encoded_latent_size: The size of the output of the latent state encoding
- network.
- num_timesteps: The maximum number of timesteps in the data.
- data_lengths: A tuple of size batch_size that contains the desired lengths
- of each sequence in the dummy data.
- use_tilt: Use a tilting function.
- random_seed: A random seed to feed the VRNN, mainly useful for testing
- purposes.
-
- Returns:
- model: A VRNN object.
- inputs: A Tensor of shape [num_timesteps, batch_size, data_size], the inputs
- to the model, also known as the observations.
- targets: A Tensor of shape [num_timesteps, batch_size, data_size], the
- desired outputs of the model.
- lengths: A Tensor of shape [batch_size], the lengths of the sequences in the
- batch.
- """
-
- fcnet_hidden_sizes = [fcnet_hidden_size]
- initializers = {"w": tf.contrib.layers.xavier_initializer(seed=random_seed),
- "b": tf.zeros_initializer()}
- model = vrnn.create_vrnn(
- data_size,
- latent_size,
- generative_class,
- rnn_hidden_size=rnn_hidden_size,
- fcnet_hidden_sizes=fcnet_hidden_sizes,
- encoded_data_size=encoded_data_size,
- encoded_latent_size=encoded_latent_size,
- use_tilt=use_tilt,
- initializers=initializers,
- random_seed=random_seed)
- inputs = tf.random_uniform([num_timesteps, batch_size, data_size],
- seed=random_seed, dtype=tf.float32)
- targets = tf.random_uniform([num_timesteps, batch_size, data_size],
- seed=random_seed, dtype=tf.float32)
- lengths = tf.constant(data_lengths, dtype=tf.int32)
- return model, inputs, targets, lengths
-
-
-def create_srnn(generative_class=base.ConditionalNormalDistribution,
- batch_size=2, data_size=3, rnn_hidden_size=4,
- latent_size=5, fcnet_hidden_size=7, encoded_data_size=3,
- encoded_latent_size=2, num_timesteps=7, data_lengths=(7, 4),
- use_tilt=False, random_seed=None):
- """Creates a SRNN and some dummy data to feed it for testing purposes.
-
- Args:
- generative_class: The class of the generative distribution.
- batch_size: The number of elements per batch.
- data_size: The dimension of the vectors that make up the data sequences.
- rnn_hidden_size: The hidden state dimension of the RNN that forms the
- deterministic part of this SRNN.
- latent_size: The size of the stochastic latent state of the SRNN.
- fcnet_hidden_size: The size of the hidden layer of the fully connected
- networks that parameterize the conditional probability distributions
- of the SRNN.
- encoded_data_size: The size of the output of the data encoding network.
- encoded_latent_size: The size of the output of the latent state encoding
- network.
- num_timesteps: The maximum number of timesteps in the data.
- data_lengths: A tuple of size batch_size that contains the desired lengths
- of each sequence in the dummy data.
- use_tilt: Use a tilting function.
- random_seed: A random seed to feed the SRNN, mainly useful for testing
- purposes.
-
- Returns:
- model: A SRNN object.
- inputs: A Tensor of shape [num_timesteps, batch_size, data_size], the inputs
- to the model, also known as the observations.
- targets: A Tensor of shape [num_timesteps, batch_size, data_size], the
- desired outputs of the model.
- lengths: A Tensor of shape [batch_size], the lengths of the sequences in the
- batch.
- """
-
- fcnet_hidden_sizes = [fcnet_hidden_size]
- initializers = {"w": tf.contrib.layers.xavier_initializer(seed=random_seed),
- "b": tf.zeros_initializer()}
- model = srnn.create_srnn(
- data_size,
- latent_size,
- generative_class,
- rnn_hidden_size=rnn_hidden_size,
- fcnet_hidden_sizes=fcnet_hidden_sizes,
- encoded_data_size=encoded_data_size,
- encoded_latent_size=encoded_latent_size,
- use_tilt=use_tilt,
- initializers=initializers,
- random_seed=random_seed)
- inputs = tf.random_uniform([num_timesteps, batch_size, data_size],
- seed=random_seed, dtype=tf.float32)
- targets = tf.random_uniform([num_timesteps, batch_size, data_size],
- seed=random_seed, dtype=tf.float32)
- lengths = tf.constant(data_lengths, dtype=tf.int32)
- return model, inputs, targets, lengths
diff --git a/research/fivo/run_fivo.py b/research/fivo/run_fivo.py
deleted file mode 100644
index 1ca079421f09fb65439dae210b1c3760240b51ad..0000000000000000000000000000000000000000
--- a/research/fivo/run_fivo.py
+++ /dev/null
@@ -1,142 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""A script to run training for sequential latent variable models.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-from fivo import ghmm_runners
-from fivo import runners
-
-# Shared flags.
-tf.app.flags.DEFINE_enum("mode", "train",
- ["train", "eval", "sample"],
- "The mode of the binary.")
-tf.app.flags.DEFINE_enum("model", "vrnn",
- ["vrnn", "ghmm", "srnn"],
- "Model choice.")
-tf.app.flags.DEFINE_integer("latent_size", 64,
- "The size of the latent state of the model.")
-tf.app.flags.DEFINE_enum("dataset_type", "pianoroll",
- ["pianoroll", "speech", "pose"],
- "The type of dataset.")
-tf.app.flags.DEFINE_string("dataset_path", "",
- "Path to load the dataset from.")
-tf.app.flags.DEFINE_integer("data_dimension", None,
- "The dimension of each vector in the data sequence. "
- "Defaults to 88 for pianoroll datasets and 200 for speech "
- "datasets. Should not need to be changed except for "
- "testing.")
-tf.app.flags.DEFINE_integer("batch_size", 4,
- "Batch size.")
-tf.app.flags.DEFINE_integer("num_samples", 4,
- "The number of samples (or particles) for multisample "
- "algorithms.")
-tf.app.flags.DEFINE_string("logdir", "/tmp/smc_vi",
- "The directory to keep checkpoints and summaries in.")
-tf.app.flags.DEFINE_integer("random_seed", None,
- "A random seed for seeding the TensorFlow graph.")
-tf.app.flags.DEFINE_integer("parallel_iterations", 30,
- "The number of parallel iterations to use for the while "
- "loop that computes the bounds.")
-
-# Training flags.
-tf.app.flags.DEFINE_enum("bound", "fivo",
- ["elbo", "iwae", "fivo", "fivo-aux"],
- "The bound to optimize.")
-tf.app.flags.DEFINE_boolean("normalize_by_seq_len", True,
- "If true, normalize the loss by the number of timesteps "
- "per sequence.")
-tf.app.flags.DEFINE_float("learning_rate", 0.0002,
- "The learning rate for ADAM.")
-tf.app.flags.DEFINE_integer("max_steps", int(1e9),
- "The number of gradient update steps to train for.")
-tf.app.flags.DEFINE_integer("summarize_every", 50,
- "The number of steps between summaries.")
-tf.app.flags.DEFINE_enum("resampling_type", "multinomial",
- ["multinomial", "relaxed"],
- "The resampling strategy to use for training.")
-tf.app.flags.DEFINE_float("relaxed_resampling_temperature", 0.5,
- "The relaxation temperature for relaxed resampling.")
-tf.app.flags.DEFINE_enum("proposal_type", "filtering",
- ["prior", "filtering", "smoothing",
- "true-filtering", "true-smoothing"],
- "The type of proposal to use. true-filtering and true-smoothing "
- "are only available for the GHMM. The specific implementation "
- "of each proposal type is left to model-writers.")
-
-# Distributed training flags.
-tf.app.flags.DEFINE_string("master", "",
- "The BNS name of the TensorFlow master to use.")
-tf.app.flags.DEFINE_integer("task", 0,
- "Task id of the replica running the training.")
-tf.app.flags.DEFINE_integer("ps_tasks", 0,
- "Number of tasks in the ps job. If 0 no ps job is used.")
-tf.app.flags.DEFINE_boolean("stagger_workers", True,
- "If true, bring one worker online every 1000 steps.")
-
-# Evaluation flags.
-tf.app.flags.DEFINE_enum("split", "train",
- ["train", "test", "valid"],
- "Split to evaluate the model on.")
-
-# Sampling flags.
-tf.app.flags.DEFINE_integer("sample_length", 50,
- "The number of timesteps to sample for.")
-tf.app.flags.DEFINE_integer("prefix_length", 25,
- "The number of timesteps to condition the model on "
- "before sampling.")
-tf.app.flags.DEFINE_string("sample_out_dir", None,
- "The directory to write the samples to. "
- "Defaults to logdir.")
-
-# GHMM flags.
-tf.app.flags.DEFINE_float("variance", 0.1,
- "The variance of the ghmm.")
-tf.app.flags.DEFINE_integer("num_timesteps", 5,
- "The number of timesteps to run the gmp for.")
-FLAGS = tf.app.flags.FLAGS
-
-PIANOROLL_DEFAULT_DATA_DIMENSION = 88
-SPEECH_DEFAULT_DATA_DIMENSION = 200
-
-
-def main(unused_argv):
- tf.logging.set_verbosity(tf.logging.INFO)
- if FLAGS.model in ["vrnn", "srnn"]:
- if FLAGS.data_dimension is None:
- if FLAGS.dataset_type == "pianoroll":
- FLAGS.data_dimension = PIANOROLL_DEFAULT_DATA_DIMENSION
- elif FLAGS.dataset_type == "speech":
- FLAGS.data_dimension = SPEECH_DEFAULT_DATA_DIMENSION
- if FLAGS.mode == "train":
- runners.run_train(FLAGS)
- elif FLAGS.mode == "eval":
- runners.run_eval(FLAGS)
- elif FLAGS.mode == "sample":
- runners.run_sample(FLAGS)
- elif FLAGS.model == "ghmm":
- if FLAGS.mode == "train":
- ghmm_runners.run_train(FLAGS)
- elif FLAGS.mode == "eval":
- ghmm_runners.run_eval(FLAGS)
-
-if __name__ == "__main__":
- tf.app.run(main)
diff --git a/research/global_objectives/README.md b/research/global_objectives/README.md
deleted file mode 100644
index f9a778c59d420f9bf5deccf4b2b45147636de582..0000000000000000000000000000000000000000
--- a/research/global_objectives/README.md
+++ /dev/null
@@ -1,152 +0,0 @@
-
-
-
-
-# Global Objectives
-The Global Objectives library provides TensorFlow loss functions that optimize
-directly for a variety of objectives including AUC, recall at precision, and
-more. The global objectives losses can be used as drop-in replacements for
-TensorFlow's standard multilabel loss functions:
-`tf.nn.sigmoid_cross_entropy_with_logits` and `tf.losses.sigmoid_cross_entropy`.
-
-Many machine learning classification models are optimized for classification
-accuracy, when the real objective the user cares about is different and can be
-precision at a fixed recall, precision-recall AUC, ROC AUC or similar metrics.
-These are referred to as "global objectives" because they depend on how the
-model classifies the dataset as a whole and do not decouple across data points
-as accuracy does.
-
-Because these objectives are combinatorial, discontinuous, and essentially
-intractable to optimize directly, the functions in this library approximate
-their corresponding objectives. This approximation approach follows the same
-pattern as optimizing for accuracy, where a surrogate objective such as
-cross-entropy or the hinge loss is used as an upper bound on the error rate.
-
-## Getting Started
-For a full example of how to use the loss functions in practice, see
-loss_layers_example.py.
-
-Briefly, global objective losses can be used to replace
-`tf.nn.sigmoid_cross_entropy_with_logits` by providing the relevant
-additional arguments. For example,
-
-``` python
-tf.nn.sigmoid_cross_entropy_with_logits(labels=labels, logits=logits)
-```
-
-could be replaced with
-
-``` python
-global_objectives.recall_at_precision_loss(
- labels=labels,
- logits=logits,
- target_precision=0.95)[0]
-```
-
-Just as minimizing the cross-entropy loss will maximize accuracy, the loss
-functions in loss_layers.py were written so that minimizing the loss will
-maximize the corresponding objective.
-
-The global objective losses have two return values -- the loss tensor and
-additional quantities for debugging and customization -- which is why the first
-value is used above. For more information, see
-[Visualization & Debugging](#visualization-debugging).
-
-## Binary Label Format
-Binary classification problems can be represented as a multi-class problem with
-two classes, or as a multi-label problem with one label. (Recall that multiclass
-problems have mutually exclusive classes, e.g. 'cat xor dog', and multilabel
-have classes which are not mutually exclusive, e.g. an image can contain a cat,
-a dog, both, or neither.) The softmax loss
-(`tf.nn.softmax_cross_entropy_with_logits`) is used for multi-class problems,
-while the sigmoid loss (`tf.nn.sigmoid_cross_entropy_with_logits`) is used for
-multi-label problems.
-
-A multiclass label format for binary classification might represent positives
-with the label [1, 0] and negatives with the label [0, 1], while the multilbel
-format for the same problem would use [1] and [0], respectively.
-
-All global objectives loss functions assume that the multilabel format is used.
-Accordingly, if your current loss function is softmax, the labels will have to
-be reformatted for the loss to work properly.
-
-## Dual Variables
-Global objectives losses (except for `roc_auc_loss`) use internal variables
-called dual variables or Lagrange multipliers to enforce the desired constraint
-(e.g. if optimzing for recall at precision, the constraint is on precision).
-
-These dual variables are created and initialized internally by the loss
-functions, and are updated during training by the same optimizer used for the
-model's other variables. To initialize the dual variables to a particular value,
-use the `lambdas_initializer` argument. The dual variables can be found under
-the key `lambdas` in the `other_outputs` dictionary returned by the losses.
-
-## Loss Function Arguments
-The following arguments are common to all loss functions in the library, and are
-either required or very important.
-
-* `labels`: Corresponds directly to the `labels` argument of
- `tf.nn.sigmoid_cross_entropy_with_logits`.
-* `logits`: Corresponds directly to the `logits` argument of
- `tf.nn.sigmoid_cross_entropy_with_logits`.
-* `dual_rate_factor`: A floating point value which controls the step size for
- the Lagrange multipliers. Setting this value less than 1.0 will cause the
- constraint to be enforced more gradually and will result in more stable
- training.
-
-In addition, the objectives with a single constraint (e.g.
-`recall_at_precision_loss`) have an argument (e.g. `target_precision`) used to
-specify the value of the constraint. The optional `precision_range` argument to
-`precision_recall_auc_loss` is used to specify the range of precision values
-over which to optimize the AUC, and defaults to the interval [0, 1].
-
-Optional arguments:
-
-* `weights`: A tensor which acts as coefficients for the loss. If a weight of x
- is provided for a datapoint and that datapoint is a true (false) positive
- (negative), it will be counted as x true (false) positives (negatives).
- Defaults to 1.0.
-* `label_priors`: A tensor specifying the fraction of positive datapoints for
- each label. If not provided, it will be computed inside the loss function.
-* `surrogate_type`: Either 'xent' or 'hinge', specifying which upper bound
- should be used for indicator functions.
-* `lambdas_initializer`: An initializer for the dual variables (Lagrange
- multipliers). See also the Dual Variables section.
-* `num_anchors` (precision_recall_auc_loss only): The number of grid points used
- when approximating the AUC as a Riemann sum.
-
-## Hyperparameters
-While the functional form of the global objectives losses allow them to be
-easily substituted in place of `sigmoid_cross_entropy_with_logits`, model
-hyperparameters such as learning rate, weight decay, etc. may need to be
-fine-tuned to the new loss. Fortunately, the amount of hyperparameter re-tuning
-is usually minor.
-
-The most important hyperparameters to modify are the learning rate and
-dual_rate_factor (see the section on Loss Function Arguments, above).
-
-## Visualization & Debugging
-The global objectives losses return two values. The first is a tensor
-representing the numerical value of the loss, which can be passed to an
-optimizer. The second is a dictionary of tensors created by the loss function
-which are not necessary for optimization but useful in debugging. These vary
-depending on the loss function, but usually include `lambdas` (the Lagrange
-multipliers) as well as the lower bound on true positives and upper bound on
-false positives.
-
-When visualizing the loss during training, note that the global objectives
-losses differ from standard losses in some important ways:
-
-* The global losses may be negative. This is because the value returned by the
- loss includes terms involving the Lagrange multipliers, which may be negative.
-* The global losses may not decrease over the course of training. To enforce the
- constraints in the objective, the loss changes over time and may increase.
-
-## More Info
-For more details, see the [Global Objectives paper](https://arxiv.org/abs/1608.04802).
-
-## Maintainers
-
-* Mariano Schain
-* Elad Eban
-* [Alan Mackey](https://github.com/mackeya-google)
diff --git a/research/global_objectives/loss_layers.py b/research/global_objectives/loss_layers.py
deleted file mode 100644
index eaea05398ef3771247060afda63be184ea76cdf0..0000000000000000000000000000000000000000
--- a/research/global_objectives/loss_layers.py
+++ /dev/null
@@ -1,930 +0,0 @@
-# Copyright 2018 The TensorFlow Global Objectives Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Loss functions for learning global objectives.
-
-These functions have two return values: a Tensor with the value of
-the loss, and a dictionary of internal quantities for customizability.
-"""
-
-# Dependency imports
-import numpy
-import tensorflow as tf
-
-from global_objectives import util
-
-
-def precision_recall_auc_loss(
- labels,
- logits,
- precision_range=(0.0, 1.0),
- num_anchors=20,
- weights=1.0,
- dual_rate_factor=0.1,
- label_priors=None,
- surrogate_type='xent',
- lambdas_initializer=tf.constant_initializer(1.0),
- reuse=None,
- variables_collections=None,
- trainable=True,
- scope=None):
- """Computes precision-recall AUC loss.
-
- The loss is based on a sum of losses for recall at a range of
- precision values (anchor points). This sum is a Riemann sum that
- approximates the area under the precision-recall curve.
-
- The per-example `weights` argument changes not only the coefficients of
- individual training examples, but how the examples are counted toward the
- constraint. If `label_priors` is given, it MUST take `weights` into account.
- That is,
- label_priors = P / (P + N)
- where
- P = sum_i (wt_i on positives)
- N = sum_i (wt_i on negatives).
-
- Args:
- labels: A `Tensor` of shape [batch_size] or [batch_size, num_labels].
- logits: A `Tensor` with the same shape as `labels`.
- precision_range: A length-two tuple, the range of precision values over
- which to compute AUC. The entries must be nonnegative, increasing, and
- less than or equal to 1.0.
- num_anchors: The number of grid points used to approximate the Riemann sum.
- weights: Coefficients for the loss. Must be a scalar or `Tensor` of shape
- [batch_size] or [batch_size, num_labels].
- dual_rate_factor: A floating point value which controls the step size for
- the Lagrange multipliers.
- label_priors: None, or a floating point `Tensor` of shape [num_labels]
- containing the prior probability of each label (i.e. the fraction of the
- training data consisting of positive examples). If None, the label
- priors are computed from `labels` with a moving average. See the notes
- above regarding the interaction with `weights` and do not set this unless
- you have a good reason to do so.
- surrogate_type: Either 'xent' or 'hinge', specifying which upper bound
- should be used for indicator functions.
- lambdas_initializer: An initializer for the Lagrange multipliers.
- reuse: Whether or not the layer and its variables should be reused. To be
- able to reuse the layer scope must be given.
- variables_collections: Optional list of collections for the variables.
- trainable: If `True` also add variables to the graph collection
- `GraphKeys.TRAINABLE_VARIABLES` (see `tf.Variable`).
- scope: Optional scope for `variable_scope`.
-
- Returns:
- loss: A `Tensor` of the same shape as `logits` with the component-wise
- loss.
- other_outputs: A dictionary of useful internal quantities for debugging. For
- more details, see http://arxiv.org/pdf/1608.04802.pdf.
- lambdas: A Tensor of shape [1, num_labels, num_anchors] consisting of the
- Lagrange multipliers.
- biases: A Tensor of shape [1, num_labels, num_anchors] consisting of the
- learned bias term for each.
- label_priors: A Tensor of shape [1, num_labels, 1] consisting of the prior
- probability of each label learned by the loss, if not provided.
- true_positives_lower_bound: Lower bound on the number of true positives
- given `labels` and `logits`. This is the same lower bound which is used
- in the loss expression to be optimized.
- false_positives_upper_bound: Upper bound on the number of false positives
- given `labels` and `logits`. This is the same upper bound which is used
- in the loss expression to be optimized.
-
- Raises:
- ValueError: If `surrogate_type` is not `xent` or `hinge`.
- """
- with tf.variable_scope(scope,
- 'precision_recall_auc',
- [labels, logits, label_priors],
- reuse=reuse):
- labels, logits, weights, original_shape = _prepare_labels_logits_weights(
- labels, logits, weights)
- num_labels = util.get_num_labels(logits)
-
- # Convert other inputs to tensors and standardize dtypes.
- dual_rate_factor = util.convert_and_cast(
- dual_rate_factor, 'dual_rate_factor', logits.dtype)
-
- # Create Tensor of anchor points and distance between anchors.
- precision_values, delta = _range_to_anchors_and_delta(
- precision_range, num_anchors, logits.dtype)
- # Create lambdas with shape [1, num_labels, num_anchors].
- lambdas, lambdas_variable = _create_dual_variable(
- 'lambdas',
- shape=[1, num_labels, num_anchors],
- dtype=logits.dtype,
- initializer=lambdas_initializer,
- collections=variables_collections,
- trainable=trainable,
- dual_rate_factor=dual_rate_factor)
- # Create biases with shape [1, num_labels, num_anchors].
- biases = tf.contrib.framework.model_variable(
- name='biases',
- shape=[1, num_labels, num_anchors],
- dtype=logits.dtype,
- initializer=tf.zeros_initializer(),
- collections=variables_collections,
- trainable=trainable)
- # Maybe create label_priors.
- label_priors = maybe_create_label_priors(
- label_priors, labels, weights, variables_collections)
- label_priors = tf.reshape(label_priors, [1, num_labels, 1])
-
- # Expand logits, labels, and weights to shape [batch_size, num_labels, 1].
- logits = tf.expand_dims(logits, 2)
- labels = tf.expand_dims(labels, 2)
- weights = tf.expand_dims(weights, 2)
-
- # Calculate weighted loss and other outputs. The log(2.0) term corrects for
- # logloss not being an upper bound on the indicator function.
- loss = weights * util.weighted_surrogate_loss(
- labels,
- logits + biases,
- surrogate_type=surrogate_type,
- positive_weights=1.0 + lambdas * (1.0 - precision_values),
- negative_weights=lambdas * precision_values)
- maybe_log2 = tf.log(2.0) if surrogate_type == 'xent' else 1.0
- maybe_log2 = tf.cast(maybe_log2, logits.dtype.base_dtype)
- lambda_term = lambdas * (1.0 - precision_values) * label_priors * maybe_log2
- per_anchor_loss = loss - lambda_term
- per_label_loss = delta * tf.reduce_sum(per_anchor_loss, 2)
- # Normalize the AUC such that a perfect score function will have AUC 1.0.
- # Because precision_range is discretized into num_anchors + 1 intervals
- # but only num_anchors terms are included in the Riemann sum, the
- # effective length of the integration interval is `delta` less than the
- # length of precision_range.
- scaled_loss = tf.div(per_label_loss,
- precision_range[1] - precision_range[0] - delta,
- name='AUC_Normalize')
- scaled_loss = tf.reshape(scaled_loss, original_shape)
-
- other_outputs = {
- 'lambdas': lambdas_variable,
- 'biases': biases,
- 'label_priors': label_priors,
- 'true_positives_lower_bound': true_positives_lower_bound(
- labels, logits, weights, surrogate_type),
- 'false_positives_upper_bound': false_positives_upper_bound(
- labels, logits, weights, surrogate_type)}
-
- return scaled_loss, other_outputs
-
-
-def roc_auc_loss(
- labels,
- logits,
- weights=1.0,
- surrogate_type='xent',
- scope=None):
- """Computes ROC AUC loss.
-
- The area under the ROC curve is the probability p that a randomly chosen
- positive example will be scored higher than a randomly chosen negative
- example. This loss approximates 1-p by using a surrogate (either hinge loss or
- cross entropy) for the indicator function. Specifically, the loss is:
-
- sum_i sum_j w_i*w_j*loss(logit_i - logit_j)
-
- where i ranges over the positive datapoints, j ranges over the negative
- datapoints, logit_k denotes the logit (or score) of the k-th datapoint, and
- loss is either the hinge or log loss given a positive label.
-
- Args:
- labels: A `Tensor` of shape [batch_size] or [batch_size, num_labels].
- logits: A `Tensor` with the same shape and dtype as `labels`.
- weights: Coefficients for the loss. Must be a scalar or `Tensor` of shape
- [batch_size] or [batch_size, num_labels].
- surrogate_type: Either 'xent' or 'hinge', specifying which upper bound
- should be used for the indicator function.
- scope: Optional scope for `name_scope`.
-
- Returns:
- loss: A `Tensor` of the same shape as `logits` with the component-wise loss.
- other_outputs: An empty dictionary, for consistency.
-
- Raises:
- ValueError: If `surrogate_type` is not `xent` or `hinge`.
- """
- with tf.name_scope(scope, 'roc_auc', [labels, logits, weights]):
- # Convert inputs to tensors and standardize dtypes.
- labels, logits, weights, original_shape = _prepare_labels_logits_weights(
- labels, logits, weights)
-
- # Create tensors of pairwise differences for logits and labels, and
- # pairwise products of weights. These have shape
- # [batch_size, batch_size, num_labels].
- logits_difference = tf.expand_dims(logits, 0) - tf.expand_dims(logits, 1)
- labels_difference = tf.expand_dims(labels, 0) - tf.expand_dims(labels, 1)
- weights_product = tf.expand_dims(weights, 0) * tf.expand_dims(weights, 1)
-
- signed_logits_difference = labels_difference * logits_difference
- raw_loss = util.weighted_surrogate_loss(
- labels=tf.ones_like(signed_logits_difference),
- logits=signed_logits_difference,
- surrogate_type=surrogate_type)
- weighted_loss = weights_product * raw_loss
-
- # Zero out entries of the loss where labels_difference zero (so loss is only
- # computed on pairs with different labels).
- loss = tf.reduce_mean(tf.abs(labels_difference) * weighted_loss, 0) * 0.5
- loss = tf.reshape(loss, original_shape)
- return loss, {}
-
-
-def recall_at_precision_loss(
- labels,
- logits,
- target_precision,
- weights=1.0,
- dual_rate_factor=0.1,
- label_priors=None,
- surrogate_type='xent',
- lambdas_initializer=tf.constant_initializer(1.0),
- reuse=None,
- variables_collections=None,
- trainable=True,
- scope=None):
- """Computes recall at precision loss.
-
- The loss is based on a surrogate of the form
- wt * w(+) * loss(+) + wt * w(-) * loss(-) - c * pi,
- where:
- - w(+) = 1 + lambdas * (1 - target_precision)
- - loss(+) is the cross-entropy loss on the positive examples
- - w(-) = lambdas * target_precision
- - loss(-) is the cross-entropy loss on the negative examples
- - wt is a scalar or tensor of per-example weights
- - c = lambdas * (1 - target_precision)
- - pi is the label_priors.
-
- The per-example weights change not only the coefficients of individual
- training examples, but how the examples are counted toward the constraint.
- If `label_priors` is given, it MUST take `weights` into account. That is,
- label_priors = P / (P + N)
- where
- P = sum_i (wt_i on positives)
- N = sum_i (wt_i on negatives).
-
- Args:
- labels: A `Tensor` of shape [batch_size] or [batch_size, num_labels].
- logits: A `Tensor` with the same shape as `labels`.
- target_precision: The precision at which to compute the loss. Can be a
- floating point value between 0 and 1 for a single precision value, or a
- `Tensor` of shape [num_labels], holding each label's target precision
- value.
- weights: Coefficients for the loss. Must be a scalar or `Tensor` of shape
- [batch_size] or [batch_size, num_labels].
- dual_rate_factor: A floating point value which controls the step size for
- the Lagrange multipliers.
- label_priors: None, or a floating point `Tensor` of shape [num_labels]
- containing the prior probability of each label (i.e. the fraction of the
- training data consisting of positive examples). If None, the label
- priors are computed from `labels` with a moving average. See the notes
- above regarding the interaction with `weights` and do not set this unless
- you have a good reason to do so.
- surrogate_type: Either 'xent' or 'hinge', specifying which upper bound
- should be used for indicator functions.
- lambdas_initializer: An initializer for the Lagrange multipliers.
- reuse: Whether or not the layer and its variables should be reused. To be
- able to reuse the layer scope must be given.
- variables_collections: Optional list of collections for the variables.
- trainable: If `True` also add variables to the graph collection
- `GraphKeys.TRAINABLE_VARIABLES` (see `tf.Variable`).
- scope: Optional scope for `variable_scope`.
-
- Returns:
- loss: A `Tensor` of the same shape as `logits` with the component-wise
- loss.
- other_outputs: A dictionary of useful internal quantities for debugging. For
- more details, see http://arxiv.org/pdf/1608.04802.pdf.
- lambdas: A Tensor of shape [num_labels] consisting of the Lagrange
- multipliers.
- label_priors: A Tensor of shape [num_labels] consisting of the prior
- probability of each label learned by the loss, if not provided.
- true_positives_lower_bound: Lower bound on the number of true positives
- given `labels` and `logits`. This is the same lower bound which is used
- in the loss expression to be optimized.
- false_positives_upper_bound: Upper bound on the number of false positives
- given `labels` and `logits`. This is the same upper bound which is used
- in the loss expression to be optimized.
-
- Raises:
- ValueError: If `logits` and `labels` do not have the same shape.
- """
- with tf.variable_scope(scope,
- 'recall_at_precision',
- [logits, labels, label_priors],
- reuse=reuse):
- labels, logits, weights, original_shape = _prepare_labels_logits_weights(
- labels, logits, weights)
- num_labels = util.get_num_labels(logits)
-
- # Convert other inputs to tensors and standardize dtypes.
- target_precision = util.convert_and_cast(
- target_precision, 'target_precision', logits.dtype)
- dual_rate_factor = util.convert_and_cast(
- dual_rate_factor, 'dual_rate_factor', logits.dtype)
-
- # Create lambdas.
- lambdas, lambdas_variable = _create_dual_variable(
- 'lambdas',
- shape=[num_labels],
- dtype=logits.dtype,
- initializer=lambdas_initializer,
- collections=variables_collections,
- trainable=trainable,
- dual_rate_factor=dual_rate_factor)
- # Maybe create label_priors.
- label_priors = maybe_create_label_priors(
- label_priors, labels, weights, variables_collections)
-
- # Calculate weighted loss and other outputs. The log(2.0) term corrects for
- # logloss not being an upper bound on the indicator function.
- weighted_loss = weights * util.weighted_surrogate_loss(
- labels,
- logits,
- surrogate_type=surrogate_type,
- positive_weights=1.0 + lambdas * (1.0 - target_precision),
- negative_weights=lambdas * target_precision)
- maybe_log2 = tf.log(2.0) if surrogate_type == 'xent' else 1.0
- maybe_log2 = tf.cast(maybe_log2, logits.dtype.base_dtype)
- lambda_term = lambdas * (1.0 - target_precision) * label_priors * maybe_log2
- loss = tf.reshape(weighted_loss - lambda_term, original_shape)
- other_outputs = {
- 'lambdas': lambdas_variable,
- 'label_priors': label_priors,
- 'true_positives_lower_bound': true_positives_lower_bound(
- labels, logits, weights, surrogate_type),
- 'false_positives_upper_bound': false_positives_upper_bound(
- labels, logits, weights, surrogate_type)}
-
- return loss, other_outputs
-
-
-def precision_at_recall_loss(
- labels,
- logits,
- target_recall,
- weights=1.0,
- dual_rate_factor=0.1,
- label_priors=None,
- surrogate_type='xent',
- lambdas_initializer=tf.constant_initializer(1.0),
- reuse=None,
- variables_collections=None,
- trainable=True,
- scope=None):
- """Computes precision at recall loss.
-
- The loss is based on a surrogate of the form
- wt * loss(-) + lambdas * (pi * (b - 1) + wt * loss(+))
- where:
- - loss(-) is the cross-entropy loss on the negative examples
- - loss(+) is the cross-entropy loss on the positive examples
- - wt is a scalar or tensor of per-example weights
- - b is the target recall
- - pi is the label_priors.
-
- The per-example weights change not only the coefficients of individual
- training examples, but how the examples are counted toward the constraint.
- If `label_priors` is given, it MUST take `weights` into account. That is,
- label_priors = P / (P + N)
- where
- P = sum_i (wt_i on positives)
- N = sum_i (wt_i on negatives).
-
- Args:
- labels: A `Tensor` of shape [batch_size] or [batch_size, num_labels].
- logits: A `Tensor` with the same shape as `labels`.
- target_recall: The recall at which to compute the loss. Can be a floating
- point value between 0 and 1 for a single target recall value, or a
- `Tensor` of shape [num_labels] holding each label's target recall value.
- weights: Coefficients for the loss. Must be a scalar or `Tensor` of shape
- [batch_size] or [batch_size, num_labels].
- dual_rate_factor: A floating point value which controls the step size for
- the Lagrange multipliers.
- label_priors: None, or a floating point `Tensor` of shape [num_labels]
- containing the prior probability of each label (i.e. the fraction of the
- training data consisting of positive examples). If None, the label
- priors are computed from `labels` with a moving average. See the notes
- above regarding the interaction with `weights` and do not set this unless
- you have a good reason to do so.
- surrogate_type: Either 'xent' or 'hinge', specifying which upper bound
- should be used for indicator functions.
- lambdas_initializer: An initializer for the Lagrange multipliers.
- reuse: Whether or not the layer and its variables should be reused. To be
- able to reuse the layer scope must be given.
- variables_collections: Optional list of collections for the variables.
- trainable: If `True` also add variables to the graph collection
- `GraphKeys.TRAINABLE_VARIABLES` (see `tf.Variable`).
- scope: Optional scope for `variable_scope`.
-
- Returns:
- loss: A `Tensor` of the same shape as `logits` with the component-wise
- loss.
- other_outputs: A dictionary of useful internal quantities for debugging. For
- more details, see http://arxiv.org/pdf/1608.04802.pdf.
- lambdas: A Tensor of shape [num_labels] consisting of the Lagrange
- multipliers.
- label_priors: A Tensor of shape [num_labels] consisting of the prior
- probability of each label learned by the loss, if not provided.
- true_positives_lower_bound: Lower bound on the number of true positives
- given `labels` and `logits`. This is the same lower bound which is used
- in the loss expression to be optimized.
- false_positives_upper_bound: Upper bound on the number of false positives
- given `labels` and `logits`. This is the same upper bound which is used
- in the loss expression to be optimized.
- """
- with tf.variable_scope(scope,
- 'precision_at_recall',
- [logits, labels, label_priors],
- reuse=reuse):
- labels, logits, weights, original_shape = _prepare_labels_logits_weights(
- labels, logits, weights)
- num_labels = util.get_num_labels(logits)
-
- # Convert other inputs to tensors and standardize dtypes.
- target_recall = util.convert_and_cast(
- target_recall, 'target_recall', logits.dtype)
- dual_rate_factor = util.convert_and_cast(
- dual_rate_factor, 'dual_rate_factor', logits.dtype)
-
- # Create lambdas.
- lambdas, lambdas_variable = _create_dual_variable(
- 'lambdas',
- shape=[num_labels],
- dtype=logits.dtype,
- initializer=lambdas_initializer,
- collections=variables_collections,
- trainable=trainable,
- dual_rate_factor=dual_rate_factor)
- # Maybe create label_priors.
- label_priors = maybe_create_label_priors(
- label_priors, labels, weights, variables_collections)
-
- # Calculate weighted loss and other outputs. The log(2.0) term corrects for
- # logloss not being an upper bound on the indicator function.
- weighted_loss = weights * util.weighted_surrogate_loss(
- labels,
- logits,
- surrogate_type,
- positive_weights=lambdas,
- negative_weights=1.0)
- maybe_log2 = tf.log(2.0) if surrogate_type == 'xent' else 1.0
- maybe_log2 = tf.cast(maybe_log2, logits.dtype.base_dtype)
- lambda_term = lambdas * label_priors * (target_recall - 1.0) * maybe_log2
- loss = tf.reshape(weighted_loss + lambda_term, original_shape)
- other_outputs = {
- 'lambdas': lambdas_variable,
- 'label_priors': label_priors,
- 'true_positives_lower_bound': true_positives_lower_bound(
- labels, logits, weights, surrogate_type),
- 'false_positives_upper_bound': false_positives_upper_bound(
- labels, logits, weights, surrogate_type)}
-
- return loss, other_outputs
-
-
-def false_positive_rate_at_true_positive_rate_loss(
- labels,
- logits,
- target_rate,
- weights=1.0,
- dual_rate_factor=0.1,
- label_priors=None,
- surrogate_type='xent',
- lambdas_initializer=tf.constant_initializer(1.0),
- reuse=None,
- variables_collections=None,
- trainable=True,
- scope=None):
- """Computes false positive rate at true positive rate loss.
-
- Note that `true positive rate` is a synonym for Recall, and that minimizing
- the false positive rate and maximizing precision are equivalent for a fixed
- Recall. Therefore, this function is identical to precision_at_recall_loss.
-
- The per-example weights change not only the coefficients of individual
- training examples, but how the examples are counted toward the constraint.
- If `label_priors` is given, it MUST take `weights` into account. That is,
- label_priors = P / (P + N)
- where
- P = sum_i (wt_i on positives)
- N = sum_i (wt_i on negatives).
-
- Args:
- labels: A `Tensor` of shape [batch_size] or [batch_size, num_labels].
- logits: A `Tensor` with the same shape as `labels`.
- target_rate: The true positive rate at which to compute the loss. Can be a
- floating point value between 0 and 1 for a single true positive rate, or
- a `Tensor` of shape [num_labels] holding each label's true positive rate.
- weights: Coefficients for the loss. Must be a scalar or `Tensor` of shape
- [batch_size] or [batch_size, num_labels].
- dual_rate_factor: A floating point value which controls the step size for
- the Lagrange multipliers.
- label_priors: None, or a floating point `Tensor` of shape [num_labels]
- containing the prior probability of each label (i.e. the fraction of the
- training data consisting of positive examples). If None, the label
- priors are computed from `labels` with a moving average. See the notes
- above regarding the interaction with `weights` and do not set this unless
- you have a good reason to do so.
- surrogate_type: Either 'xent' or 'hinge', specifying which upper bound
- should be used for indicator functions. 'xent' will use the cross-entropy
- loss surrogate, and 'hinge' will use the hinge loss.
- lambdas_initializer: An initializer op for the Lagrange multipliers.
- reuse: Whether or not the layer and its variables should be reused. To be
- able to reuse the layer scope must be given.
- variables_collections: Optional list of collections for the variables.
- trainable: If `True` also add variables to the graph collection
- `GraphKeys.TRAINABLE_VARIABLES` (see `tf.Variable`).
- scope: Optional scope for `variable_scope`.
-
- Returns:
- loss: A `Tensor` of the same shape as `logits` with the component-wise
- loss.
- other_outputs: A dictionary of useful internal quantities for debugging. For
- more details, see http://arxiv.org/pdf/1608.04802.pdf.
- lambdas: A Tensor of shape [num_labels] consisting of the Lagrange
- multipliers.
- label_priors: A Tensor of shape [num_labels] consisting of the prior
- probability of each label learned by the loss, if not provided.
- true_positives_lower_bound: Lower bound on the number of true positives
- given `labels` and `logits`. This is the same lower bound which is used
- in the loss expression to be optimized.
- false_positives_upper_bound: Upper bound on the number of false positives
- given `labels` and `logits`. This is the same upper bound which is used
- in the loss expression to be optimized.
-
- Raises:
- ValueError: If `surrogate_type` is not `xent` or `hinge`.
- """
- return precision_at_recall_loss(labels=labels,
- logits=logits,
- target_recall=target_rate,
- weights=weights,
- dual_rate_factor=dual_rate_factor,
- label_priors=label_priors,
- surrogate_type=surrogate_type,
- lambdas_initializer=lambdas_initializer,
- reuse=reuse,
- variables_collections=variables_collections,
- trainable=trainable,
- scope=scope)
-
-
-def true_positive_rate_at_false_positive_rate_loss(
- labels,
- logits,
- target_rate,
- weights=1.0,
- dual_rate_factor=0.1,
- label_priors=None,
- surrogate_type='xent',
- lambdas_initializer=tf.constant_initializer(1.0),
- reuse=None,
- variables_collections=None,
- trainable=True,
- scope=None):
- """Computes true positive rate at false positive rate loss.
-
- The loss is based on a surrogate of the form
- wt * loss(+) + lambdas * (wt * loss(-) - r * (1 - pi))
- where:
- - loss(-) is the loss on the negative examples
- - loss(+) is the loss on the positive examples
- - wt is a scalar or tensor of per-example weights
- - r is the target rate
- - pi is the label_priors.
-
- The per-example weights change not only the coefficients of individual
- training examples, but how the examples are counted toward the constraint.
- If `label_priors` is given, it MUST take `weights` into account. That is,
- label_priors = P / (P + N)
- where
- P = sum_i (wt_i on positives)
- N = sum_i (wt_i on negatives).
-
- Args:
- labels: A `Tensor` of shape [batch_size] or [batch_size, num_labels].
- logits: A `Tensor` with the same shape as `labels`.
- target_rate: The false positive rate at which to compute the loss. Can be a
- floating point value between 0 and 1 for a single false positive rate, or
- a `Tensor` of shape [num_labels] holding each label's false positive rate.
- weights: Coefficients for the loss. Must be a scalar or `Tensor` of shape
- [batch_size] or [batch_size, num_labels].
- dual_rate_factor: A floating point value which controls the step size for
- the Lagrange multipliers.
- label_priors: None, or a floating point `Tensor` of shape [num_labels]
- containing the prior probability of each label (i.e. the fraction of the
- training data consisting of positive examples). If None, the label
- priors are computed from `labels` with a moving average. See the notes
- above regarding the interaction with `weights` and do not set this unless
- you have a good reason to do so.
- surrogate_type: Either 'xent' or 'hinge', specifying which upper bound
- should be used for indicator functions. 'xent' will use the cross-entropy
- loss surrogate, and 'hinge' will use the hinge loss.
- lambdas_initializer: An initializer op for the Lagrange multipliers.
- reuse: Whether or not the layer and its variables should be reused. To be
- able to reuse the layer scope must be given.
- variables_collections: Optional list of collections for the variables.
- trainable: If `True` also add variables to the graph collection
- `GraphKeys.TRAINABLE_VARIABLES` (see `tf.Variable`).
- scope: Optional scope for `variable_scope`.
-
- Returns:
- loss: A `Tensor` of the same shape as `logits` with the component-wise
- loss.
- other_outputs: A dictionary of useful internal quantities for debugging. For
- more details, see http://arxiv.org/pdf/1608.04802.pdf.
- lambdas: A Tensor of shape [num_labels] consisting of the Lagrange
- multipliers.
- label_priors: A Tensor of shape [num_labels] consisting of the prior
- probability of each label learned by the loss, if not provided.
- true_positives_lower_bound: Lower bound on the number of true positives
- given `labels` and `logits`. This is the same lower bound which is used
- in the loss expression to be optimized.
- false_positives_upper_bound: Upper bound on the number of false positives
- given `labels` and `logits`. This is the same upper bound which is used
- in the loss expression to be optimized.
-
- Raises:
- ValueError: If `surrogate_type` is not `xent` or `hinge`.
- """
- with tf.variable_scope(scope,
- 'tpr_at_fpr',
- [labels, logits, label_priors],
- reuse=reuse):
- labels, logits, weights, original_shape = _prepare_labels_logits_weights(
- labels, logits, weights)
- num_labels = util.get_num_labels(logits)
-
- # Convert other inputs to tensors and standardize dtypes.
- target_rate = util.convert_and_cast(
- target_rate, 'target_rate', logits.dtype)
- dual_rate_factor = util.convert_and_cast(
- dual_rate_factor, 'dual_rate_factor', logits.dtype)
-
- # Create lambdas.
- lambdas, lambdas_variable = _create_dual_variable(
- 'lambdas',
- shape=[num_labels],
- dtype=logits.dtype,
- initializer=lambdas_initializer,
- collections=variables_collections,
- trainable=trainable,
- dual_rate_factor=dual_rate_factor)
- # Maybe create label_priors.
- label_priors = maybe_create_label_priors(
- label_priors, labels, weights, variables_collections)
-
- # Loss op and other outputs. The log(2.0) term corrects for
- # logloss not being an upper bound on the indicator function.
- weighted_loss = weights * util.weighted_surrogate_loss(
- labels,
- logits,
- surrogate_type=surrogate_type,
- positive_weights=1.0,
- negative_weights=lambdas)
- maybe_log2 = tf.log(2.0) if surrogate_type == 'xent' else 1.0
- maybe_log2 = tf.cast(maybe_log2, logits.dtype.base_dtype)
- lambda_term = lambdas * target_rate * (1.0 - label_priors) * maybe_log2
- loss = tf.reshape(weighted_loss - lambda_term, original_shape)
- other_outputs = {
- 'lambdas': lambdas_variable,
- 'label_priors': label_priors,
- 'true_positives_lower_bound': true_positives_lower_bound(
- labels, logits, weights, surrogate_type),
- 'false_positives_upper_bound': false_positives_upper_bound(
- labels, logits, weights, surrogate_type)}
-
- return loss, other_outputs
-
-
-def _prepare_labels_logits_weights(labels, logits, weights):
- """Validates labels, logits, and weights.
-
- Converts inputs to tensors, checks shape compatibility, and casts dtype if
- necessary.
-
- Args:
- labels: A `Tensor` of shape [batch_size] or [batch_size, num_labels].
- logits: A `Tensor` with the same shape as `labels`.
- weights: Either `None` or a `Tensor` with shape broadcastable to `logits`.
-
- Returns:
- labels: Same as `labels` arg after possible conversion to tensor, cast, and
- reshape.
- logits: Same as `logits` arg after possible conversion to tensor and
- reshape.
- weights: Same as `weights` arg after possible conversion, cast, and reshape.
- original_shape: Shape of `labels` and `logits` before reshape.
-
- Raises:
- ValueError: If `labels` and `logits` do not have the same shape.
- """
- # Convert `labels` and `logits` to Tensors and standardize dtypes.
- logits = tf.convert_to_tensor(logits, name='logits')
- labels = util.convert_and_cast(labels, 'labels', logits.dtype.base_dtype)
- weights = util.convert_and_cast(weights, 'weights', logits.dtype.base_dtype)
-
- try:
- labels.get_shape().merge_with(logits.get_shape())
- except ValueError:
- raise ValueError('logits and labels must have the same shape (%s vs %s)' %
- (logits.get_shape(), labels.get_shape()))
-
- original_shape = labels.get_shape().as_list()
- if labels.get_shape().ndims > 0:
- original_shape[0] = -1
- if labels.get_shape().ndims <= 1:
- labels = tf.reshape(labels, [-1, 1])
- logits = tf.reshape(logits, [-1, 1])
-
- if weights.get_shape().ndims == 1:
- # Weights has shape [batch_size]. Reshape to [batch_size, 1].
- weights = tf.reshape(weights, [-1, 1])
- if weights.get_shape().ndims == 0:
- # Weights is a scalar. Change shape of weights to match logits.
- weights *= tf.ones_like(logits)
-
- return labels, logits, weights, original_shape
-
-
-def _range_to_anchors_and_delta(precision_range, num_anchors, dtype):
- """Calculates anchor points from precision range.
-
- Args:
- precision_range: As required in precision_recall_auc_loss.
- num_anchors: int, number of equally spaced anchor points.
- dtype: Data type of returned tensors.
-
- Returns:
- precision_values: A `Tensor` of data type dtype with equally spaced values
- in the interval precision_range.
- delta: The spacing between the values in precision_values.
-
- Raises:
- ValueError: If precision_range is invalid.
- """
- # Validate precision_range.
- if not 0 <= precision_range[0] <= precision_range[-1] <= 1:
- raise ValueError('precision values must obey 0 <= %f <= %f <= 1' %
- (precision_range[0], precision_range[-1]))
- if not 0 < len(precision_range) < 3:
- raise ValueError('length of precision_range (%d) must be 1 or 2' %
- len(precision_range))
-
- # Sets precision_values uniformly between min_precision and max_precision.
- values = numpy.linspace(start=precision_range[0],
- stop=precision_range[1],
- num=num_anchors+2)[1:-1]
- precision_values = util.convert_and_cast(
- values, 'precision_values', dtype)
- delta = util.convert_and_cast(
- values[0] - precision_range[0], 'delta', dtype)
- # Makes precision_values [1, 1, num_anchors].
- precision_values = util.expand_outer(precision_values, 3)
- return precision_values, delta
-
-
-def _create_dual_variable(name, shape, dtype, initializer, collections,
- trainable, dual_rate_factor):
- """Creates a new dual variable.
-
- Dual variables are required to be nonnegative. If trainable, their gradient
- is reversed so that they are maximized (rather than minimized) by the
- optimizer.
-
- Args:
- name: A string, the name for the new variable.
- shape: Shape of the new variable.
- dtype: Data type for the new variable.
- initializer: Initializer for the new variable.
- collections: List of graph collections keys. The new variable is added to
- these collections. Defaults to `[GraphKeys.GLOBAL_VARIABLES]`.
- trainable: If `True`, the default, also adds the variable to the graph
- collection `GraphKeys.TRAINABLE_VARIABLES`. This collection is used as
- the default list of variables to use by the `Optimizer` classes.
- dual_rate_factor: A floating point value or `Tensor`. The learning rate for
- the dual variable is scaled by this factor.
-
- Returns:
- dual_value: An op that computes the absolute value of the dual variable
- and reverses its gradient.
- dual_variable: The underlying variable itself.
- """
- # We disable partitioning while constructing dual variables because they will
- # be updated with assign, which is not available for partitioned variables.
- partitioner = tf.get_variable_scope().partitioner
- try:
- tf.get_variable_scope().set_partitioner(None)
- dual_variable = tf.contrib.framework.model_variable(
- name=name,
- shape=shape,
- dtype=dtype,
- initializer=initializer,
- collections=collections,
- trainable=trainable)
- finally:
- tf.get_variable_scope().set_partitioner(partitioner)
- # Using the absolute value enforces nonnegativity.
- dual_value = tf.abs(dual_variable)
-
- if trainable:
- # To reverse the gradient on the dual variable, multiply the gradient by
- # -dual_rate_factor
- dual_value = (tf.stop_gradient((1.0 + dual_rate_factor) * dual_value)
- - dual_rate_factor * dual_value)
- return dual_value, dual_variable
-
-
-def maybe_create_label_priors(label_priors,
- labels,
- weights,
- variables_collections):
- """Creates moving average ops to track label priors, if necessary.
-
- Args:
- label_priors: As required in e.g. precision_recall_auc_loss.
- labels: A `Tensor` of shape [batch_size] or [batch_size, num_labels].
- weights: As required in e.g. precision_recall_auc_loss.
- variables_collections: Optional list of collections for the variables, if
- any must be created.
-
- Returns:
- label_priors: A Tensor of shape [num_labels] consisting of the
- weighted label priors, after updating with moving average ops if created.
- """
- if label_priors is not None:
- label_priors = util.convert_and_cast(
- label_priors, name='label_priors', dtype=labels.dtype.base_dtype)
- return tf.squeeze(label_priors)
-
- label_priors = util.build_label_priors(
- labels,
- weights,
- variables_collections=variables_collections)
- return label_priors
-
-
-def true_positives_lower_bound(labels, logits, weights, surrogate_type):
- """Calculate a lower bound on the number of true positives.
-
- This lower bound on the number of true positives given `logits` and `labels`
- is the same one used in the global objectives loss functions.
-
- Args:
- labels: A `Tensor` of shape [batch_size] or [batch_size, num_labels].
- logits: A `Tensor` of shape [batch_size, num_labels] or
- [batch_size, num_labels, num_anchors]. If the third dimension is present,
- the lower bound is computed on each slice [:, :, k] independently.
- weights: Per-example loss coefficients, with shape broadcast-compatible with
- that of `labels`.
- surrogate_type: Either 'xent' or 'hinge', specifying which upper bound
- should be used for indicator functions.
-
- Returns:
- A `Tensor` of shape [num_labels] or [num_labels, num_anchors].
- """
- maybe_log2 = tf.log(2.0) if surrogate_type == 'xent' else 1.0
- maybe_log2 = tf.cast(maybe_log2, logits.dtype.base_dtype)
- if logits.get_shape().ndims == 3 and labels.get_shape().ndims < 3:
- labels = tf.expand_dims(labels, 2)
- loss_on_positives = util.weighted_surrogate_loss(
- labels, logits, surrogate_type, negative_weights=0.0) / maybe_log2
- return tf.reduce_sum(weights * (labels - loss_on_positives), 0)
-
-
-def false_positives_upper_bound(labels, logits, weights, surrogate_type):
- """Calculate an upper bound on the number of false positives.
-
- This upper bound on the number of false positives given `logits` and `labels`
- is the same one used in the global objectives loss functions.
-
- Args:
- labels: A `Tensor` of shape [batch_size, num_labels]
- logits: A `Tensor` of shape [batch_size, num_labels] or
- [batch_size, num_labels, num_anchors]. If the third dimension is present,
- the lower bound is computed on each slice [:, :, k] independently.
- weights: Per-example loss coefficients, with shape broadcast-compatible with
- that of `labels`.
- surrogate_type: Either 'xent' or 'hinge', specifying which upper bound
- should be used for indicator functions.
-
- Returns:
- A `Tensor` of shape [num_labels] or [num_labels, num_anchors].
- """
- maybe_log2 = tf.log(2.0) if surrogate_type == 'xent' else 1.0
- maybe_log2 = tf.cast(maybe_log2, logits.dtype.base_dtype)
- loss_on_negatives = util.weighted_surrogate_loss(
- labels, logits, surrogate_type, positive_weights=0.0) / maybe_log2
- return tf.reduce_sum(weights * loss_on_negatives, 0)
diff --git a/research/global_objectives/loss_layers_example.py b/research/global_objectives/loss_layers_example.py
deleted file mode 100644
index 2323cb0762e7f4eade8f283162be61cc45513d49..0000000000000000000000000000000000000000
--- a/research/global_objectives/loss_layers_example.py
+++ /dev/null
@@ -1,211 +0,0 @@
-# Copyright 2018 The TensorFlow Global Objectives Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Example for using global objectives.
-
-Illustrate, using synthetic data, how using the precision_at_recall loss
-significanly improves the performace of a linear classifier.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-# Dependency imports
-import numpy as np
-from sklearn.metrics import precision_score
-import tensorflow as tf
-from global_objectives import loss_layers
-
-# When optimizing using global_objectives, if set to True then the saddle point
-# optimization steps are performed internally by the Tensorflow optimizer,
-# otherwise by dedicated saddle-point steps as part of the optimization loop.
-USE_GO_SADDLE_POINT_OPT = False
-
-TARGET_RECALL = 0.98
-TRAIN_ITERATIONS = 150
-LEARNING_RATE = 1.0
-GO_DUAL_RATE_FACTOR = 15.0
-NUM_CHECKPOINTS = 6
-
-EXPERIMENT_DATA_CONFIG = {
- 'positives_centers': [[0, 1.0], [1, -0.5]],
- 'negatives_centers': [[0, -0.5], [1, 1.0]],
- 'positives_variances': [0.15, 0.1],
- 'negatives_variances': [0.15, 0.1],
- 'positives_counts': [500, 50],
- 'negatives_counts': [3000, 100]
-}
-
-
-def create_training_and_eval_data_for_experiment(**data_config):
- """Creates train and eval data sets.
-
- Note: The synthesized binary-labeled data is a mixture of four Gaussians - two
- positives and two negatives. The centers, variances, and sizes for each of
- the two positives and negatives mixtures are passed in the respective keys
- of data_config:
-
- Args:
- **data_config: Dictionary with Array entries as follows:
- positives_centers - float [2,2] two centers of positives data sets.
- negatives_centers - float [2,2] two centers of negatives data sets.
- positives_variances - float [2] Variances for the positives sets.
- negatives_variances - float [2] Variances for the negatives sets.
- positives_counts - int [2] Counts for each of the two positives sets.
- negatives_counts - int [2] Counts for each of the two negatives sets.
-
- Returns:
- A dictionary with two shuffled data sets created - one for training and one
- for eval. The dictionary keys are 'train_data', 'train_labels', 'eval_data',
- and 'eval_labels'. The data points are two-dimentional floats, and the
- labels are in {0,1}.
- """
- def data_points(is_positives, index):
- variance = data_config['positives_variances'
- if is_positives else 'negatives_variances'][index]
- center = data_config['positives_centers'
- if is_positives else 'negatives_centers'][index]
- count = data_config['positives_counts'
- if is_positives else 'negatives_counts'][index]
- return variance*np.random.randn(count, 2) + np.array([center])
-
- def create_data():
- return np.concatenate([data_points(False, 0),
- data_points(True, 0),
- data_points(True, 1),
- data_points(False, 1)], axis=0)
-
- def create_labels():
- """Creates an array of 0.0 or 1.0 labels for the data_config batches."""
- return np.array([0.0]*data_config['negatives_counts'][0] +
- [1.0]*data_config['positives_counts'][0] +
- [1.0]*data_config['positives_counts'][1] +
- [0.0]*data_config['negatives_counts'][1])
-
- permutation = np.random.permutation(
- sum(data_config['positives_counts'] + data_config['negatives_counts']))
-
- train_data = create_data()[permutation, :]
- eval_data = create_data()[permutation, :]
- train_labels = create_labels()[permutation]
- eval_labels = create_labels()[permutation]
-
- return {
- 'train_data': train_data,
- 'train_labels': train_labels,
- 'eval_data': eval_data,
- 'eval_labels': eval_labels
- }
-
-
-def train_model(data, use_global_objectives):
- """Trains a linear model for maximal accuracy or precision at given recall."""
-
- def precision_at_recall(scores, labels, target_recall):
- """Computes precision - at target recall - over data."""
- positive_scores = scores[labels == 1.0]
- threshold = np.percentile(positive_scores, 100 - target_recall*100)
- predicted = scores >= threshold
- return precision_score(labels, predicted)
-
- w = tf.Variable(tf.constant([-1.0, -1.0], shape=[2, 1]), trainable=True,
- name='weights', dtype=tf.float32)
- b = tf.Variable(tf.zeros([1]), trainable=True, name='biases',
- dtype=tf.float32)
-
- logits = tf.matmul(tf.cast(data['train_data'], tf.float32), w) + b
-
- labels = tf.constant(
- data['train_labels'],
- shape=[len(data['train_labels']), 1],
- dtype=tf.float32)
-
- if use_global_objectives:
- loss, other_outputs = loss_layers.precision_at_recall_loss(
- labels, logits,
- TARGET_RECALL,
- dual_rate_factor=GO_DUAL_RATE_FACTOR)
- loss = tf.reduce_mean(loss)
- else:
- loss = tf.reduce_mean(
- tf.nn.sigmoid_cross_entropy_with_logits(labels=labels, logits=logits))
-
- global_step = tf.Variable(0, trainable=False)
-
- learning_rate = tf.train.polynomial_decay(
- LEARNING_RATE,
- global_step,
- TRAIN_ITERATIONS, (LEARNING_RATE / TRAIN_ITERATIONS),
- power=1.0,
- cycle=False,
- name='learning_rate')
-
- optimizer = tf.train.GradientDescentOptimizer(learning_rate)
-
- if (not use_global_objectives) or USE_GO_SADDLE_POINT_OPT:
- training_op = optimizer.minimize(loss, global_step=global_step)
- else:
- lambdas = other_outputs['lambdas']
- primal_update_op = optimizer.minimize(loss, var_list=[w, b])
- dual_update_op = optimizer.minimize(
- loss, global_step=global_step, var_list=[lambdas])
-
- # Training loop:
- with tf.Session() as sess:
- checkpoint_step = TRAIN_ITERATIONS // NUM_CHECKPOINTS
- sess.run(tf.global_variables_initializer())
- step = sess.run(global_step)
-
- while step <= TRAIN_ITERATIONS:
- if (not use_global_objectives) or USE_GO_SADDLE_POINT_OPT:
- _, step, loss_value, w_value, b_value = sess.run(
- [training_op, global_step, loss, w, b])
- else:
- _, w_value, b_value = sess.run([primal_update_op, w, b])
- _, loss_value, step = sess.run([dual_update_op, loss, global_step])
-
- if use_global_objectives:
- go_outputs = sess.run(other_outputs.values())
-
- if step % checkpoint_step == 0:
- precision = precision_at_recall(
- np.dot(data['train_data'], w_value) + b_value,
- data['train_labels'], TARGET_RECALL)
-
- tf.logging.info('Loss = %f Precision = %f', loss_value, precision)
- if use_global_objectives:
- for i, output_name in enumerate(other_outputs.keys()):
- tf.logging.info('\t%s = %f', output_name, go_outputs[i])
-
- w_value, b_value = sess.run([w, b])
- return precision_at_recall(np.dot(data['eval_data'], w_value) + b_value,
- data['eval_labels'],
- TARGET_RECALL)
-
-
-def main(unused_argv):
- del unused_argv
- experiment_data = create_training_and_eval_data_for_experiment(
- **EXPERIMENT_DATA_CONFIG)
- global_objectives_loss_precision = train_model(experiment_data, True)
- tf.logging.info('global_objectives precision at requested recall is %f',
- global_objectives_loss_precision)
- cross_entropy_loss_precision = train_model(experiment_data, False)
- tf.logging.info('cross_entropy precision at requested recall is %f',
- cross_entropy_loss_precision)
-
-
-if __name__ == '__main__':
- tf.logging.set_verbosity(tf.logging.INFO)
- tf.app.run()
diff --git a/research/global_objectives/loss_layers_test.py b/research/global_objectives/loss_layers_test.py
deleted file mode 100644
index 3f91c80deec16a34f5271cdfadbd0d364c3a8cea..0000000000000000000000000000000000000000
--- a/research/global_objectives/loss_layers_test.py
+++ /dev/null
@@ -1,1379 +0,0 @@
-# Copyright 2018 The TensorFlow Global Objectives Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tests for global objectives loss layers."""
-
-# Dependency imports
-from absl.testing import parameterized
-import numpy
-import tensorflow as tf
-
-from global_objectives import loss_layers
-from global_objectives import util
-
-
-# TODO: Include weights in the lagrange multiplier update tests.
-class PrecisionRecallAUCLossTest(parameterized.TestCase, tf.test.TestCase):
-
- @parameterized.named_parameters(
- ('_xent', 'xent', 0.7),
- ('_hinge', 'hinge', 0.7),
- ('_hinge_2', 'hinge', 0.5)
- )
- def testSinglePointAUC(self, surrogate_type, target_precision):
- # Tests a case with only one anchor point, where the loss should equal
- # recall_at_precision_loss
- batch_shape = [10, 2]
- logits = tf.Variable(tf.random_normal(batch_shape))
- labels = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.4)))
-
- auc_loss, _ = loss_layers.precision_recall_auc_loss(
- labels,
- logits,
- precision_range=(target_precision - 0.01, target_precision + 0.01),
- num_anchors=1,
- surrogate_type=surrogate_type)
- point_loss, _ = loss_layers.recall_at_precision_loss(
- labels, logits, target_precision=target_precision,
- surrogate_type=surrogate_type)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- self.assertAllClose(auc_loss.eval(), point_loss.eval())
-
- def testThreePointAUC(self):
- # Tests a case with three anchor points against a weighted sum of recall
- # at precision losses.
- batch_shape = [11, 3]
- logits = tf.Variable(tf.random_normal(batch_shape))
- labels = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.4)))
-
- # TODO: Place the hing/xent loss in a for loop.
- auc_loss, _ = loss_layers.precision_recall_auc_loss(
- labels, logits, num_anchors=1)
- first_point_loss, _ = loss_layers.recall_at_precision_loss(
- labels, logits, target_precision=0.25)
- second_point_loss, _ = loss_layers.recall_at_precision_loss(
- labels, logits, target_precision=0.5)
- third_point_loss, _ = loss_layers.recall_at_precision_loss(
- labels, logits, target_precision=0.75)
- expected_loss = (first_point_loss + second_point_loss +
- third_point_loss) / 3
-
- auc_loss_hinge, _ = loss_layers.precision_recall_auc_loss(
- labels, logits, num_anchors=1, surrogate_type='hinge')
- first_point_hinge, _ = loss_layers.recall_at_precision_loss(
- labels, logits, target_precision=0.25, surrogate_type='hinge')
- second_point_hinge, _ = loss_layers.recall_at_precision_loss(
- labels, logits, target_precision=0.5, surrogate_type='hinge')
- third_point_hinge, _ = loss_layers.recall_at_precision_loss(
- labels, logits, target_precision=0.75, surrogate_type='hinge')
- expected_hinge = (first_point_hinge + second_point_hinge +
- third_point_hinge) / 3
-
- with self.test_session():
- tf.global_variables_initializer().run()
- self.assertAllClose(auc_loss.eval(), expected_loss.eval())
- self.assertAllClose(auc_loss_hinge.eval(), expected_hinge.eval())
-
- def testLagrangeMultiplierUpdateDirection(self):
- for target_precision in [0.35, 0.65]:
- precision_range = (target_precision - 0.01, target_precision + 0.01)
-
- for surrogate_type in ['xent', 'hinge']:
- kwargs = {'precision_range': precision_range,
- 'num_anchors': 1,
- 'surrogate_type': surrogate_type,
- 'scope': 'pr-auc_{}_{}'.format(target_precision,
- surrogate_type)}
- run_lagrange_multiplier_test(
- global_objective=loss_layers.precision_recall_auc_loss,
- objective_kwargs=kwargs,
- data_builder=_multilabel_data,
- test_object=self)
- kwargs['scope'] = 'other-' + kwargs['scope']
- run_lagrange_multiplier_test(
- global_objective=loss_layers.precision_recall_auc_loss,
- objective_kwargs=kwargs,
- data_builder=_other_multilabel_data(surrogate_type),
- test_object=self)
-
-
-class ROCAUCLossTest(parameterized.TestCase, tf.test.TestCase):
-
- def testSimpleScores(self):
- # Tests the loss on data with only one negative example with score zero.
- # In this case, the loss should equal the surrogate loss on the scores with
- # positive labels.
- num_positives = 10
- scores_positives = tf.constant(3.0 * numpy.random.randn(num_positives),
- shape=[num_positives, 1])
- labels = tf.constant([0.0] + [1.0] * num_positives,
- shape=[num_positives + 1, 1])
- scores = tf.concat([[[0.0]], scores_positives], 0)
-
- loss = tf.reduce_sum(
- loss_layers.roc_auc_loss(labels, scores, surrogate_type='hinge')[0])
- expected_loss = tf.reduce_sum(
- tf.maximum(1.0 - scores_positives, 0)) / (num_positives + 1)
- with self.test_session():
- self.assertAllClose(expected_loss.eval(), loss.eval())
-
- def testRandomROCLoss(self):
- # Checks that random Bernoulli scores and labels has ~25% swaps.
- shape = [1000, 30]
- scores = tf.constant(
- numpy.random.randint(0, 2, size=shape), shape=shape, dtype=tf.float32)
- labels = tf.constant(
- numpy.random.randint(0, 2, size=shape), shape=shape, dtype=tf.float32)
- loss = tf.reduce_mean(loss_layers.roc_auc_loss(
- labels, scores, surrogate_type='hinge')[0])
- with self.test_session():
- self.assertAllClose(0.25, loss.eval(), 1e-2)
-
- @parameterized.named_parameters(
- ('_zero_hinge', 'xent',
- [0.0, 0.0, 0.0, 1.0, 1.0, 1.0],
- [-5.0, -7.0, -9.0, 8.0, 10.0, 14.0],
- 0.0),
- ('_zero_xent', 'hinge',
- [0.0, 0.0, 0.0, 1.0, 1.0, 1.0],
- [-0.2, 0, -0.1, 1.0, 1.1, 1.0],
- 0.0),
- ('_xent', 'xent',
- [0.0, 0.0, 0.0, 1.0, 1.0, 1.0],
- [0.0, -17.0, -19.0, 1.0, 14.0, 14.0],
- numpy.log(1.0 + numpy.exp(-1.0)) / 6),
- ('_hinge', 'hinge',
- [0.0, 0.0, 0.0, 1.0, 1.0, 1.0],
- [-0.2, -0.05, 0.0, 0.95, 0.8, 1.0],
- 0.4 / 6)
- )
- def testManualROCLoss(self, surrogate_type, labels, logits, expected_value):
- labels = tf.constant(labels)
- logits = tf.constant(logits)
- loss, _ = loss_layers.roc_auc_loss(
- labels=labels, logits=logits, surrogate_type=surrogate_type)
-
- with self.test_session():
- self.assertAllClose(expected_value, tf.reduce_sum(loss).eval())
-
- def testMultiLabelROCLoss(self):
- # Tests the loss on multi-label data against manually computed loss.
- targets = numpy.array([[0.0, 0.0, 1.0, 1.0], [0.0, 0.0, 1.0, 1.0]])
- scores = numpy.array([[0.1, 1.0, 1.1, 1.0], [1.0, 0.0, 1.3, 1.1]])
- class_1_auc = tf.reduce_sum(
- loss_layers.roc_auc_loss(targets[0], scores[0])[0])
- class_2_auc = tf.reduce_sum(
- loss_layers.roc_auc_loss(targets[1], scores[1])[0])
- total_auc = tf.reduce_sum(loss_layers.roc_auc_loss(
- targets.transpose(), scores.transpose())[0])
-
- with self.test_session():
- self.assertAllClose(total_auc.eval(),
- class_1_auc.eval() + class_2_auc.eval())
-
- def testWeights(self):
- # Test the loss with per-example weights.
- # The logits_negatives below are repeated, so that setting half their
- # weights to 2 and the other half to 0 should leave the loss unchanged.
- logits_positives = tf.constant([2.54321, -0.26, 3.334334], shape=[3, 1])
- logits_negatives = tf.constant([-0.6, 1, -1.3, -1.3, -0.6, 1], shape=[6, 1])
- logits = tf.concat([logits_positives, logits_negatives], 0)
- targets = tf.constant([1, 1, 1, 0, 0, 0, 0, 0, 0],
- shape=[9, 1], dtype=tf.float32)
- weights = tf.constant([1, 1, 1, 0, 0, 0, 2, 2, 2],
- shape=[9, 1], dtype=tf.float32)
-
- loss = tf.reduce_sum(loss_layers.roc_auc_loss(targets, logits)[0])
- weighted_loss = tf.reduce_sum(
- loss_layers.roc_auc_loss(targets, logits, weights)[0])
-
- with self.test_session():
- self.assertAllClose(loss.eval(), weighted_loss.eval())
-
-
-class RecallAtPrecisionTest(tf.test.TestCase):
-
- def testEqualWeightLoss(self):
- # Tests a special case where the loss should equal cross entropy loss.
- target_precision = 1.0
- num_labels = 5
- batch_shape = [20, num_labels]
- logits = tf.Variable(tf.random_normal(batch_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.7)))
- label_priors = tf.constant(0.34, shape=[num_labels])
-
- loss, _ = loss_layers.recall_at_precision_loss(
- targets, logits, target_precision, label_priors=label_priors)
- expected_loss = (
- tf.contrib.nn.deprecated_flipped_sigmoid_cross_entropy_with_logits(
- logits, targets))
-
- with self.test_session() as session:
- tf.global_variables_initializer().run()
- loss_val, expected_val = session.run([loss, expected_loss])
- self.assertAllClose(loss_val, expected_val)
-
- def testEqualWeightLossWithMultiplePrecisions(self):
- """Tests a case where the loss equals xent loss with multiple precisions."""
- target_precision = [1.0, 1.0]
- num_labels = 2
- batch_size = 20
- target_shape = [batch_size, num_labels]
- logits = tf.Variable(tf.random_normal(target_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(target_shape), 0.7)))
- label_priors = tf.constant([0.34], shape=[num_labels])
-
- loss, _ = loss_layers.recall_at_precision_loss(
- targets,
- logits,
- target_precision,
- label_priors=label_priors,
- surrogate_type='xent',
- )
-
- expected_loss = (
- tf.contrib.nn.deprecated_flipped_sigmoid_cross_entropy_with_logits(
- logits, targets))
-
- with self.test_session() as session:
- tf.global_variables_initializer().run()
- loss_val, expected_val = session.run([loss, expected_loss])
- self.assertAllClose(loss_val, expected_val)
-
- def testPositivesOnlyLoss(self):
- # Tests a special case where the loss should equal cross entropy loss
- # on the negatives only.
- target_precision = 1.0
- num_labels = 3
- batch_shape = [30, num_labels]
- logits = tf.Variable(tf.random_normal(batch_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.4)))
- label_priors = tf.constant(0.45, shape=[num_labels])
-
- loss, _ = loss_layers.recall_at_precision_loss(
- targets, logits, target_precision, label_priors=label_priors,
- lambdas_initializer=tf.zeros_initializer())
- expected_loss = util.weighted_sigmoid_cross_entropy_with_logits(
- targets,
- logits,
- positive_weights=1.0,
- negative_weights=0.0)
-
- with self.test_session() as session:
- tf.global_variables_initializer().run()
- loss_val, expected_val = session.run([loss, expected_loss])
- self.assertAllClose(loss_val, expected_val)
-
- def testEquivalenceBetweenSingleAndMultiplePrecisions(self):
- """Checks recall at precision with different precision values.
-
- Runs recall at precision with multiple precision values, and runs each label
- seperately with its own precision value as a scalar. Validates that the
- returned loss values are the same.
- """
- target_precision = [0.2, 0.9, 0.4]
- num_labels = 3
- batch_shape = [30, num_labels]
- logits = tf.Variable(tf.random_normal(batch_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.4)))
- label_priors = tf.constant([0.45, 0.8, 0.3], shape=[num_labels])
-
- multi_label_loss, _ = loss_layers.recall_at_precision_loss(
- targets, logits, target_precision, label_priors=label_priors,
- )
-
- single_label_losses = [
- loss_layers.recall_at_precision_loss(
- tf.expand_dims(targets[:, i], -1),
- tf.expand_dims(logits[:, i], -1),
- target_precision[i],
- label_priors=label_priors[i])[0]
- for i in range(num_labels)
- ]
-
- single_label_losses = tf.concat(single_label_losses, 1)
-
- with self.test_session() as session:
- tf.global_variables_initializer().run()
- multi_label_loss_val, single_label_loss_val = session.run(
- [multi_label_loss, single_label_losses])
- self.assertAllClose(multi_label_loss_val, single_label_loss_val)
-
- def testEquivalenceBetweenSingleAndEqualMultiplePrecisions(self):
- """Compares single and multiple target precisions with the same value.
-
- Checks that using a single target precision and multiple target precisions
- with the same value would result in the same loss value.
- """
- num_labels = 2
- target_shape = [20, num_labels]
- logits = tf.Variable(tf.random_normal(target_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(target_shape), 0.7)))
- label_priors = tf.constant([0.34], shape=[num_labels])
-
- multi_precision_loss, _ = loss_layers.recall_at_precision_loss(
- targets,
- logits,
- [0.75, 0.75],
- label_priors=label_priors,
- surrogate_type='xent',
- )
-
- single_precision_loss, _ = loss_layers.recall_at_precision_loss(
- targets,
- logits,
- 0.75,
- label_priors=label_priors,
- surrogate_type='xent',
- )
-
- with self.test_session() as session:
- tf.global_variables_initializer().run()
- multi_precision_loss_val, single_precision_loss_val = session.run(
- [multi_precision_loss, single_precision_loss])
- self.assertAllClose(multi_precision_loss_val, single_precision_loss_val)
-
- def testLagrangeMultiplierUpdateDirection(self):
- for target_precision in [0.35, 0.65]:
- for surrogate_type in ['xent', 'hinge']:
- kwargs = {'target_precision': target_precision,
- 'surrogate_type': surrogate_type,
- 'scope': 'r-at-p_{}_{}'.format(target_precision,
- surrogate_type)}
- run_lagrange_multiplier_test(
- global_objective=loss_layers.recall_at_precision_loss,
- objective_kwargs=kwargs,
- data_builder=_multilabel_data,
- test_object=self)
- kwargs['scope'] = 'other-' + kwargs['scope']
- run_lagrange_multiplier_test(
- global_objective=loss_layers.recall_at_precision_loss,
- objective_kwargs=kwargs,
- data_builder=_other_multilabel_data(surrogate_type),
- test_object=self)
-
- def testLagrangeMultiplierUpdateDirectionWithMultiplePrecisions(self):
- """Runs Lagrange multiplier test with multiple precision values."""
- target_precision = [0.65, 0.35]
-
- for surrogate_type in ['xent', 'hinge']:
- scope_str = 'r-at-p_{}_{}'.format(
- '_'.join([str(precision) for precision in target_precision]),
- surrogate_type)
- kwargs = {
- 'target_precision': target_precision,
- 'surrogate_type': surrogate_type,
- 'scope': scope_str,
- }
- run_lagrange_multiplier_test(
- global_objective=loss_layers.recall_at_precision_loss,
- objective_kwargs=kwargs,
- data_builder=_multilabel_data,
- test_object=self)
- kwargs['scope'] = 'other-' + kwargs['scope']
- run_lagrange_multiplier_test(
- global_objective=loss_layers.recall_at_precision_loss,
- objective_kwargs=kwargs,
- data_builder=_other_multilabel_data(surrogate_type),
- test_object=self)
-
-
-class PrecisionAtRecallTest(tf.test.TestCase):
-
- def testCrossEntropyEquivalence(self):
- # Checks a special case where the loss should equal cross-entropy loss.
- target_recall = 1.0
- num_labels = 3
- batch_shape = [10, num_labels]
- logits = tf.Variable(tf.random_normal(batch_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.4)))
-
- loss, _ = loss_layers.precision_at_recall_loss(
- targets, logits, target_recall,
- lambdas_initializer=tf.constant_initializer(1.0))
- expected_loss = util.weighted_sigmoid_cross_entropy_with_logits(
- targets, logits)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- self.assertAllClose(loss.eval(), expected_loss.eval())
-
- def testNegativesOnlyLoss(self):
- # Checks a special case where the loss should equal the loss on
- # the negative examples only.
- target_recall = 0.61828
- num_labels = 4
- batch_shape = [8, num_labels]
- logits = tf.Variable(tf.random_normal(batch_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.6)))
-
- loss, _ = loss_layers.precision_at_recall_loss(
- targets,
- logits,
- target_recall,
- surrogate_type='hinge',
- lambdas_initializer=tf.constant_initializer(0.0),
- scope='negatives_only_test')
- expected_loss = util.weighted_hinge_loss(
- targets, logits, positive_weights=0.0, negative_weights=1.0)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- self.assertAllClose(expected_loss.eval(), loss.eval())
-
- def testLagrangeMultiplierUpdateDirection(self):
- for target_recall in [0.34, 0.66]:
- for surrogate_type in ['xent', 'hinge']:
- kwargs = {'target_recall': target_recall,
- 'dual_rate_factor': 1.0,
- 'surrogate_type': surrogate_type,
- 'scope': 'p-at-r_{}_{}'.format(target_recall, surrogate_type)}
-
- run_lagrange_multiplier_test(
- global_objective=loss_layers.precision_at_recall_loss,
- objective_kwargs=kwargs,
- data_builder=_multilabel_data,
- test_object=self)
- kwargs['scope'] = 'other-' + kwargs['scope']
- run_lagrange_multiplier_test(
- global_objective=loss_layers.precision_at_recall_loss,
- objective_kwargs=kwargs,
- data_builder=_other_multilabel_data(surrogate_type),
- test_object=self)
-
- def testCrossEntropyEquivalenceWithMultipleRecalls(self):
- """Checks a case where the loss equals xent loss with multiple recalls."""
- num_labels = 3
- target_recall = [1.0] * num_labels
- batch_shape = [10, num_labels]
- logits = tf.Variable(tf.random_normal(batch_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.4)))
-
- loss, _ = loss_layers.precision_at_recall_loss(
- targets, logits, target_recall,
- lambdas_initializer=tf.constant_initializer(1.0))
- expected_loss = util.weighted_sigmoid_cross_entropy_with_logits(
- targets, logits)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- self.assertAllClose(loss.eval(), expected_loss.eval())
-
- def testNegativesOnlyLossWithMultipleRecalls(self):
- """Tests a case where the loss equals the loss on the negative examples.
-
- Checks this special case using multiple target recall values.
- """
- num_labels = 4
- target_recall = [0.61828] * num_labels
- batch_shape = [8, num_labels]
- logits = tf.Variable(tf.random_normal(batch_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.6)))
-
- loss, _ = loss_layers.precision_at_recall_loss(
- targets,
- logits,
- target_recall,
- surrogate_type='hinge',
- lambdas_initializer=tf.constant_initializer(0.0),
- scope='negatives_only_test')
- expected_loss = util.weighted_hinge_loss(
- targets, logits, positive_weights=0.0, negative_weights=1.0)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- self.assertAllClose(expected_loss.eval(), loss.eval())
-
- def testLagrangeMultiplierUpdateDirectionWithMultipleRecalls(self):
- """Runs Lagrange multiplier test with multiple recall values."""
- target_recall = [0.34, 0.66]
- for surrogate_type in ['xent', 'hinge']:
- scope_str = 'p-at-r_{}_{}'.format(
- '_'.join([str(recall) for recall in target_recall]),
- surrogate_type)
- kwargs = {'target_recall': target_recall,
- 'dual_rate_factor': 1.0,
- 'surrogate_type': surrogate_type,
- 'scope': scope_str}
-
- run_lagrange_multiplier_test(
- global_objective=loss_layers.precision_at_recall_loss,
- objective_kwargs=kwargs,
- data_builder=_multilabel_data,
- test_object=self)
- kwargs['scope'] = 'other-' + kwargs['scope']
- run_lagrange_multiplier_test(
- global_objective=loss_layers.precision_at_recall_loss,
- objective_kwargs=kwargs,
- data_builder=_other_multilabel_data(surrogate_type),
- test_object=self)
-
- def testEquivalenceBetweenSingleAndMultipleRecalls(self):
- """Checks precision at recall with multiple different recall values.
-
- Runs precision at recall with multiple recall values, and runs each label
- seperately with its own recall value as a scalar. Validates that the
- returned loss values are the same.
- """
- target_precision = [0.7, 0.9, 0.4]
- num_labels = 3
- batch_shape = [30, num_labels]
- logits = tf.Variable(tf.random_normal(batch_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.4)))
- label_priors = tf.constant(0.45, shape=[num_labels])
-
- multi_label_loss, _ = loss_layers.precision_at_recall_loss(
- targets, logits, target_precision, label_priors=label_priors
- )
-
- single_label_losses = [
- loss_layers.precision_at_recall_loss(
- tf.expand_dims(targets[:, i], -1),
- tf.expand_dims(logits[:, i], -1),
- target_precision[i],
- label_priors=label_priors[i])[0]
- for i in range(num_labels)
- ]
-
- single_label_losses = tf.concat(single_label_losses, 1)
-
- with self.test_session() as session:
- tf.global_variables_initializer().run()
- multi_label_loss_val, single_label_loss_val = session.run(
- [multi_label_loss, single_label_losses])
- self.assertAllClose(multi_label_loss_val, single_label_loss_val)
-
- def testEquivalenceBetweenSingleAndEqualMultipleRecalls(self):
- """Compares single and multiple target recalls of the same value.
-
- Checks that using a single target recall and multiple recalls with the
- same value would result in the same loss value.
- """
- num_labels = 2
- target_shape = [20, num_labels]
- logits = tf.Variable(tf.random_normal(target_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(target_shape), 0.7)))
- label_priors = tf.constant([0.34], shape=[num_labels])
-
- multi_precision_loss, _ = loss_layers.precision_at_recall_loss(
- targets,
- logits,
- [0.75, 0.75],
- label_priors=label_priors,
- surrogate_type='xent',
- )
-
- single_precision_loss, _ = loss_layers.precision_at_recall_loss(
- targets,
- logits,
- 0.75,
- label_priors=label_priors,
- surrogate_type='xent',
- )
-
- with self.test_session() as session:
- tf.global_variables_initializer().run()
- multi_precision_loss_val, single_precision_loss_val = session.run(
- [multi_precision_loss, single_precision_loss])
- self.assertAllClose(multi_precision_loss_val, single_precision_loss_val)
-
-
-class FalsePositiveRateAtTruePositiveRateTest(tf.test.TestCase):
-
- def testNegativesOnlyLoss(self):
- # Checks a special case where the loss returned should be the loss on the
- # negative examples.
- target_recall = 0.6
- num_labels = 3
- batch_shape = [3, num_labels]
- logits = tf.Variable(tf.random_normal(batch_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.4)))
- label_priors = tf.constant(numpy.random.uniform(size=[num_labels]),
- dtype=tf.float32)
-
- xent_loss, _ = loss_layers.false_positive_rate_at_true_positive_rate_loss(
- targets, logits, target_recall, label_priors=label_priors,
- lambdas_initializer=tf.constant_initializer(0.0))
- xent_expected = util.weighted_sigmoid_cross_entropy_with_logits(
- targets,
- logits,
- positive_weights=0.0,
- negative_weights=1.0)
- hinge_loss, _ = loss_layers.false_positive_rate_at_true_positive_rate_loss(
- targets, logits, target_recall, label_priors=label_priors,
- lambdas_initializer=tf.constant_initializer(0.0),
- surrogate_type='hinge')
- hinge_expected = util.weighted_hinge_loss(
- targets,
- logits,
- positive_weights=0.0,
- negative_weights=1.0)
-
- with self.test_session() as session:
- tf.global_variables_initializer().run()
- xent_val, xent_expected = session.run([xent_loss, xent_expected])
- self.assertAllClose(xent_val, xent_expected)
- hinge_val, hinge_expected = session.run([hinge_loss, hinge_expected])
- self.assertAllClose(hinge_val, hinge_expected)
-
- def testPositivesOnlyLoss(self):
- # Checks a special case where the loss returned should be the loss on the
- # positive examples only.
- target_recall = 1.0
- num_labels = 5
- batch_shape = [5, num_labels]
- logits = tf.Variable(tf.random_normal(batch_shape))
- targets = tf.ones_like(logits)
- label_priors = tf.constant(numpy.random.uniform(size=[num_labels]),
- dtype=tf.float32)
-
- loss, _ = loss_layers.false_positive_rate_at_true_positive_rate_loss(
- targets, logits, target_recall, label_priors=label_priors)
- expected_loss = tf.nn.sigmoid_cross_entropy_with_logits(
- labels=targets, logits=logits)
- hinge_loss, _ = loss_layers.false_positive_rate_at_true_positive_rate_loss(
- targets, logits, target_recall, label_priors=label_priors,
- surrogate_type='hinge')
- expected_hinge = util.weighted_hinge_loss(
- targets, logits)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- self.assertAllClose(loss.eval(), expected_loss.eval())
- self.assertAllClose(hinge_loss.eval(), expected_hinge.eval())
-
- def testEqualWeightLoss(self):
- # Checks a special case where the loss returned should be proportional to
- # the ordinary loss.
- target_recall = 1.0
- num_labels = 4
- batch_shape = [40, num_labels]
- logits = tf.Variable(tf.random_normal(batch_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.6)))
- label_priors = tf.constant(0.5, shape=[num_labels])
-
- loss, _ = loss_layers.false_positive_rate_at_true_positive_rate_loss(
- targets, logits, target_recall, label_priors=label_priors)
- expected_loss = tf.nn.sigmoid_cross_entropy_with_logits(
- labels=targets, logits=logits)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- self.assertAllClose(loss.eval(), expected_loss.eval())
-
- def testLagrangeMultiplierUpdateDirection(self):
- for target_rate in [0.35, 0.65]:
- for surrogate_type in ['xent', 'hinge']:
- kwargs = {'target_rate': target_rate,
- 'surrogate_type': surrogate_type,
- 'scope': 'fpr-at-tpr_{}_{}'.format(target_rate,
- surrogate_type)}
- # True positive rate is a synonym for recall, so we use the
- # recall constraint data.
- run_lagrange_multiplier_test(
- global_objective=(
- loss_layers.false_positive_rate_at_true_positive_rate_loss),
- objective_kwargs=kwargs,
- data_builder=_multilabel_data,
- test_object=self)
- kwargs['scope'] = 'other-' + kwargs['scope']
- run_lagrange_multiplier_test(
- global_objective=(
- loss_layers.false_positive_rate_at_true_positive_rate_loss),
- objective_kwargs=kwargs,
- data_builder=_other_multilabel_data(surrogate_type),
- test_object=self)
-
- def testLagrangeMultiplierUpdateDirectionWithMultipleRates(self):
- """Runs Lagrange multiplier test with multiple target rates."""
- target_rate = [0.35, 0.65]
- for surrogate_type in ['xent', 'hinge']:
- kwargs = {'target_rate': target_rate,
- 'surrogate_type': surrogate_type,
- 'scope': 'fpr-at-tpr_{}_{}'.format(
- '_'.join([str(target) for target in target_rate]),
- surrogate_type)}
- # True positive rate is a synonym for recall, so we use the
- # recall constraint data.
- run_lagrange_multiplier_test(
- global_objective=(
- loss_layers.false_positive_rate_at_true_positive_rate_loss),
- objective_kwargs=kwargs,
- data_builder=_multilabel_data,
- test_object=self)
- kwargs['scope'] = 'other-' + kwargs['scope']
- run_lagrange_multiplier_test(
- global_objective=(
- loss_layers.false_positive_rate_at_true_positive_rate_loss),
- objective_kwargs=kwargs,
- data_builder=_other_multilabel_data(surrogate_type),
- test_object=self)
-
- def testEquivalenceBetweenSingleAndEqualMultipleRates(self):
- """Compares single and multiple target rates of the same value.
-
- Checks that using a single target rate and multiple rates with the
- same value would result in the same loss value.
- """
- num_labels = 2
- target_shape = [20, num_labels]
- logits = tf.Variable(tf.random_normal(target_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(target_shape), 0.7)))
- label_priors = tf.constant([0.34], shape=[num_labels])
-
- multi_label_loss, _ = (
- loss_layers.false_positive_rate_at_true_positive_rate_loss(
- targets, logits, [0.75, 0.75], label_priors=label_priors))
-
- single_label_loss, _ = (
- loss_layers.false_positive_rate_at_true_positive_rate_loss(
- targets, logits, 0.75, label_priors=label_priors))
-
- with self.test_session() as session:
- tf.global_variables_initializer().run()
- multi_label_loss_val, single_label_loss_val = session.run(
- [multi_label_loss, single_label_loss])
- self.assertAllClose(multi_label_loss_val, single_label_loss_val)
-
- def testEquivalenceBetweenSingleAndMultipleRates(self):
- """Compares single and multiple target rates of different values.
-
- Runs false_positive_rate_at_true_positive_rate_loss with multiple target
- rates, and runs each label seperately with its own target rate as a
- scalar. Validates that the returned loss values are the same.
- """
- target_precision = [0.7, 0.9, 0.4]
- num_labels = 3
- batch_shape = [30, num_labels]
- logits = tf.Variable(tf.random_normal(batch_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.4)))
- label_priors = tf.constant(0.45, shape=[num_labels])
-
- multi_label_loss, _ = (
- loss_layers.false_positive_rate_at_true_positive_rate_loss(
- targets, logits, target_precision, label_priors=label_priors))
-
- single_label_losses = [
- loss_layers.false_positive_rate_at_true_positive_rate_loss(
- tf.expand_dims(targets[:, i], -1),
- tf.expand_dims(logits[:, i], -1),
- target_precision[i],
- label_priors=label_priors[i])[0]
- for i in range(num_labels)
- ]
-
- single_label_losses = tf.concat(single_label_losses, 1)
-
- with self.test_session() as session:
- tf.global_variables_initializer().run()
- multi_label_loss_val, single_label_loss_val = session.run(
- [multi_label_loss, single_label_losses])
- self.assertAllClose(multi_label_loss_val, single_label_loss_val)
-
-
-class TruePositiveRateAtFalsePositiveRateTest(tf.test.TestCase):
-
- def testPositivesOnlyLoss(self):
- # A special case where the loss should equal the loss on the positive
- # examples.
- target_rate = numpy.random.uniform()
- num_labels = 3
- batch_shape = [20, num_labels]
- logits = tf.Variable(tf.random_normal(batch_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.6)))
- label_priors = tf.constant(numpy.random.uniform(size=[num_labels]),
- dtype=tf.float32)
-
- xent_loss, _ = loss_layers.true_positive_rate_at_false_positive_rate_loss(
- targets, logits, target_rate, label_priors=label_priors,
- lambdas_initializer=tf.constant_initializer(0.0))
- xent_expected = util.weighted_sigmoid_cross_entropy_with_logits(
- targets,
- logits,
- positive_weights=1.0,
- negative_weights=0.0)
- hinge_loss, _ = loss_layers.true_positive_rate_at_false_positive_rate_loss(
- targets, logits, target_rate, label_priors=label_priors,
- lambdas_initializer=tf.constant_initializer(0.0),
- surrogate_type='hinge')
- hinge_expected = util.weighted_hinge_loss(
- targets,
- logits,
- positive_weights=1.0,
- negative_weights=0.0)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- self.assertAllClose(xent_expected.eval(), xent_loss.eval())
- self.assertAllClose(hinge_expected.eval(), hinge_loss.eval())
-
- def testNegativesOnlyLoss(self):
- # A special case where the loss should equal the loss on the negative
- # examples, minus target_rate * (1 - label_priors) * maybe_log2.
- target_rate = numpy.random.uniform()
- num_labels = 3
- batch_shape = [25, num_labels]
- logits = tf.Variable(tf.random_normal(batch_shape))
- targets = tf.zeros_like(logits)
- label_priors = tf.constant(numpy.random.uniform(size=[num_labels]),
- dtype=tf.float32)
-
- xent_loss, _ = loss_layers.true_positive_rate_at_false_positive_rate_loss(
- targets, logits, target_rate, label_priors=label_priors)
- xent_expected = tf.subtract(
- util.weighted_sigmoid_cross_entropy_with_logits(targets,
- logits,
- positive_weights=0.0,
- negative_weights=1.0),
- target_rate * (1.0 - label_priors) * numpy.log(2))
- hinge_loss, _ = loss_layers.true_positive_rate_at_false_positive_rate_loss(
- targets, logits, target_rate, label_priors=label_priors,
- surrogate_type='hinge')
- hinge_expected = util.weighted_hinge_loss(
- targets, logits) - target_rate * (1.0 - label_priors)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- self.assertAllClose(xent_expected.eval(), xent_loss.eval())
- self.assertAllClose(hinge_expected.eval(), hinge_loss.eval())
-
- def testLagrangeMultiplierUpdateDirection(self):
- for target_rate in [0.35, 0.65]:
- for surrogate_type in ['xent', 'hinge']:
- kwargs = {'target_rate': target_rate,
- 'surrogate_type': surrogate_type,
- 'scope': 'tpr-at-fpr_{}_{}'.format(target_rate,
- surrogate_type)}
- run_lagrange_multiplier_test(
- global_objective=(
- loss_layers.true_positive_rate_at_false_positive_rate_loss),
- objective_kwargs=kwargs,
- data_builder=_multilabel_data,
- test_object=self)
- kwargs['scope'] = 'other-' + kwargs['scope']
- run_lagrange_multiplier_test(
- global_objective=(
- loss_layers.true_positive_rate_at_false_positive_rate_loss),
- objective_kwargs=kwargs,
- data_builder=_other_multilabel_data(surrogate_type),
- test_object=self)
-
- def testLagrangeMultiplierUpdateDirectionWithMultipleRates(self):
- """Runs Lagrange multiplier test with multiple target rates."""
- target_rate = [0.35, 0.65]
- for surrogate_type in ['xent', 'hinge']:
- kwargs = {'target_rate': target_rate,
- 'surrogate_type': surrogate_type,
- 'scope': 'tpr-at-fpr_{}_{}'.format(
- '_'.join([str(target) for target in target_rate]),
- surrogate_type)}
- run_lagrange_multiplier_test(
- global_objective=(
- loss_layers.true_positive_rate_at_false_positive_rate_loss),
- objective_kwargs=kwargs,
- data_builder=_multilabel_data,
- test_object=self)
- kwargs['scope'] = 'other-' + kwargs['scope']
- run_lagrange_multiplier_test(
- global_objective=(
- loss_layers.true_positive_rate_at_false_positive_rate_loss),
- objective_kwargs=kwargs,
- data_builder=_other_multilabel_data(surrogate_type),
- test_object=self)
-
- def testEquivalenceBetweenSingleAndEqualMultipleRates(self):
- """Compares single and multiple target rates of the same value.
-
- Checks that using a single target rate and multiple rates with the
- same value would result in the same loss value.
- """
- num_labels = 2
- target_shape = [20, num_labels]
- logits = tf.Variable(tf.random_normal(target_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(target_shape), 0.7)))
- label_priors = tf.constant([0.34], shape=[num_labels])
-
- multi_label_loss, _ = (
- loss_layers.true_positive_rate_at_false_positive_rate_loss(
- targets, logits, [0.75, 0.75], label_priors=label_priors))
-
- single_label_loss, _ = (
- loss_layers.true_positive_rate_at_false_positive_rate_loss(
- targets, logits, 0.75, label_priors=label_priors))
-
- with self.test_session() as session:
- tf.global_variables_initializer().run()
- multi_label_loss_val, single_label_loss_val = session.run(
- [multi_label_loss, single_label_loss])
- self.assertAllClose(multi_label_loss_val, single_label_loss_val)
-
- def testEquivalenceBetweenSingleAndMultipleRates(self):
- """Compares single and multiple target rates of different values.
-
- Runs true_positive_rate_at_false_positive_rate_loss with multiple target
- rates, and runs each label seperately with its own target rate as a
- scalar. Validates that the returned loss values are the same.
- """
- target_precision = [0.7, 0.9, 0.4]
- num_labels = 3
- batch_shape = [30, num_labels]
- logits = tf.Variable(tf.random_normal(batch_shape))
- targets = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.4)))
- label_priors = tf.constant(0.45, shape=[num_labels])
-
- multi_label_loss, _ = (
- loss_layers.true_positive_rate_at_false_positive_rate_loss(
- targets, logits, target_precision, label_priors=label_priors))
-
- single_label_losses = [
- loss_layers.true_positive_rate_at_false_positive_rate_loss(
- tf.expand_dims(targets[:, i], -1),
- tf.expand_dims(logits[:, i], -1),
- target_precision[i],
- label_priors=label_priors[i])[0]
- for i in range(num_labels)
- ]
-
- single_label_losses = tf.concat(single_label_losses, 1)
-
- with self.test_session() as session:
- tf.global_variables_initializer().run()
- multi_label_loss_val, single_label_loss_val = session.run(
- [multi_label_loss, single_label_losses])
- self.assertAllClose(multi_label_loss_val, single_label_loss_val)
-
-
-class UtilityFunctionsTest(tf.test.TestCase):
-
- def testTrainableDualVariable(self):
- # Confirm correct behavior of a trainable dual variable.
- x = tf.get_variable('primal', dtype=tf.float32, initializer=2.0)
- y_value, y = loss_layers._create_dual_variable(
- 'dual', shape=None, dtype=tf.float32, initializer=1.0, collections=None,
- trainable=True, dual_rate_factor=0.3)
- optimizer = tf.train.GradientDescentOptimizer(learning_rate=1.0)
- update = optimizer.minimize(0.5 * tf.square(x - y_value))
-
- with self.test_session():
- tf.global_variables_initializer().run()
- update.run()
- self.assertAllClose(0.7, y.eval())
-
- def testUntrainableDualVariable(self):
- # Confirm correct behavior of dual variable which is not trainable.
- x = tf.get_variable('primal', dtype=tf.float32, initializer=-2.0)
- y_value, y = loss_layers._create_dual_variable(
- 'dual', shape=None, dtype=tf.float32, initializer=1.0, collections=None,
- trainable=False, dual_rate_factor=0.8)
- optimizer = tf.train.GradientDescentOptimizer(learning_rate=1.0)
- update = optimizer.minimize(tf.square(x) * y_value + tf.exp(y_value))
-
- with self.test_session():
- tf.global_variables_initializer().run()
- update.run()
- self.assertAllClose(1.0, y.eval())
-
-
-class BoundTest(parameterized.TestCase, tf.test.TestCase):
-
- @parameterized.named_parameters(
- ('_xent', 'xent', 1.0, [2.0, 1.0]),
- ('_xent_weighted', 'xent',
- numpy.array([0, 2, 0.5, 1, 2, 3]).reshape(6, 1), [2.5, 0]),
- ('_hinge', 'hinge', 1.0, [2.0, 1.0]),
- ('_hinge_weighted', 'hinge',
- numpy.array([1.0, 2, 3, 4, 5, 6]).reshape(6, 1), [5.0, 1]))
- def testLowerBoundMultilabel(self, surrogate_type, weights, expected):
- labels, logits, _ = _multilabel_data()
- lower_bound = loss_layers.true_positives_lower_bound(
- labels, logits, weights, surrogate_type)
-
- with self.test_session():
- self.assertAllClose(lower_bound.eval(), expected)
-
- @parameterized.named_parameters(
- ('_xent', 'xent'), ('_hinge', 'hinge'))
- def testLowerBoundOtherMultilabel(self, surrogate_type):
- labels, logits, _ = _other_multilabel_data(surrogate_type)()
- lower_bound = loss_layers.true_positives_lower_bound(
- labels, logits, 1.0, surrogate_type)
-
- with self.test_session():
- self.assertAllClose(lower_bound.eval(), [4.0, 2.0], atol=1e-5)
-
- @parameterized.named_parameters(
- ('_xent', 'xent', 1.0, [1.0, 2.0]),
- ('_xent_weighted', 'xent',
- numpy.array([3.0, 2, 1, 0, 1, 2]).reshape(6, 1), [2.0, 1.0]),
- ('_hinge', 'hinge', 1.0, [1.0, 2.0]),
- ('_hinge_weighted', 'hinge',
- numpy.array([13, 12, 11, 0.5, 0, 0.5]).reshape(6, 1), [0.5, 0.5]))
- def testUpperBoundMultilabel(self, surrogate_type, weights, expected):
- labels, logits, _ = _multilabel_data()
- upper_bound = loss_layers.false_positives_upper_bound(
- labels, logits, weights, surrogate_type)
-
- with self.test_session():
- self.assertAllClose(upper_bound.eval(), expected)
-
- @parameterized.named_parameters(
- ('_xent', 'xent'), ('_hinge', 'hinge'))
- def testUpperBoundOtherMultilabel(self, surrogate_type):
- labels, logits, _ = _other_multilabel_data(surrogate_type)()
- upper_bound = loss_layers.false_positives_upper_bound(
- labels, logits, 1.0, surrogate_type)
-
- with self.test_session():
- self.assertAllClose(upper_bound.eval(), [2.0, 4.0], atol=1e-5)
-
- @parameterized.named_parameters(
- ('_lower', 'lower'), ('_upper', 'upper'))
- def testThreeDimensionalLogits(self, bound):
- bound_function = loss_layers.false_positives_upper_bound
- if bound == 'lower':
- bound_function = loss_layers.true_positives_lower_bound
- random_labels = numpy.float32(numpy.random.uniform(size=[2, 3]) > 0.5)
- random_logits = numpy.float32(numpy.random.randn(2, 3, 2))
- first_slice_logits = random_logits[:, :, 0].reshape(2, 3)
- second_slice_logits = random_logits[:, :, 1].reshape(2, 3)
-
- full_bound = bound_function(
- tf.constant(random_labels), tf.constant(random_logits), 1.0, 'xent')
- first_slice_bound = bound_function(tf.constant(random_labels),
- tf.constant(first_slice_logits),
- 1.0,
- 'xent')
- second_slice_bound = bound_function(tf.constant(random_labels),
- tf.constant(second_slice_logits),
- 1.0,
- 'xent')
- stacked_bound = tf.stack([first_slice_bound, second_slice_bound], axis=1)
-
- with self.test_session():
- self.assertAllClose(full_bound.eval(), stacked_bound.eval())
-
-
-def run_lagrange_multiplier_test(global_objective,
- objective_kwargs,
- data_builder,
- test_object):
- """Runs a test for the Lagrange multiplier update of `global_objective`.
-
- The test checks that the constraint for `global_objective` is satisfied on
- the first label of the data produced by `data_builder` but not the second.
-
- Args:
- global_objective: One of the global objectives.
- objective_kwargs: A dictionary of keyword arguments to pass to
- `global_objective`. Must contain an entry for the constraint argument
- of `global_objective`, e.g. 'target_rate' or 'target_precision'.
- data_builder: A function which returns tensors corresponding to labels,
- logits, and label priors.
- test_object: An instance of tf.test.TestCase.
- """
- # Construct global objective kwargs from a copy of `objective_kwargs`.
- kwargs = dict(objective_kwargs)
- targets, logits, priors = data_builder()
- kwargs['labels'] = targets
- kwargs['logits'] = logits
- kwargs['label_priors'] = priors
-
- loss, output_dict = global_objective(**kwargs)
- lambdas = tf.squeeze(output_dict['lambdas'])
- opt = tf.train.GradientDescentOptimizer(learning_rate=0.1)
- update_op = opt.minimize(loss, var_list=[output_dict['lambdas']])
-
- with test_object.test_session() as session:
- tf.global_variables_initializer().run()
- lambdas_before = session.run(lambdas)
- session.run(update_op)
- lambdas_after = session.run(lambdas)
- test_object.assertLess(lambdas_after[0], lambdas_before[0])
- test_object.assertGreater(lambdas_after[1], lambdas_before[1])
-
-
-class CrossFunctionTest(parameterized.TestCase, tf.test.TestCase):
-
- @parameterized.named_parameters(
- ('_auc01xent', loss_layers.precision_recall_auc_loss, {
- 'precision_range': (0.0, 1.0), 'surrogate_type': 'xent'
- }),
- ('_auc051xent', loss_layers.precision_recall_auc_loss, {
- 'precision_range': (0.5, 1.0), 'surrogate_type': 'xent'
- }),
- ('_auc01)hinge', loss_layers.precision_recall_auc_loss, {
- 'precision_range': (0.0, 1.0), 'surrogate_type': 'hinge'
- }),
- ('_ratp04', loss_layers.recall_at_precision_loss, {
- 'target_precision': 0.4, 'surrogate_type': 'xent'
- }),
- ('_ratp066', loss_layers.recall_at_precision_loss, {
- 'target_precision': 0.66, 'surrogate_type': 'xent'
- }),
- ('_ratp07_hinge', loss_layers.recall_at_precision_loss, {
- 'target_precision': 0.7, 'surrogate_type': 'hinge'
- }),
- ('_fpattp066', loss_layers.false_positive_rate_at_true_positive_rate_loss,
- {'target_rate': 0.66, 'surrogate_type': 'xent'}),
- ('_fpattp046', loss_layers.false_positive_rate_at_true_positive_rate_loss,
- {
- 'target_rate': 0.46, 'surrogate_type': 'xent'
- }),
- ('_fpattp076_hinge',
- loss_layers.false_positive_rate_at_true_positive_rate_loss, {
- 'target_rate': 0.76, 'surrogate_type': 'hinge'
- }),
- ('_fpattp036_hinge',
- loss_layers.false_positive_rate_at_true_positive_rate_loss, {
- 'target_rate': 0.36, 'surrogate_type': 'hinge'
- }),
- )
- def testWeigtedGlobalObjective(self,
- global_objective,
- objective_kwargs):
- """Runs a test of `global_objective` with per-example weights.
-
- Args:
- global_objective: One of the global objectives.
- objective_kwargs: A dictionary of keyword arguments to pass to
- `global_objective`. Must contain keys 'surrogate_type', and the keyword
- for the constraint argument of `global_objective`, e.g. 'target_rate' or
- 'target_precision'.
- """
- logits_positives = tf.constant([1, -0.5, 3], shape=[3, 1])
- logits_negatives = tf.constant([-0.5, 1, -1, -1, -0.5, 1], shape=[6, 1])
-
- # Dummy tensor is used to compute the gradients.
- dummy = tf.constant(1.0)
- logits = tf.concat([logits_positives, logits_negatives], 0)
- logits = tf.multiply(logits, dummy)
- targets = tf.constant([1, 1, 1, 0, 0, 0, 0, 0, 0],
- shape=[9, 1], dtype=tf.float32)
- priors = tf.constant(1.0/3.0, shape=[1])
- weights = tf.constant([1, 1, 1, 0, 0, 0, 2, 2, 2],
- shape=[9, 1], dtype=tf.float32)
-
- # Construct global objective kwargs.
- objective_kwargs['labels'] = targets
- objective_kwargs['logits'] = logits
- objective_kwargs['label_priors'] = priors
-
- scope = 'weighted_test'
- # Unweighted loss.
- objective_kwargs['scope'] = scope + '_plain'
- raw_loss, update = global_objective(**objective_kwargs)
- loss = tf.reduce_sum(raw_loss)
-
- # Weighted loss.
- objective_kwargs['weights'] = weights
- objective_kwargs['scope'] = scope + '_weighted'
- raw_weighted_loss, weighted_update = global_objective(**objective_kwargs)
- weighted_loss = tf.reduce_sum(raw_weighted_loss)
-
- lambdas = tf.contrib.framework.get_unique_variable(scope + '_plain/lambdas')
- weighted_lambdas = tf.contrib.framework.get_unique_variable(
- scope + '_weighted/lambdas')
- logits_gradient = tf.gradients(loss, dummy)
- weighted_logits_gradient = tf.gradients(weighted_loss, dummy)
-
- with self.test_session() as session:
- tf.global_variables_initializer().run()
- self.assertAllClose(loss.eval(), weighted_loss.eval())
-
- logits_grad, weighted_logits_grad = session.run(
- [logits_gradient, weighted_logits_gradient])
- self.assertAllClose(logits_grad, weighted_logits_grad)
-
- session.run([update, weighted_update])
- lambdas_value, weighted_lambdas_value = session.run(
- [lambdas, weighted_lambdas])
- self.assertAllClose(lambdas_value, weighted_lambdas_value)
-
- @parameterized.named_parameters(
- ('_prauc051xent', loss_layers.precision_recall_auc_loss, {
- 'precision_range': (0.5, 1.0), 'surrogate_type': 'xent'
- }),
- ('_prauc01hinge', loss_layers.precision_recall_auc_loss, {
- 'precision_range': (0.0, 1.0), 'surrogate_type': 'hinge'
- }),
- ('_rocxent', loss_layers.roc_auc_loss, {'surrogate_type': 'xent'}),
- ('_rochinge', loss_layers.roc_auc_loss, {'surrogate_type': 'xent'}),
- ('_ratp04', loss_layers.recall_at_precision_loss, {
- 'target_precision': 0.4, 'surrogate_type': 'xent'
- }),
- ('_ratp07_hinge', loss_layers.recall_at_precision_loss, {
- 'target_precision': 0.7, 'surrogate_type': 'hinge'
- }),
- ('_patr05', loss_layers.precision_at_recall_loss, {
- 'target_recall': 0.4, 'surrogate_type': 'xent'
- }),
- ('_patr08_hinge', loss_layers.precision_at_recall_loss, {
- 'target_recall': 0.7, 'surrogate_type': 'hinge'
- }),
- ('_fpattp046', loss_layers.false_positive_rate_at_true_positive_rate_loss,
- {
- 'target_rate': 0.46, 'surrogate_type': 'xent'
- }),
- ('_fpattp036_hinge',
- loss_layers.false_positive_rate_at_true_positive_rate_loss, {
- 'target_rate': 0.36, 'surrogate_type': 'hinge'
- }),
- ('_tpatfp076', loss_layers.true_positive_rate_at_false_positive_rate_loss,
- {
- 'target_rate': 0.76, 'surrogate_type': 'xent'
- }),
- ('_tpatfp036_hinge',
- loss_layers.true_positive_rate_at_false_positive_rate_loss, {
- 'target_rate': 0.36, 'surrogate_type': 'hinge'
- }),
- )
- def testVectorAndMatrixLabelEquivalence(self,
- global_objective,
- objective_kwargs):
- """Tests equivalence between label shape [batch_size] or [batch_size, 1]."""
- vector_labels = tf.constant([1.0, 1.0, 0.0, 0.0], shape=[4])
- vector_logits = tf.constant([1.0, 0.1, 0.1, -1.0], shape=[4])
-
- # Construct vector global objective kwargs and loss.
- vector_kwargs = objective_kwargs.copy()
- vector_kwargs['labels'] = vector_labels
- vector_kwargs['logits'] = vector_logits
- vector_loss, _ = global_objective(**vector_kwargs)
- vector_loss_sum = tf.reduce_sum(vector_loss)
-
- # Construct matrix global objective kwargs and loss.
- matrix_kwargs = objective_kwargs.copy()
- matrix_kwargs['labels'] = tf.expand_dims(vector_labels, 1)
- matrix_kwargs['logits'] = tf.expand_dims(vector_logits, 1)
- matrix_loss, _ = global_objective(**matrix_kwargs)
- matrix_loss_sum = tf.reduce_sum(matrix_loss)
-
- self.assertEqual(1, vector_loss.get_shape().ndims)
- self.assertEqual(2, matrix_loss.get_shape().ndims)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- self.assertAllClose(vector_loss_sum.eval(), matrix_loss_sum.eval())
-
- @parameterized.named_parameters(
- ('_prauc', loss_layers.precision_recall_auc_loss, None),
- ('_roc', loss_layers.roc_auc_loss, None),
- ('_rap', loss_layers.recall_at_precision_loss, {'target_precision': 0.8}),
- ('_patr', loss_layers.precision_at_recall_loss, {'target_recall': 0.7}),
- ('_fpattp', loss_layers.false_positive_rate_at_true_positive_rate_loss,
- {'target_rate': 0.9}),
- ('_tpatfp', loss_layers.true_positive_rate_at_false_positive_rate_loss,
- {'target_rate': 0.1})
- )
- def testUnknownBatchSize(self, global_objective, objective_kwargs):
- # Tests that there are no errors when the batch size is not known.
- batch_shape = [5, 2]
- logits = tf.placeholder(tf.float32)
- logits_feed = numpy.random.randn(*batch_shape)
- labels = tf.placeholder(tf.float32)
- labels_feed = logits_feed > 0.1
- logits.set_shape([None, 2])
- labels.set_shape([None, 2])
-
- if objective_kwargs is None:
- objective_kwargs = {}
-
- placeholder_kwargs = objective_kwargs.copy()
- placeholder_kwargs['labels'] = labels
- placeholder_kwargs['logits'] = logits
- placeholder_loss, _ = global_objective(**placeholder_kwargs)
-
- kwargs = objective_kwargs.copy()
- kwargs['labels'] = labels_feed
- kwargs['logits'] = logits_feed
- loss, _ = global_objective(**kwargs)
-
- with self.test_session() as session:
- tf.global_variables_initializer().run()
- feed_loss_val = session.run(placeholder_loss,
- feed_dict={logits: logits_feed,
- labels: labels_feed})
- loss_val = session.run(loss)
- self.assertAllClose(feed_loss_val, loss_val)
-
-
-# Both sets of logits below are designed so that the surrogate precision and
-# recall (true positive rate) of class 1 is ~ 2/3, and the same surrogates for
-# class 2 are ~ 1/3. The false positive rate surrogates are ~ 1/3 and 2/3.
-def _multilabel_data():
- targets = tf.constant([1.0, 1.0, 1.0, 0.0, 0.0, 0.0], shape=[6, 1])
- targets = tf.concat([targets, targets], 1)
- logits_positives = tf.constant([[0.0, 15],
- [16, 0.0],
- [14, 0.0]], shape=[3, 2])
- logits_negatives = tf.constant([[-17, 0.0],
- [-15, 0.0],
- [0.0, -101]], shape=[3, 2])
- logits = tf.concat([logits_positives, logits_negatives], 0)
- priors = tf.constant(0.5, shape=[2])
-
- return targets, logits, priors
-
-
-def _other_multilabel_data(surrogate_type):
- targets = tf.constant(
- [1.0] * 6 + [0.0] * 6, shape=[12, 1])
- targets = tf.concat([targets, targets], 1)
- logits_positives = tf.constant([[0.0, 13],
- [12, 0.0],
- [15, 0.0],
- [0.0, 30],
- [13, 0.0],
- [18, 0.0]], shape=[6, 2])
- # A score of cost_2 incurs a loss of ~2.0.
- cost_2 = 1.0 if surrogate_type == 'hinge' else 1.09861229
- logits_negatives = tf.constant([[-16, cost_2],
- [-15, cost_2],
- [cost_2, -111],
- [-133, -14,],
- [-14.0100101, -16,],
- [-19.888828882, -101]], shape=[6, 2])
- logits = tf.concat([logits_positives, logits_negatives], 0)
- priors = tf.constant(0.5, shape=[2])
-
- def builder():
- return targets, logits, priors
-
- return builder
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/global_objectives/test_all.py b/research/global_objectives/test_all.py
deleted file mode 100644
index d7e439e219840a9ec5c65382c6bc392b1d68b447..0000000000000000000000000000000000000000
--- a/research/global_objectives/test_all.py
+++ /dev/null
@@ -1,37 +0,0 @@
-# Copyright 2018 The TensorFlow Global Objectives Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Runs all unit tests in the Global Objectives package.
-
-Requires that TensorFlow and abseil (https://github.com/abseil/abseil-py) be
-installed on your machine. Command to run the tests:
-python test_all.py
-
-"""
-
-import os
-import sys
-import unittest
-
-this_file = os.path.realpath(__file__)
-start_dir = os.path.dirname(this_file)
-parent_dir = os.path.dirname(start_dir)
-
-sys.path.append(parent_dir)
-loader = unittest.TestLoader()
-suite = loader.discover(start_dir, pattern='*_test.py')
-
-runner = unittest.TextTestRunner(verbosity=2)
-runner.run(suite)
diff --git a/research/global_objectives/util.py b/research/global_objectives/util.py
deleted file mode 100644
index e2b287a90bd743e5466b875c933c3872868f4a5f..0000000000000000000000000000000000000000
--- a/research/global_objectives/util.py
+++ /dev/null
@@ -1,348 +0,0 @@
-# Copyright 2018 The TensorFlow Global Objectives Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Contains utility functions for the global objectives library."""
-
-# Dependency imports
-import tensorflow as tf
-
-
-def weighted_sigmoid_cross_entropy_with_logits(labels,
- logits,
- positive_weights=1.0,
- negative_weights=1.0,
- name=None):
- """Computes a weighting of sigmoid cross entropy given `logits`.
-
- Measures the weighted probability error in discrete classification tasks in
- which classes are independent and not mutually exclusive. For instance, one
- could perform multilabel classification where a picture can contain both an
- elephant and a dog at the same time. The class weight multiplies the
- different types of errors.
- For brevity, let `x = logits`, `z = labels`, `c = positive_weights`,
- `d = negative_weights` The
- weighed logistic loss is
-
- ```
- c * z * -log(sigmoid(x)) + d * (1 - z) * -log(1 - sigmoid(x))
- = c * z * -log(1 / (1 + exp(-x))) - d * (1 - z) * log(exp(-x) / (1 + exp(-x)))
- = c * z * log(1 + exp(-x)) + d * (1 - z) * (-log(exp(-x)) + log(1 + exp(-x)))
- = c * z * log(1 + exp(-x)) + d * (1 - z) * (x + log(1 + exp(-x)))
- = (1 - z) * x * d + (1 - z + c * z ) * log(1 + exp(-x))
- = - d * x * z + d * x + (d - d * z + c * z ) * log(1 + exp(-x))
- ```
-
- To ensure stability and avoid overflow, the implementation uses the identity
- log(1 + exp(-x)) = max(0,-x) + log(1 + exp(-abs(x)))
- and the result is computed as
-
- ```
- = -d * x * z + d * x
- + (d - d * z + c * z ) * (max(0,-x) + log(1 + exp(-abs(x))))
- ```
-
- Note that the loss is NOT an upper bound on the 0-1 loss, unless it is divided
- by log(2).
-
- Args:
- labels: A `Tensor` of type `float32` or `float64`. `labels` can be a 2D
- tensor with shape [batch_size, num_labels] or a 3D tensor with shape
- [batch_size, num_labels, K].
- logits: A `Tensor` of the same type and shape as `labels`. If `logits` has
- shape [batch_size, num_labels, K], the loss is computed separately on each
- slice [:, :, k] of `logits`.
- positive_weights: A `Tensor` that holds positive weights and has the
- following semantics according to its shape:
- scalar - A global positive weight.
- 1D tensor - must be of size K, a weight for each 'attempt'
- 2D tensor - of size [num_labels, K'] where K' is either K or 1.
- The `positive_weights` will be expanded to the left to match the
- dimensions of logits and labels.
- negative_weights: A `Tensor` that holds positive weight and has the
- semantics identical to positive_weights.
- name: A name for the operation (optional).
-
- Returns:
- A `Tensor` of the same shape as `logits` with the componentwise
- weighted logistic losses.
- """
- with tf.name_scope(
- name,
- 'weighted_logistic_loss',
- [logits, labels, positive_weights, negative_weights]) as name:
- labels, logits, positive_weights, negative_weights = prepare_loss_args(
- labels, logits, positive_weights, negative_weights)
-
- softplus_term = tf.add(tf.maximum(-logits, 0.0),
- tf.log(1.0 + tf.exp(-tf.abs(logits))))
- weight_dependent_factor = (
- negative_weights + (positive_weights - negative_weights) * labels)
- return (negative_weights * (logits - labels * logits) +
- weight_dependent_factor * softplus_term)
-
-
-def weighted_hinge_loss(labels,
- logits,
- positive_weights=1.0,
- negative_weights=1.0,
- name=None):
- """Computes weighted hinge loss given logits `logits`.
-
- The loss applies to multi-label classification tasks where labels are
- independent and not mutually exclusive. See also
- `weighted_sigmoid_cross_entropy_with_logits`.
-
- Args:
- labels: A `Tensor` of type `float32` or `float64`. Each entry must be
- either 0 or 1. `labels` can be a 2D tensor with shape
- [batch_size, num_labels] or a 3D tensor with shape
- [batch_size, num_labels, K].
- logits: A `Tensor` of the same type and shape as `labels`. If `logits` has
- shape [batch_size, num_labels, K], the loss is computed separately on each
- slice [:, :, k] of `logits`.
- positive_weights: A `Tensor` that holds positive weights and has the
- following semantics according to its shape:
- scalar - A global positive weight.
- 1D tensor - must be of size K, a weight for each 'attempt'
- 2D tensor - of size [num_labels, K'] where K' is either K or 1.
- The `positive_weights` will be expanded to the left to match the
- dimensions of logits and labels.
- negative_weights: A `Tensor` that holds positive weight and has the
- semantics identical to positive_weights.
- name: A name for the operation (optional).
-
- Returns:
- A `Tensor` of the same shape as `logits` with the componentwise
- weighted hinge loss.
- """
- with tf.name_scope(
- name, 'weighted_hinge_loss',
- [logits, labels, positive_weights, negative_weights]) as name:
- labels, logits, positive_weights, negative_weights = prepare_loss_args(
- labels, logits, positive_weights, negative_weights)
-
- positives_term = positive_weights * labels * tf.maximum(1.0 - logits, 0)
- negatives_term = (negative_weights * (1.0 - labels)
- * tf.maximum(1.0 + logits, 0))
- return positives_term + negatives_term
-
-
-def weighted_surrogate_loss(labels,
- logits,
- surrogate_type='xent',
- positive_weights=1.0,
- negative_weights=1.0,
- name=None):
- """Returns either weighted cross-entropy or hinge loss.
-
- For example `surrogate_type` is 'xent' returns the weighted cross
- entropy loss.
-
- Args:
- labels: A `Tensor` of type `float32` or `float64`. Each entry must be
- between 0 and 1. `labels` can be a 2D tensor with shape
- [batch_size, num_labels] or a 3D tensor with shape
- [batch_size, num_labels, K].
- logits: A `Tensor` of the same type and shape as `labels`. If `logits` has
- shape [batch_size, num_labels, K], each slice [:, :, k] represents an
- 'attempt' to predict `labels` and the loss is computed per slice.
- surrogate_type: A string that determines which loss to return, supports
- 'xent' for cross-entropy and 'hinge' for hinge loss.
- positive_weights: A `Tensor` that holds positive weights and has the
- following semantics according to its shape:
- scalar - A global positive weight.
- 1D tensor - must be of size K, a weight for each 'attempt'
- 2D tensor - of size [num_labels, K'] where K' is either K or 1.
- The `positive_weights` will be expanded to the left to match the
- dimensions of logits and labels.
- negative_weights: A `Tensor` that holds positive weight and has the
- semantics identical to positive_weights.
- name: A name for the operation (optional).
-
- Returns:
- The weigthed loss.
-
- Raises:
- ValueError: If value of `surrogate_type` is not supported.
- """
- with tf.name_scope(
- name, 'weighted_loss',
- [logits, labels, surrogate_type, positive_weights,
- negative_weights]) as name:
- if surrogate_type == 'xent':
- return weighted_sigmoid_cross_entropy_with_logits(
- logits=logits,
- labels=labels,
- positive_weights=positive_weights,
- negative_weights=negative_weights,
- name=name)
- elif surrogate_type == 'hinge':
- return weighted_hinge_loss(
- logits=logits,
- labels=labels,
- positive_weights=positive_weights,
- negative_weights=negative_weights,
- name=name)
- raise ValueError('surrogate_type %s not supported.' % surrogate_type)
-
-
-def expand_outer(tensor, rank):
- """Expands the given `Tensor` outwards to a target rank.
-
- For example if rank = 3 and tensor.shape is [3, 4], this function will expand
- to such that the resulting shape will be [1, 3, 4].
-
- Args:
- tensor: The tensor to expand.
- rank: The target dimension.
-
- Returns:
- The expanded tensor.
-
- Raises:
- ValueError: If rank of `tensor` is unknown, or if `rank` is smaller than
- the rank of `tensor`.
- """
- if tensor.get_shape().ndims is None:
- raise ValueError('tensor dimension must be known.')
- if len(tensor.get_shape()) > rank:
- raise ValueError(
- '`rank` must be at least the current tensor dimension: (%s vs %s).' %
- (rank, len(tensor.get_shape())))
- while len(tensor.get_shape()) < rank:
- tensor = tf.expand_dims(tensor, 0)
- return tensor
-
-
-def build_label_priors(labels,
- weights=None,
- positive_pseudocount=1.0,
- negative_pseudocount=1.0,
- variables_collections=None):
- """Creates an op to maintain and update label prior probabilities.
-
- For each label, the label priors are estimated as
- (P + sum_i w_i y_i) / (P + N + sum_i w_i),
- where y_i is the ith label, w_i is the ith weight, P is a pseudo-count of
- positive labels, and N is a pseudo-count of negative labels. The index i
- ranges over all labels observed during all evaluations of the returned op.
-
- Args:
- labels: A `Tensor` with shape [batch_size, num_labels]. Entries should be
- in [0, 1].
- weights: Coefficients representing the weight of each label. Must be either
- a Tensor of shape [batch_size, num_labels] or `None`, in which case each
- weight is treated as 1.0.
- positive_pseudocount: Number of positive labels used to initialize the label
- priors.
- negative_pseudocount: Number of negative labels used to initialize the label
- priors.
- variables_collections: Optional list of collections for created variables.
-
- Returns:
- label_priors: An op to update the weighted label_priors. Gives the
- current value of the label priors when evaluated.
- """
- dtype = labels.dtype.base_dtype
- num_labels = get_num_labels(labels)
-
- if weights is None:
- weights = tf.ones_like(labels)
-
- # We disable partitioning while constructing dual variables because they will
- # be updated with assign, which is not available for partitioned variables.
- partitioner = tf.get_variable_scope().partitioner
- try:
- tf.get_variable_scope().set_partitioner(None)
- # Create variable and update op for weighted label counts.
- weighted_label_counts = tf.contrib.framework.model_variable(
- name='weighted_label_counts',
- shape=[num_labels],
- dtype=dtype,
- initializer=tf.constant_initializer(
- [positive_pseudocount] * num_labels, dtype=dtype),
- collections=variables_collections,
- trainable=False)
- weighted_label_counts_update = weighted_label_counts.assign_add(
- tf.reduce_sum(weights * labels, 0))
-
- # Create variable and update op for the sum of the weights.
- weight_sum = tf.contrib.framework.model_variable(
- name='weight_sum',
- shape=[num_labels],
- dtype=dtype,
- initializer=tf.constant_initializer(
- [positive_pseudocount + negative_pseudocount] * num_labels,
- dtype=dtype),
- collections=variables_collections,
- trainable=False)
- weight_sum_update = weight_sum.assign_add(tf.reduce_sum(weights, 0))
-
- finally:
- tf.get_variable_scope().set_partitioner(partitioner)
-
- label_priors = tf.div(
- weighted_label_counts_update,
- weight_sum_update)
- return label_priors
-
-
-def convert_and_cast(value, name, dtype):
- """Convert input to tensor and cast to dtype.
-
- Args:
- value: An object whose type has a registered Tensor conversion function,
- e.g. python numerical type or numpy array.
- name: Name to use for the new Tensor, if one is created.
- dtype: Optional element type for the returned tensor.
-
- Returns:
- A tensor.
- """
- return tf.cast(tf.convert_to_tensor(value, name=name), dtype=dtype)
-
-
-def prepare_loss_args(labels, logits, positive_weights, negative_weights):
- """Prepare arguments for weighted loss functions.
-
- If needed, will convert given arguments to appropriate type and shape.
-
- Args:
- labels: labels or labels of the loss function.
- logits: Logits of the loss function.
- positive_weights: Weight on the positive examples.
- negative_weights: Weight on the negative examples.
-
- Returns:
- Converted labels, logits, positive_weights, negative_weights.
- """
- logits = tf.convert_to_tensor(logits, name='logits')
- labels = convert_and_cast(labels, 'labels', logits.dtype)
- if len(labels.get_shape()) == 2 and len(logits.get_shape()) == 3:
- labels = tf.expand_dims(labels, [2])
-
- positive_weights = convert_and_cast(positive_weights, 'positive_weights',
- logits.dtype)
- positive_weights = expand_outer(positive_weights, logits.get_shape().ndims)
- negative_weights = convert_and_cast(negative_weights, 'negative_weights',
- logits.dtype)
- negative_weights = expand_outer(negative_weights, logits.get_shape().ndims)
- return labels, logits, positive_weights, negative_weights
-
-
-def get_num_labels(labels_or_logits):
- """Returns the number of labels inferred from labels_or_logits."""
- if labels_or_logits.get_shape().ndims <= 1:
- return 1
- return labels_or_logits.get_shape()[1].value
diff --git a/research/global_objectives/util_test.py b/research/global_objectives/util_test.py
deleted file mode 100644
index 195252a53eb1d0a50735d2f987b0882681b0544a..0000000000000000000000000000000000000000
--- a/research/global_objectives/util_test.py
+++ /dev/null
@@ -1,333 +0,0 @@
-# Copyright 2018 The TensorFlow Global Objectives Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tests for global objectives util functions."""
-
-# Dependency imports
-from absl.testing import parameterized
-import numpy as np
-import tensorflow as tf
-
-from global_objectives import util
-
-
-def weighted_sigmoid_cross_entropy(targets, logits, weight):
- return (weight * targets * np.log(1.0 + np.exp(-logits)) + (
- (1.0 - targets) * np.log(1.0 + 1.0 / np.exp(-logits))))
-
-
-def hinge_loss(labels, logits):
- # Mostly copied from tensorflow.python.ops.losses but with loss per datapoint.
- labels = tf.to_float(labels)
- all_ones = tf.ones_like(labels)
- labels = tf.subtract(2 * labels, all_ones)
- return tf.nn.relu(tf.subtract(all_ones, tf.multiply(labels, logits)))
-
-
-class WeightedSigmoidCrossEntropyTest(parameterized.TestCase, tf.test.TestCase):
-
- def testTrivialCompatibilityWithSigmoidCrossEntropy(self):
- """Tests compatibility with unweighted function with weight 1.0."""
- x_shape = [300, 10]
- targets = np.random.random_sample(x_shape).astype(np.float32)
- logits = np.random.randn(*x_shape).astype(np.float32)
- weighted_loss = util.weighted_sigmoid_cross_entropy_with_logits(
- targets,
- logits)
- expected_loss = (
- tf.contrib.nn.deprecated_flipped_sigmoid_cross_entropy_with_logits(
- logits, targets))
- with self.test_session():
- self.assertAllClose(expected_loss.eval(),
- weighted_loss.eval(),
- atol=0.000001)
-
- def testNonTrivialCompatibilityWithSigmoidCrossEntropy(self):
- """Tests use of an arbitrary weight (4.12)."""
- x_shape = [300, 10]
- targets = np.random.random_sample(x_shape).astype(np.float32)
- logits = np.random.randn(*x_shape).astype(np.float32)
- weight = 4.12
- weighted_loss = util.weighted_sigmoid_cross_entropy_with_logits(
- targets,
- logits,
- weight,
- weight)
- expected_loss = (
- weight *
- tf.contrib.nn.deprecated_flipped_sigmoid_cross_entropy_with_logits(
- logits, targets))
- with self.test_session():
- self.assertAllClose(expected_loss.eval(),
- weighted_loss.eval(),
- atol=0.000001)
-
- def testDifferentSizeWeightedSigmoidCrossEntropy(self):
- """Tests correctness on 3D tensors.
-
- Tests that the function works as expected when logits is a 3D tensor and
- targets is a 2D tensor.
- """
- targets_shape = [30, 4]
- logits_shape = [targets_shape[0], targets_shape[1], 3]
- targets = np.random.random_sample(targets_shape).astype(np.float32)
- logits = np.random.randn(*logits_shape).astype(np.float32)
-
- weight_vector = [2.0, 3.0, 13.0]
- loss = util.weighted_sigmoid_cross_entropy_with_logits(targets,
- logits,
- weight_vector)
-
- with self.test_session():
- loss = loss.eval()
- for i in range(0, len(weight_vector)):
- expected = weighted_sigmoid_cross_entropy(targets, logits[:, :, i],
- weight_vector[i])
- self.assertAllClose(loss[:, :, i], expected, atol=0.000001)
-
- @parameterized.parameters((300, 10, 0.3), (20, 4, 2.0), (30, 4, 3.9))
- def testWeightedSigmoidCrossEntropy(self, batch_size, num_labels, weight):
- """Tests thats the tf and numpy functions agree on many instances."""
- x_shape = [batch_size, num_labels]
- targets = np.random.random_sample(x_shape).astype(np.float32)
- logits = np.random.randn(*x_shape).astype(np.float32)
-
- with self.test_session():
- loss = util.weighted_sigmoid_cross_entropy_with_logits(
- targets,
- logits,
- weight,
- 1.0,
- name='weighted-loss')
- expected = weighted_sigmoid_cross_entropy(targets, logits, weight)
- self.assertAllClose(expected, loss.eval(), atol=0.000001)
-
- def testGradients(self):
- """Tests that weighted loss gradients behave as expected."""
- dummy_tensor = tf.constant(1.0)
-
- positives_shape = [10, 1]
- positives_logits = dummy_tensor * tf.Variable(
- tf.random_normal(positives_shape) + 1.0)
- positives_targets = tf.ones(positives_shape)
- positives_weight = 4.6
- positives_loss = (
- tf.contrib.nn.deprecated_flipped_sigmoid_cross_entropy_with_logits(
- positives_logits, positives_targets) * positives_weight)
-
- negatives_shape = [190, 1]
- negatives_logits = dummy_tensor * tf.Variable(
- tf.random_normal(negatives_shape))
- negatives_targets = tf.zeros(negatives_shape)
- negatives_weight = 0.9
- negatives_loss = (
- tf.contrib.nn.deprecated_flipped_sigmoid_cross_entropy_with_logits(
- negatives_logits, negatives_targets) * negatives_weight)
-
- all_logits = tf.concat([positives_logits, negatives_logits], 0)
- all_targets = tf.concat([positives_targets, negatives_targets], 0)
- weighted_loss = tf.reduce_sum(
- util.weighted_sigmoid_cross_entropy_with_logits(
- all_targets, all_logits, positives_weight, negatives_weight))
- weighted_gradients = tf.gradients(weighted_loss, dummy_tensor)
-
- expected_loss = tf.add(
- tf.reduce_sum(positives_loss),
- tf.reduce_sum(negatives_loss))
- expected_gradients = tf.gradients(expected_loss, dummy_tensor)
-
- with tf.Session() as session:
- tf.global_variables_initializer().run()
- grad, expected_grad = session.run(
- [weighted_gradients, expected_gradients])
- self.assertAllClose(grad, expected_grad)
-
- def testDtypeFlexibility(self):
- """Tests the loss on inputs of varying data types."""
- shape = [20, 3]
- logits = np.random.randn(*shape)
- targets = tf.truncated_normal(shape)
- positive_weights = tf.constant(3, dtype=tf.int64)
- negative_weights = 1
-
- loss = util.weighted_sigmoid_cross_entropy_with_logits(
- targets, logits, positive_weights, negative_weights)
-
- with self.test_session():
- self.assertEqual(loss.eval().dtype, np.float)
-
-
-class WeightedHingeLossTest(tf.test.TestCase):
-
- def testTrivialCompatibilityWithHinge(self):
- # Tests compatibility with unweighted hinge loss.
- x_shape = [55, 10]
- logits = tf.constant(np.random.randn(*x_shape).astype(np.float32))
- targets = tf.to_float(tf.constant(np.random.random_sample(x_shape) > 0.3))
- weighted_loss = util.weighted_hinge_loss(targets, logits)
- expected_loss = hinge_loss(targets, logits)
- with self.test_session():
- self.assertAllClose(expected_loss.eval(), weighted_loss.eval())
-
- def testLessTrivialCompatibilityWithHinge(self):
- # Tests compatibility with a constant weight for positives and negatives.
- x_shape = [56, 11]
- logits = tf.constant(np.random.randn(*x_shape).astype(np.float32))
- targets = tf.to_float(tf.constant(np.random.random_sample(x_shape) > 0.7))
- weight = 1.0 + 1.0/2 + 1.0/3 + 1.0/4 + 1.0/5 + 1.0/6 + 1.0/7
- weighted_loss = util.weighted_hinge_loss(targets, logits, weight, weight)
- expected_loss = hinge_loss(targets, logits) * weight
- with self.test_session():
- self.assertAllClose(expected_loss.eval(), weighted_loss.eval())
-
- def testNontrivialCompatibilityWithHinge(self):
- # Tests compatibility with different positive and negative weights.
- x_shape = [23, 8]
- logits_positives = tf.constant(np.random.randn(*x_shape).astype(np.float32))
- logits_negatives = tf.constant(np.random.randn(*x_shape).astype(np.float32))
- targets_positives = tf.ones(x_shape)
- targets_negatives = tf.zeros(x_shape)
- logits = tf.concat([logits_positives, logits_negatives], 0)
- targets = tf.concat([targets_positives, targets_negatives], 0)
-
- raw_loss = util.weighted_hinge_loss(targets,
- logits,
- positive_weights=3.4,
- negative_weights=1.2)
- loss = tf.reduce_sum(raw_loss, 0)
- positives_hinge = hinge_loss(targets_positives, logits_positives)
- negatives_hinge = hinge_loss(targets_negatives, logits_negatives)
- expected = tf.add(tf.reduce_sum(3.4 * positives_hinge, 0),
- tf.reduce_sum(1.2 * negatives_hinge, 0))
-
- with self.test_session():
- self.assertAllClose(loss.eval(), expected.eval())
-
- def test3DLogitsAndTargets(self):
- # Tests correctness when logits is 3D and targets is 2D.
- targets_shape = [30, 4]
- logits_shape = [targets_shape[0], targets_shape[1], 3]
- targets = tf.to_float(
- tf.constant(np.random.random_sample(targets_shape) > 0.7))
- logits = tf.constant(np.random.randn(*logits_shape).astype(np.float32))
- weight_vector = [1.0, 1.0, 1.0]
- loss = util.weighted_hinge_loss(targets, logits, weight_vector)
-
- with self.test_session():
- loss_value = loss.eval()
- for i in range(len(weight_vector)):
- expected = hinge_loss(targets, logits[:, :, i]).eval()
- self.assertAllClose(loss_value[:, :, i], expected)
-
-
-class BuildLabelPriorsTest(tf.test.TestCase):
-
- def testLabelPriorConsistency(self):
- # Checks that, with zero pseudocounts, the returned label priors reproduce
- # label frequencies in the batch.
- batch_shape = [4, 10]
- labels = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.678)))
-
- label_priors_update = util.build_label_priors(
- labels=labels, positive_pseudocount=0, negative_pseudocount=0)
- expected_priors = tf.reduce_mean(labels, 0)
-
- with self.test_session():
- tf.global_variables_initializer().run()
- self.assertAllClose(label_priors_update.eval(), expected_priors.eval())
-
- def testLabelPriorsUpdate(self):
- # Checks that the update of label priors behaves as expected.
- batch_shape = [1, 5]
- labels = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.4)))
- label_priors_update = util.build_label_priors(labels)
-
- label_sum = np.ones(shape=batch_shape)
- weight_sum = 2.0 * np.ones(shape=batch_shape)
-
- with self.test_session() as session:
- tf.global_variables_initializer().run()
-
- for _ in range(3):
- label_sum += labels.eval()
- weight_sum += np.ones(shape=batch_shape)
- expected_posteriors = label_sum / weight_sum
- label_priors = label_priors_update.eval().reshape(batch_shape)
- self.assertAllClose(label_priors, expected_posteriors)
-
- # Re-initialize labels to get a new random sample.
- session.run(labels.initializer)
-
- def testLabelPriorsUpdateWithWeights(self):
- # Checks the update of label priors with per-example weights.
- batch_size = 6
- num_labels = 5
- batch_shape = [batch_size, num_labels]
- labels = tf.Variable(
- tf.to_float(tf.greater(tf.random_uniform(batch_shape), 0.6)))
- weights = tf.Variable(tf.random_uniform(batch_shape) * 6.2)
-
- update_op = util.build_label_priors(labels, weights=weights)
-
- expected_weighted_label_counts = 1.0 + tf.reduce_sum(weights * labels, 0)
- expected_weight_sum = 2.0 + tf.reduce_sum(weights, 0)
- expected_label_posteriors = tf.divide(expected_weighted_label_counts,
- expected_weight_sum)
-
- with self.test_session() as session:
- tf.global_variables_initializer().run()
-
- updated_priors, expected_posteriors = session.run(
- [update_op, expected_label_posteriors])
- self.assertAllClose(updated_priors, expected_posteriors)
-
-
-class WeightedSurrogateLossTest(parameterized.TestCase, tf.test.TestCase):
-
- @parameterized.parameters(
- ('hinge', util.weighted_hinge_loss),
- ('xent', util.weighted_sigmoid_cross_entropy_with_logits))
- def testCompatibilityLoss(self, loss_name, loss_fn):
- x_shape = [28, 4]
- logits = tf.constant(np.random.randn(*x_shape).astype(np.float32))
- targets = tf.to_float(tf.constant(np.random.random_sample(x_shape) > 0.5))
- positive_weights = 0.66
- negative_weights = 11.1
- expected_loss = loss_fn(
- targets,
- logits,
- positive_weights=positive_weights,
- negative_weights=negative_weights)
- computed_loss = util.weighted_surrogate_loss(
- targets,
- logits,
- loss_name,
- positive_weights=positive_weights,
- negative_weights=negative_weights)
- with self.test_session():
- self.assertAllClose(expected_loss.eval(), computed_loss.eval())
-
- def testSurrogatgeError(self):
- x_shape = [7, 3]
- logits = tf.constant(np.random.randn(*x_shape).astype(np.float32))
- targets = tf.to_float(tf.constant(np.random.random_sample(x_shape) > 0.5))
-
- with self.assertRaises(ValueError):
- util.weighted_surrogate_loss(logits, targets, 'bug')
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/im2txt/.gitignore b/research/im2txt/.gitignore
deleted file mode 100644
index fb46913cc7a5994c4324de50829c95d7858c30f4..0000000000000000000000000000000000000000
--- a/research/im2txt/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-/bazel-bin
-/bazel-ci_build-cache
-/bazel-genfiles
-/bazel-out
-/bazel-im2txt
-/bazel-testlogs
-/bazel-tf
diff --git a/research/im2txt/README.md b/research/im2txt/README.md
deleted file mode 100644
index 2eb72822a39e3959a5a9370f26a9cc5c12be0fda..0000000000000000000000000000000000000000
--- a/research/im2txt/README.md
+++ /dev/null
@@ -1,342 +0,0 @@
-
-
-
-
-# Show and Tell: A Neural Image Caption Generator
-
-A TensorFlow implementation of the image-to-text model described in the paper:
-
-"Show and Tell: Lessons learned from the 2015 MSCOCO Image Captioning
-Challenge."
-
-Oriol Vinyals, Alexander Toshev, Samy Bengio, Dumitru Erhan.
-
-*IEEE transactions on pattern analysis and machine intelligence (2016).*
-
-Full text available at: http://arxiv.org/abs/1609.06647
-
-## Contact
-***Author:*** Chris Shallue
-
-***Pull requests and issues:*** @cshallue
-
-## Contents
-* [Model Overview](#model-overview)
- * [Introduction](#introduction)
- * [Architecture](#architecture)
-* [Getting Started](#getting-started)
- * [A Note on Hardware and Training Time](#a-note-on-hardware-and-training-time)
- * [Install Required Packages](#install-required-packages)
- * [Prepare the Training Data](#prepare-the-training-data)
- * [Download the Inception v3 Checkpoint](#download-the-inception-v3-checkpoint)
-* [Training a Model](#training-a-model)
- * [Initial Training](#initial-training)
- * [Fine Tune the Inception v3 Model](#fine-tune-the-inception-v3-model)
-* [Generating Captions](#generating-captions)
-
-## Model Overview
-
-### Introduction
-
-The *Show and Tell* model is a deep neural network that learns how to describe
-the content of images. For example:
-
-
-
-### Architecture
-
-The *Show and Tell* model is an example of an *encoder-decoder* neural network.
-It works by first "encoding" an image into a fixed-length vector representation,
-and then "decoding" the representation into a natural language description.
-
-The image encoder is a deep convolutional neural network. This type of
-network is widely used for image tasks and is currently state-of-the-art for
-object recognition and detection. Our particular choice of network is the
-[*Inception v3*](http://arxiv.org/abs/1512.00567) image recognition model
-pretrained on the
-[ILSVRC-2012-CLS](http://www.image-net.org/challenges/LSVRC/2012/) image
-classification dataset.
-
-The decoder is a long short-term memory (LSTM) network. This type of network is
-commonly used for sequence modeling tasks such as language modeling and machine
-translation. In the *Show and Tell* model, the LSTM network is trained as a
-language model conditioned on the image encoding.
-
-Words in the captions are represented with an embedding model. Each word in the
-vocabulary is associated with a fixed-length vector representation that is
-learned during training.
-
-The following diagram illustrates the model architecture.
-
-
-
-In this diagram, \{*s*0, *s*1, ..., *s**N*-1\}
-are the words of the caption and \{*w**e**s*0,
-*w**e**s*1, ..., *w**e**s**N*-1\}
-are their corresponding word embedding vectors. The outputs \{*p*1,
-*p*2, ..., *p**N*\} of the LSTM are probability
-distributions generated by the model for the next word in the sentence. The
-terms \{log *p*1(*s*1),
-log *p*2(*s*2), ...,
-log *p**N*(*s**N*)\} are the log-likelihoods of the
-correct word at each step; the negated sum of these terms is the minimization
-objective of the model.
-
-During the first phase of training the parameters of the *Inception v3* model
-are kept fixed: it is simply a static image encoder function. A single trainable
-layer is added on top of the *Inception v3* model to transform the image
-embedding into the word embedding vector space. The model is trained with
-respect to the parameters of the word embeddings, the parameters of the layer on
-top of *Inception v3* and the parameters of the LSTM. In the second phase of
-training, all parameters - including the parameters of *Inception v3* - are
-trained to jointly fine-tune the image encoder and the LSTM.
-
-Given a trained model and an image we use *beam search* to generate captions for
-that image. Captions are generated word-by-word, where at each step *t* we use
-the set of sentences already generated with length *t* - 1 to generate a new set
-of sentences with length *t*. We keep only the top *k* candidates at each step,
-where the hyperparameter *k* is called the *beam size*. We have found the best
-performance with *k* = 3.
-
-## Getting Started
-
-### A Note on Hardware and Training Time
-
-The time required to train the *Show and Tell* model depends on your specific
-hardware and computational capacity. In this guide we assume you will be running
-training on a single machine with a GPU. In our experience on an NVIDIA Tesla
-K20m GPU the initial training phase takes 1-2 weeks. The second training phase
-may take several additional weeks to achieve peak performance (but you can stop
-this phase early and still get reasonable results).
-
-It is possible to achieve a speed-up by implementing distributed training across
-a cluster of machines with GPUs, but that is not covered in this guide.
-
-Whilst it is possible to run this code on a CPU, beware that this may be
-approximately 10 times slower.
-
-### Install Required Packages
-First ensure that you have installed the following required packages:
-
-* **Bazel** ([instructions](http://bazel.io/docs/install.html))
-* **Python 2.7**
-* **TensorFlow** 1.0 or greater ([instructions](https://www.tensorflow.org/install/))
-* **NumPy** ([instructions](http://www.scipy.org/install.html))
-* **Natural Language Toolkit (NLTK)**:
- * First install NLTK ([instructions](http://www.nltk.org/install.html))
- * Then install the NLTK data package "punkt" ([instructions](http://www.nltk.org/data.html))
-* **Unzip**
-### Prepare the Training Data
-
-To train the model you will need to provide training data in native TFRecord
-format. The TFRecord format consists of a set of sharded files containing
-serialized `tf.SequenceExample` protocol buffers. Each `tf.SequenceExample`
-proto contains an image (JPEG format), a caption and metadata such as the image
-id.
-
-Each caption is a list of words. During preprocessing, a dictionary is created
-that assigns each word in the vocabulary to an integer-valued id. Each caption
-is encoded as a list of integer word ids in the `tf.SequenceExample` protos.
-
-We have provided a script to download and preprocess the [MSCOCO](http://mscoco.org/) image captioning data set into this format. Downloading
-and preprocessing the data may take several hours depending on your network and
-computer speed. Please be patient.
-
-Before running the script, ensure that your hard disk has at least 150GB of
-available space for storing the downloaded and processed data.
-
-```shell
-# Location to save the MSCOCO data.
-MSCOCO_DIR="${HOME}/im2txt/data/mscoco"
-
-# Build the preprocessing script.
-cd research/im2txt
-bazel build //im2txt:download_and_preprocess_mscoco
-
-# Run the preprocessing script.
-bazel-bin/im2txt/download_and_preprocess_mscoco "${MSCOCO_DIR}"
-```
-
-The final line of the output should read:
-
-```
-2016-09-01 16:47:47.296630: Finished processing all 20267 image-caption pairs in data set 'test'.
-```
-
-When the script finishes you will find 256 training, 4 validation and 8 testing
-files in `DATA_DIR`. The files will match the patterns `train-?????-of-00256`,
-`val-?????-of-00004` and `test-?????-of-00008`, respectively.
-
-### Download the Inception v3 Checkpoint
-
-The *Show and Tell* model requires a pretrained *Inception v3* checkpoint file
-to initialize the parameters of its image encoder submodel.
-
-This checkpoint file is provided by the
-[TensorFlow-Slim image classification library](https://github.com/tensorflow/models/tree/master/research/slim#tensorflow-slim-image-classification-library)
-which provides a suite of pre-trained image classification models. You can read
-more about the models provided by the library
-[here](https://github.com/tensorflow/models/tree/master/research/slim#pre-trained-models).
-
-
-Run the following commands to download the *Inception v3* checkpoint.
-
-```shell
-# Location to save the Inception v3 checkpoint.
-INCEPTION_DIR="${HOME}/im2txt/data"
-mkdir -p ${INCEPTION_DIR}
-
-wget "http://download.tensorflow.org/models/inception_v3_2016_08_28.tar.gz"
-tar -xvf "inception_v3_2016_08_28.tar.gz" -C ${INCEPTION_DIR}
-rm "inception_v3_2016_08_28.tar.gz"
-```
-
-Note that the *Inception v3* checkpoint will only be used for initializing the
-parameters of the *Show and Tell* model. Once the *Show and Tell* model starts
-training it will save its own checkpoint files containing the values of all its
-parameters (including copies of the *Inception v3* parameters). If training is
-stopped and restarted, the parameter values will be restored from the latest
-*Show and Tell* checkpoint and the *Inception v3* checkpoint will be ignored. In
-other words, the *Inception v3* checkpoint is only used in the 0-th global step
-(initialization) of training the *Show and Tell* model.
-
-## Training a Model
-
-### Initial Training
-
-Run the training script.
-
-```shell
-# Directory containing preprocessed MSCOCO data.
-MSCOCO_DIR="${HOME}/im2txt/data/mscoco"
-
-# Inception v3 checkpoint file.
-INCEPTION_CHECKPOINT="${HOME}/im2txt/data/inception_v3.ckpt"
-
-# Directory to save the model.
-MODEL_DIR="${HOME}/im2txt/model"
-
-# Build the model.
-cd research/im2txt
-bazel build -c opt //im2txt/...
-
-# Run the training script.
-bazel-bin/im2txt/train \
- --input_file_pattern="${MSCOCO_DIR}/train-?????-of-00256" \
- --inception_checkpoint_file="${INCEPTION_CHECKPOINT}" \
- --train_dir="${MODEL_DIR}/train" \
- --train_inception=false \
- --number_of_steps=1000000
-```
-
-Run the evaluation script in a separate process. This will log evaluation
-metrics to TensorBoard which allows training progress to be monitored in
-real-time.
-
-Note that you may run out of memory if you run the evaluation script on the same
-GPU as the training script. You can run the command
-`export CUDA_VISIBLE_DEVICES=""` to force the evaluation script to run on CPU.
-If evaluation runs too slowly on CPU, you can decrease the value of
-`--num_eval_examples`.
-
-```shell
-MSCOCO_DIR="${HOME}/im2txt/data/mscoco"
-MODEL_DIR="${HOME}/im2txt/model"
-
-# Ignore GPU devices (only necessary if your GPU is currently memory
-# constrained, for example, by running the training script).
-export CUDA_VISIBLE_DEVICES=""
-
-# Run the evaluation script. This will run in a loop, periodically loading the
-# latest model checkpoint file and computing evaluation metrics.
-bazel-bin/im2txt/evaluate \
- --input_file_pattern="${MSCOCO_DIR}/val-?????-of-00004" \
- --checkpoint_dir="${MODEL_DIR}/train" \
- --eval_dir="${MODEL_DIR}/eval"
-```
-
-Run a TensorBoard server in a separate process for real-time monitoring of
-training progress and evaluation metrics.
-
-```shell
-MODEL_DIR="${HOME}/im2txt/model"
-
-# Run a TensorBoard server.
-tensorboard --logdir="${MODEL_DIR}"
-```
-
-### Fine Tune the Inception v3 Model
-
-Your model will already be able to generate reasonable captions after the first
-phase of training. Try it out! (See [Generating Captions](#generating-captions)).
-
-You can further improve the performance of the model by running a
-second training phase to jointly fine-tune the parameters of the *Inception v3*
-image submodel and the LSTM.
-
-```shell
-# Restart the training script with --train_inception=true.
-bazel-bin/im2txt/train \
- --input_file_pattern="${MSCOCO_DIR}/train-?????-of-00256" \
- --train_dir="${MODEL_DIR}/train" \
- --train_inception=true \
- --number_of_steps=3000000 # Additional 2M steps (assuming 1M in initial training).
-```
-
-Note that training will proceed much slower now, and the model will continue to
-improve by a small amount for a long time. We have found that it will improve
-slowly for an additional 2-2.5 million steps before it begins to overfit. This
-may take several weeks on a single GPU. If you don't care about absolutely
-optimal performance then feel free to halt training sooner by stopping the
-training script or passing a smaller value to the flag `--number_of_steps`. Your
-model will still work reasonably well.
-
-## Generating Captions
-
-Your trained *Show and Tell* model can generate captions for any JPEG image! The
-following command line will generate captions for an image from the test set.
-
-```shell
-# Path to checkpoint file or a directory containing checkpoint files. Passing
-# a directory will only work if there is also a file named 'checkpoint' which
-# lists the available checkpoints in the directory. It will not work if you
-# point to a directory with just a copy of a model checkpoint: in that case,
-# you will need to pass the checkpoint path explicitly.
-CHECKPOINT_PATH="${HOME}/im2txt/model/train"
-
-# Vocabulary file generated by the preprocessing script.
-VOCAB_FILE="${HOME}/im2txt/data/mscoco/word_counts.txt"
-
-# JPEG image file to caption.
-IMAGE_FILE="${HOME}/im2txt/data/mscoco/raw-data/val2014/COCO_val2014_000000224477.jpg"
-
-# Build the inference binary.
-cd research/im2txt
-bazel build -c opt //im2txt:run_inference
-
-# Ignore GPU devices (only necessary if your GPU is currently memory
-# constrained, for example, by running the training script).
-export CUDA_VISIBLE_DEVICES=""
-
-# Run inference to generate captions.
-bazel-bin/im2txt/run_inference \
- --checkpoint_path=${CHECKPOINT_PATH} \
- --vocab_file=${VOCAB_FILE} \
- --input_files=${IMAGE_FILE}
-```
-
-Example output:
-
-```
-Captions for image COCO_val2014_000000224477.jpg:
- 0) a man riding a wave on top of a surfboard . (p=0.040413)
- 1) a person riding a surf board on a wave (p=0.017452)
- 2) a man riding a wave on a surfboard in the ocean . (p=0.005743)
-```
-
-Note: you may get different results. Some variation between different models is
-expected.
-
-Here is the image:
-
-
diff --git a/research/im2txt/WORKSPACE b/research/im2txt/WORKSPACE
deleted file mode 100644
index 22da718b06f9c61be4ffdf45e48919ed4a5f17ae..0000000000000000000000000000000000000000
--- a/research/im2txt/WORKSPACE
+++ /dev/null
@@ -1 +0,0 @@
-workspace(name = "im2txt")
diff --git a/research/im2txt/conda-env/ubuntu-18-04-environment.yaml b/research/im2txt/conda-env/ubuntu-18-04-environment.yaml
deleted file mode 100644
index 332ff2a47f8f49fcdde7b769c29ff84cf5a5ff9d..0000000000000000000000000000000000000000
--- a/research/im2txt/conda-env/ubuntu-18-04-environment.yaml
+++ /dev/null
@@ -1,142 +0,0 @@
-name: im2txt
-channels:
- - defaults
-dependencies:
- - _tflow_select=2.3.0=mkl
- - absl-py=0.5.0=py27_0
- - astor=0.7.1=py27_0
- - backports=1.0=py27_1
- - backports.functools_lru_cache=1.5=py27_1
- - backports.shutil_get_terminal_size=1.0.0=py27_2
- - backports.weakref=1.0.post1=py27_0
- - backports_abc=0.5=py27_0
- - blas=1.0=mkl
- - bleach=3.0.2=py27_0
- - ca-certificates=2018.03.07=0
- - certifi=2018.10.15=py27_0
- - configparser=3.5.0=py27_0
- - cycler=0.10.0=py27_0
- - dbus=1.13.2=h714fa37_1
- - decorator=4.3.0=py27_0
- - entrypoints=0.2.3=py27_2
- - enum34=1.1.6=py27_1
- - expat=2.2.6=he6710b0_0
- - fastcache=1.0.2=py27h14c3975_2
- - fontconfig=2.13.0=h9420a91_0
- - freetype=2.9.1=h8a8886c_1
- - funcsigs=1.0.2=py27_0
- - functools32=3.2.3.2=py27_1
- - futures=3.2.0=py27_0
- - gast=0.2.0=py27_0
- - glib=2.56.2=hd408876_0
- - gmp=6.1.2=h6c8ec71_1
- - gmpy2=2.0.8=py27h10f8cd9_2
- - grpcio=1.12.1=py27hdbcaa40_0
- - gst-plugins-base=1.14.0=hbbd80ab_1
- - gstreamer=1.14.0=hb453b48_1
- - h5py=2.8.0=py27h989c5e5_3
- - hdf5=1.10.2=hba1933b_1
- - icu=58.2=h9c2bf20_1
- - intel-openmp=2019.0=118
- - ipaddress=1.0.22=py27_0
- - ipykernel=4.10.0=py27_0
- - ipython=5.8.0=py27_0
- - ipython_genutils=0.2.0=py27_0
- - ipywidgets=7.4.2=py27_0
- - jinja2=2.10=py27_0
- - jpeg=9b=h024ee3a_2
- - jsonschema=2.6.0=py27_0
- - jupyter=1.0.0=py27_7
- - jupyter_client=5.2.3=py27_0
- - jupyter_console=5.2.0=py27_1
- - jupyter_core=4.4.0=py27_0
- - keras-applications=1.0.6=py27_0
- - keras-preprocessing=1.0.5=py27_0
- - kiwisolver=1.0.1=py27hf484d3e_0
- - libedit=3.1.20170329=h6b74fdf_2
- - libffi=3.2.1=hd88cf55_4
- - libgcc-ng=8.2.0=hdf63c60_1
- - libgfortran-ng=7.3.0=hdf63c60_0
- - libpng=1.6.35=hbc83047_0
- - libprotobuf=3.6.0=hdbcaa40_0
- - libsodium=1.0.16=h1bed415_0
- - libstdcxx-ng=8.2.0=hdf63c60_1
- - libuuid=1.0.3=h1bed415_2
- - libxcb=1.13=h1bed415_1
- - libxml2=2.9.8=h26e45fe_1
- - linecache2=1.0.0=py27_0
- - markdown=3.0.1=py27_0
- - markupsafe=1.0=py27h14c3975_1
- - matplotlib=2.2.3=py27hb69df0a_0
- - mistune=0.8.4=py27h7b6447c_0
- - mkl=2019.0=118
- - mkl_fft=1.0.6=py27h7dd41cf_0
- - mkl_random=1.0.1=py27h4414c95_1
- - mock=2.0.0=py27_0
- - mpc=1.1.0=h10f8cd9_1
- - mpfr=4.0.1=hdf1c602_3
- - mpmath=1.0.0=py27_2
- - nbconvert=5.3.1=py27_0
- - nbformat=4.4.0=py27_0
- - ncurses=6.1=hf484d3e_0
- - nltk=3.3.0=py27_0
- - nose=1.3.7=py27_2
- - notebook=5.7.0=py27_0
- - numpy=1.15.3=py27h1d66e8a_0
- - numpy-base=1.15.3=py27h81de0dd_0
- - openssl=1.0.2p=h14c3975_0
- - pandas=0.23.4=py27h04863e7_0
- - pandoc=2.2.3.2=0
- - pandocfilters=1.4.2=py27_1
- - pathlib2=2.3.2=py27_0
- - pbr=4.3.0=py27_0
- - pcre=8.42=h439df22_0
- - pexpect=4.6.0=py27_0
- - pickleshare=0.7.5=py27_0
- - pip=10.0.1=py27_0
- - prometheus_client=0.4.2=py27_0
- - prompt_toolkit=1.0.15=py27_0
- - protobuf=3.6.0=py27hf484d3e_0
- - ptyprocess=0.6.0=py27_0
- - pygments=2.2.0=py27_0
- - pyparsing=2.2.2=py27_0
- - pyqt=5.9.2=py27h05f1152_2
- - python=2.7.15=h77bded6_2
- - python-dateutil=2.7.3=py27_0
- - pytz=2018.5=py27_0
- - pyzmq=17.1.2=py27h14c3975_0
- - qt=5.9.6=h8703b6f_2
- - qtconsole=4.4.2=py27_0
- - readline=7.0=h7b6447c_5
- - scandir=1.9.0=py27h14c3975_0
- - scipy=1.1.0=py27hfa4b5c9_1
- - send2trash=1.5.0=py27_0
- - setuptools=40.4.3=py27_0
- - simplegeneric=0.8.1=py27_2
- - singledispatch=3.4.0.3=py27_0
- - sip=4.19.8=py27hf484d3e_0
- - six=1.11.0=py27_1
- - sqlite=3.25.2=h7b6447c_0
- - subprocess32=3.5.3=py27h7b6447c_0
- - sympy=1.3=py27_0
- - tensorboard=1.11.0=py27hf484d3e_0
- - tensorflow=1.11.0=mkl_py27h25e0b76_0
- - tensorflow-base=1.11.0=mkl_py27h3c3e929_0
- - termcolor=1.1.0=py27_1
- - terminado=0.8.1=py27_1
- - testpath=0.4.2=py27_0
- - tk=8.6.8=hbc83047_0
- - tornado=5.1.1=py27h7b6447c_0
- - traceback2=1.4.0=py27_0
- - traitlets=4.3.2=py27_0
- - unittest2=1.1.0=py27_0
- - wcwidth=0.1.7=py27_0
- - webencodings=0.5.1=py27_1
- - werkzeug=0.14.1=py27_0
- - wheel=0.32.2=py27_0
- - widgetsnbextension=3.4.2=py27_0
- - xz=5.2.4=h14c3975_4
- - zeromq=4.2.5=hf484d3e_1
- - zlib=1.2.11=ha838bed_2
-prefix: /home/arinto_murdopo/anaconda3/envs/im2txt
-
diff --git a/research/im2txt/g3doc/COCO_val2014_000000224477.jpg b/research/im2txt/g3doc/COCO_val2014_000000224477.jpg
deleted file mode 100644
index 8976fa84b40b04c5bf1205a49c8d236b747f8f9b..0000000000000000000000000000000000000000
Binary files a/research/im2txt/g3doc/COCO_val2014_000000224477.jpg and /dev/null differ
diff --git a/research/im2txt/g3doc/example_captions.jpg b/research/im2txt/g3doc/example_captions.jpg
deleted file mode 100644
index b3a8f43247e5c9c39a3f93daaf1ad34837959ec5..0000000000000000000000000000000000000000
Binary files a/research/im2txt/g3doc/example_captions.jpg and /dev/null differ
diff --git a/research/im2txt/g3doc/show_and_tell_architecture.png b/research/im2txt/g3doc/show_and_tell_architecture.png
deleted file mode 100644
index 984590d54ba4aa089b5740fd69f6dc6216b9047f..0000000000000000000000000000000000000000
Binary files a/research/im2txt/g3doc/show_and_tell_architecture.png and /dev/null differ
diff --git a/research/im2txt/im2txt/BUILD b/research/im2txt/im2txt/BUILD
deleted file mode 100644
index 8c403171153c36ee43cde2788dbfcaf9c7bf4293..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/BUILD
+++ /dev/null
@@ -1,96 +0,0 @@
-package(default_visibility = [":internal"])
-
-licenses(["notice"]) # Apache 2.0
-
-exports_files(["LICENSE"])
-
-package_group(
- name = "internal",
- packages = [
- "//im2txt/...",
- ],
-)
-
-py_binary(
- name = "build_mscoco_data",
- srcs = [
- "data/build_mscoco_data.py",
- ],
-)
-
-sh_binary(
- name = "download_and_preprocess_mscoco",
- srcs = ["data/download_and_preprocess_mscoco.sh"],
- data = [
- ":build_mscoco_data",
- ],
-)
-
-py_library(
- name = "configuration",
- srcs = ["configuration.py"],
- srcs_version = "PY2AND3",
-)
-
-py_library(
- name = "show_and_tell_model",
- srcs = ["show_and_tell_model.py"],
- srcs_version = "PY2AND3",
- deps = [
- "//im2txt/ops:image_embedding",
- "//im2txt/ops:image_processing",
- "//im2txt/ops:inputs",
- ],
-)
-
-py_test(
- name = "show_and_tell_model_test",
- size = "large",
- srcs = ["show_and_tell_model_test.py"],
- deps = [
- ":configuration",
- ":show_and_tell_model",
- ],
-)
-
-py_library(
- name = "inference_wrapper",
- srcs = ["inference_wrapper.py"],
- srcs_version = "PY2AND3",
- deps = [
- ":show_and_tell_model",
- "//im2txt/inference_utils:inference_wrapper_base",
- ],
-)
-
-py_binary(
- name = "train",
- srcs = ["train.py"],
- srcs_version = "PY2AND3",
- deps = [
- ":configuration",
- ":show_and_tell_model",
- ],
-)
-
-py_binary(
- name = "evaluate",
- srcs = ["evaluate.py"],
- srcs_version = "PY2AND3",
- deps = [
- ":configuration",
- ":show_and_tell_model",
- ],
-)
-
-py_binary(
- name = "run_inference",
- srcs = ["run_inference.py"],
- srcs_version = "PY2AND3",
- deps = [
- ":configuration",
- ":inference_wrapper",
- "//im2txt/inference_utils:caption_generator",
- "//im2txt/inference_utils:vocabulary",
- ],
-)
diff --git a/research/im2txt/im2txt/configuration.py b/research/im2txt/im2txt/configuration.py
deleted file mode 100644
index 3b664eb9f0cd963fb26929d019ec9cdb3282d0a8..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/configuration.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Image-to-text model and training configurations."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-class ModelConfig(object):
- """Wrapper class for model hyperparameters."""
-
- def __init__(self):
- """Sets the default model hyperparameters."""
- # File pattern of sharded TFRecord file containing SequenceExample protos.
- # Must be provided in training and evaluation modes.
- self.input_file_pattern = None
-
- # Image format ("jpeg" or "png").
- self.image_format = "jpeg"
-
- # Approximate number of values per input shard. Used to ensure sufficient
- # mixing between shards in training.
- self.values_per_input_shard = 2300
- # Minimum number of shards to keep in the input queue.
- self.input_queue_capacity_factor = 2
- # Number of threads for prefetching SequenceExample protos.
- self.num_input_reader_threads = 1
-
- # Name of the SequenceExample context feature containing image data.
- self.image_feature_name = "image/data"
- # Name of the SequenceExample feature list containing integer captions.
- self.caption_feature_name = "image/caption_ids"
-
- # Number of unique words in the vocab (plus 1, for ).
- # The default value is larger than the expected actual vocab size to allow
- # for differences between tokenizer versions used in preprocessing. There is
- # no harm in using a value greater than the actual vocab size, but using a
- # value less than the actual vocab size will result in an error.
- self.vocab_size = 12000
-
- # Number of threads for image preprocessing. Should be a multiple of 2.
- self.num_preprocess_threads = 4
-
- # Batch size.
- self.batch_size = 32
-
- # File containing an Inception v3 checkpoint to initialize the variables
- # of the Inception model. Must be provided when starting training for the
- # first time.
- self.inception_checkpoint_file = None
-
- # Dimensions of Inception v3 input images.
- self.image_height = 299
- self.image_width = 299
-
- # Scale used to initialize model variables.
- self.initializer_scale = 0.08
-
- # LSTM input and output dimensionality, respectively.
- self.embedding_size = 512
- self.num_lstm_units = 512
-
- # If < 1.0, the dropout keep probability applied to LSTM variables.
- self.lstm_dropout_keep_prob = 0.7
-
-
-class TrainingConfig(object):
- """Wrapper class for training hyperparameters."""
-
- def __init__(self):
- """Sets the default training hyperparameters."""
- # Number of examples per epoch of training data.
- self.num_examples_per_epoch = 586363
-
- # Optimizer for training the model.
- self.optimizer = "SGD"
-
- # Learning rate for the initial phase of training.
- self.initial_learning_rate = 2.0
- self.learning_rate_decay_factor = 0.5
- self.num_epochs_per_decay = 8.0
-
- # Learning rate when fine tuning the Inception v3 parameters.
- self.train_inception_learning_rate = 0.0005
-
- # If not None, clip gradients to this value.
- self.clip_gradients = 5.0
-
- # How many model checkpoints to keep.
- self.max_checkpoints_to_keep = 5
diff --git a/research/im2txt/im2txt/data/build_mscoco_data.py b/research/im2txt/im2txt/data/build_mscoco_data.py
deleted file mode 100644
index 2c3e9d977669bf63d8e39128336319b48c0432dd..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/data/build_mscoco_data.py
+++ /dev/null
@@ -1,483 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Converts MSCOCO data to TFRecord file format with SequenceExample protos.
-
-The MSCOCO images are expected to reside in JPEG files located in the following
-directory structure:
-
- train_image_dir/COCO_train2014_000000000151.jpg
- train_image_dir/COCO_train2014_000000000260.jpg
- ...
-
-and
-
- val_image_dir/COCO_val2014_000000000042.jpg
- val_image_dir/COCO_val2014_000000000073.jpg
- ...
-
-The MSCOCO annotations JSON files are expected to reside in train_captions_file
-and val_captions_file respectively.
-
-This script converts the combined MSCOCO data into sharded data files consisting
-of 256, 4 and 8 TFRecord files, respectively:
-
- output_dir/train-00000-of-00256
- output_dir/train-00001-of-00256
- ...
- output_dir/train-00255-of-00256
-
-and
-
- output_dir/val-00000-of-00004
- ...
- output_dir/val-00003-of-00004
-
-and
-
- output_dir/test-00000-of-00008
- ...
- output_dir/test-00007-of-00008
-
-Each TFRecord file contains ~2300 records. Each record within the TFRecord file
-is a serialized SequenceExample proto consisting of precisely one image-caption
-pair. Note that each image has multiple captions (usually 5) and therefore each
-image is replicated multiple times in the TFRecord files.
-
-The SequenceExample proto contains the following fields:
-
- context:
- image/image_id: integer MSCOCO image identifier
- image/data: string containing JPEG encoded image in RGB colorspace
-
- feature_lists:
- image/caption: list of strings containing the (tokenized) caption words
- image/caption_ids: list of integer ids corresponding to the caption words
-
-The captions are tokenized using the NLTK (http://www.nltk.org/) word tokenizer.
-The vocabulary of word identifiers is constructed from the sorted list (by
-descending frequency) of word tokens in the training set. Only tokens appearing
-at least 4 times are considered; all other words get the "unknown" word id.
-
-NOTE: This script will consume around 100GB of disk space because each image
-in the MSCOCO dataset is replicated ~5 times (once per caption) in the output.
-This is done for two reasons:
- 1. In order to better shuffle the training data.
- 2. It makes it easier to perform asynchronous preprocessing of each image in
- TensorFlow.
-
-Running this script using 16 threads may take around 1 hour on a HP Z420.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from collections import Counter
-from collections import namedtuple
-from datetime import datetime
-import json
-import os.path
-import random
-import sys
-import threading
-
-
-
-import nltk.tokenize
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-tf.flags.DEFINE_string("train_image_dir", "/tmp/train2014/",
- "Training image directory.")
-tf.flags.DEFINE_string("val_image_dir", "/tmp/val2014",
- "Validation image directory.")
-
-tf.flags.DEFINE_string("train_captions_file", "/tmp/captions_train2014.json",
- "Training captions JSON file.")
-tf.flags.DEFINE_string("val_captions_file", "/tmp/captions_val2014.json",
- "Validation captions JSON file.")
-
-tf.flags.DEFINE_string("output_dir", "/tmp/", "Output data directory.")
-
-tf.flags.DEFINE_integer("train_shards", 256,
- "Number of shards in training TFRecord files.")
-tf.flags.DEFINE_integer("val_shards", 4,
- "Number of shards in validation TFRecord files.")
-tf.flags.DEFINE_integer("test_shards", 8,
- "Number of shards in testing TFRecord files.")
-
-tf.flags.DEFINE_string("start_word", "",
- "Special word added to the beginning of each sentence.")
-tf.flags.DEFINE_string("end_word", "",
- "Special word added to the end of each sentence.")
-tf.flags.DEFINE_string("unknown_word", "",
- "Special word meaning 'unknown'.")
-tf.flags.DEFINE_integer("min_word_count", 4,
- "The minimum number of occurrences of each word in the "
- "training set for inclusion in the vocabulary.")
-tf.flags.DEFINE_string("word_counts_output_file", "/tmp/word_counts.txt",
- "Output vocabulary file of word counts.")
-
-tf.flags.DEFINE_integer("num_threads", 8,
- "Number of threads to preprocess the images.")
-
-FLAGS = tf.flags.FLAGS
-
-ImageMetadata = namedtuple("ImageMetadata",
- ["image_id", "filename", "captions"])
-
-
-class Vocabulary(object):
- """Simple vocabulary wrapper."""
-
- def __init__(self, vocab, unk_id):
- """Initializes the vocabulary.
-
- Args:
- vocab: A dictionary of word to word_id.
- unk_id: Id of the special 'unknown' word.
- """
- self._vocab = vocab
- self._unk_id = unk_id
-
- def word_to_id(self, word):
- """Returns the integer id of a word string."""
- if word in self._vocab:
- return self._vocab[word]
- else:
- return self._unk_id
-
-
-class ImageDecoder(object):
- """Helper class for decoding images in TensorFlow."""
-
- def __init__(self):
- # Create a single TensorFlow Session for all image decoding calls.
- self._sess = tf.Session()
-
- # TensorFlow ops for JPEG decoding.
- self._encoded_jpeg = tf.placeholder(dtype=tf.string)
- self._decode_jpeg = tf.image.decode_jpeg(self._encoded_jpeg, channels=3)
-
- def decode_jpeg(self, encoded_jpeg):
- image = self._sess.run(self._decode_jpeg,
- feed_dict={self._encoded_jpeg: encoded_jpeg})
- assert len(image.shape) == 3
- assert image.shape[2] == 3
- return image
-
-
-def _int64_feature(value):
- """Wrapper for inserting an int64 Feature into a SequenceExample proto."""
- return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
-
-
-def _bytes_feature(value):
- """Wrapper for inserting a bytes Feature into a SequenceExample proto."""
- return tf.train.Feature(bytes_list=tf.train.BytesList(value=[str(value)]))
-
-
-def _int64_feature_list(values):
- """Wrapper for inserting an int64 FeatureList into a SequenceExample proto."""
- return tf.train.FeatureList(feature=[_int64_feature(v) for v in values])
-
-
-def _bytes_feature_list(values):
- """Wrapper for inserting a bytes FeatureList into a SequenceExample proto."""
- return tf.train.FeatureList(feature=[_bytes_feature(v) for v in values])
-
-
-def _to_sequence_example(image, decoder, vocab):
- """Builds a SequenceExample proto for an image-caption pair.
-
- Args:
- image: An ImageMetadata object.
- decoder: An ImageDecoder object.
- vocab: A Vocabulary object.
-
- Returns:
- A SequenceExample proto.
- """
- with tf.gfile.FastGFile(image.filename, "r") as f:
- encoded_image = f.read()
-
- try:
- decoder.decode_jpeg(encoded_image)
- except (tf.errors.InvalidArgumentError, AssertionError):
- print("Skipping file with invalid JPEG data: %s" % image.filename)
- return
-
- context = tf.train.Features(feature={
- "image/image_id": _int64_feature(image.image_id),
- "image/data": _bytes_feature(encoded_image),
- })
-
- assert len(image.captions) == 1
- caption = image.captions[0]
- caption_ids = [vocab.word_to_id(word) for word in caption]
- feature_lists = tf.train.FeatureLists(feature_list={
- "image/caption": _bytes_feature_list(caption),
- "image/caption_ids": _int64_feature_list(caption_ids)
- })
- sequence_example = tf.train.SequenceExample(
- context=context, feature_lists=feature_lists)
-
- return sequence_example
-
-
-def _process_image_files(thread_index, ranges, name, images, decoder, vocab,
- num_shards):
- """Processes and saves a subset of images as TFRecord files in one thread.
-
- Args:
- thread_index: Integer thread identifier within [0, len(ranges)].
- ranges: A list of pairs of integers specifying the ranges of the dataset to
- process in parallel.
- name: Unique identifier specifying the dataset.
- images: List of ImageMetadata.
- decoder: An ImageDecoder object.
- vocab: A Vocabulary object.
- num_shards: Integer number of shards for the output files.
- """
- # Each thread produces N shards where N = num_shards / num_threads. For
- # instance, if num_shards = 128, and num_threads = 2, then the first thread
- # would produce shards [0, 64).
- num_threads = len(ranges)
- assert not num_shards % num_threads
- num_shards_per_batch = int(num_shards / num_threads)
-
- shard_ranges = np.linspace(ranges[thread_index][0], ranges[thread_index][1],
- num_shards_per_batch + 1).astype(int)
- num_images_in_thread = ranges[thread_index][1] - ranges[thread_index][0]
-
- counter = 0
- for s in xrange(num_shards_per_batch):
- # Generate a sharded version of the file name, e.g. 'train-00002-of-00010'
- shard = thread_index * num_shards_per_batch + s
- output_filename = "%s-%.5d-of-%.5d" % (name, shard, num_shards)
- output_file = os.path.join(FLAGS.output_dir, output_filename)
- writer = tf.python_io.TFRecordWriter(output_file)
-
- shard_counter = 0
- images_in_shard = np.arange(shard_ranges[s], shard_ranges[s + 1], dtype=int)
- for i in images_in_shard:
- image = images[i]
-
- sequence_example = _to_sequence_example(image, decoder, vocab)
- if sequence_example is not None:
- writer.write(sequence_example.SerializeToString())
- shard_counter += 1
- counter += 1
-
- if not counter % 1000:
- print("%s [thread %d]: Processed %d of %d items in thread batch." %
- (datetime.now(), thread_index, counter, num_images_in_thread))
- sys.stdout.flush()
-
- writer.close()
- print("%s [thread %d]: Wrote %d image-caption pairs to %s" %
- (datetime.now(), thread_index, shard_counter, output_file))
- sys.stdout.flush()
- shard_counter = 0
- print("%s [thread %d]: Wrote %d image-caption pairs to %d shards." %
- (datetime.now(), thread_index, counter, num_shards_per_batch))
- sys.stdout.flush()
-
-
-def _process_dataset(name, images, vocab, num_shards):
- """Processes a complete data set and saves it as a TFRecord.
-
- Args:
- name: Unique identifier specifying the dataset.
- images: List of ImageMetadata.
- vocab: A Vocabulary object.
- num_shards: Integer number of shards for the output files.
- """
- # Break up each image into a separate entity for each caption.
- images = [ImageMetadata(image.image_id, image.filename, [caption])
- for image in images for caption in image.captions]
-
- # Shuffle the ordering of images. Make the randomization repeatable.
- random.seed(12345)
- random.shuffle(images)
-
- # Break the images into num_threads batches. Batch i is defined as
- # images[ranges[i][0]:ranges[i][1]].
- num_threads = min(num_shards, FLAGS.num_threads)
- spacing = np.linspace(0, len(images), num_threads + 1).astype(np.int)
- ranges = []
- threads = []
- for i in xrange(len(spacing) - 1):
- ranges.append([spacing[i], spacing[i + 1]])
-
- # Create a mechanism for monitoring when all threads are finished.
- coord = tf.train.Coordinator()
-
- # Create a utility for decoding JPEG images to run sanity checks.
- decoder = ImageDecoder()
-
- # Launch a thread for each batch.
- print("Launching %d threads for spacings: %s" % (num_threads, ranges))
- for thread_index in xrange(len(ranges)):
- args = (thread_index, ranges, name, images, decoder, vocab, num_shards)
- t = threading.Thread(target=_process_image_files, args=args)
- t.start()
- threads.append(t)
-
- # Wait for all the threads to terminate.
- coord.join(threads)
- print("%s: Finished processing all %d image-caption pairs in data set '%s'." %
- (datetime.now(), len(images), name))
-
-
-def _create_vocab(captions):
- """Creates the vocabulary of word to word_id.
-
- The vocabulary is saved to disk in a text file of word counts. The id of each
- word in the file is its corresponding 0-based line number.
-
- Args:
- captions: A list of lists of strings.
-
- Returns:
- A Vocabulary object.
- """
- print("Creating vocabulary.")
- counter = Counter()
- for c in captions:
- counter.update(c)
- print("Total words:", len(counter))
-
- # Filter uncommon words and sort by descending count.
- word_counts = [x for x in counter.items() if x[1] >= FLAGS.min_word_count]
- word_counts.sort(key=lambda x: x[1], reverse=True)
- print("Words in vocabulary:", len(word_counts))
-
- # Write out the word counts file.
- with tf.gfile.FastGFile(FLAGS.word_counts_output_file, "w") as f:
- f.write("\n".join(["%s %d" % (w, c) for w, c in word_counts]))
- print("Wrote vocabulary file:", FLAGS.word_counts_output_file)
-
- # Create the vocabulary dictionary.
- reverse_vocab = [x[0] for x in word_counts]
- unk_id = len(reverse_vocab)
- vocab_dict = dict([(x, y) for (y, x) in enumerate(reverse_vocab)])
- vocab = Vocabulary(vocab_dict, unk_id)
-
- return vocab
-
-
-def _process_caption(caption):
- """Processes a caption string into a list of tonenized words.
-
- Args:
- caption: A string caption.
-
- Returns:
- A list of strings; the tokenized caption.
- """
- tokenized_caption = [FLAGS.start_word]
- tokenized_caption.extend(nltk.tokenize.word_tokenize(caption.lower()))
- tokenized_caption.append(FLAGS.end_word)
- return tokenized_caption
-
-
-def _load_and_process_metadata(captions_file, image_dir):
- """Loads image metadata from a JSON file and processes the captions.
-
- Args:
- captions_file: JSON file containing caption annotations.
- image_dir: Directory containing the image files.
-
- Returns:
- A list of ImageMetadata.
- """
- with tf.gfile.FastGFile(captions_file, "r") as f:
- caption_data = json.load(f)
-
- # Extract the filenames.
- id_to_filename = [(x["id"], x["file_name"]) for x in caption_data["images"]]
-
- # Extract the captions. Each image_id is associated with multiple captions.
- id_to_captions = {}
- for annotation in caption_data["annotations"]:
- image_id = annotation["image_id"]
- caption = annotation["caption"]
- id_to_captions.setdefault(image_id, [])
- id_to_captions[image_id].append(caption)
-
- assert len(id_to_filename) == len(id_to_captions)
- assert set([x[0] for x in id_to_filename]) == set(id_to_captions.keys())
- print("Loaded caption metadata for %d images from %s" %
- (len(id_to_filename), captions_file))
-
- # Process the captions and combine the data into a list of ImageMetadata.
- print("Processing captions.")
- image_metadata = []
- num_captions = 0
- for image_id, base_filename in id_to_filename:
- filename = os.path.join(image_dir, base_filename)
- captions = [_process_caption(c) for c in id_to_captions[image_id]]
- image_metadata.append(ImageMetadata(image_id, filename, captions))
- num_captions += len(captions)
- print("Finished processing %d captions for %d images in %s" %
- (num_captions, len(id_to_filename), captions_file))
-
- return image_metadata
-
-
-def main(unused_argv):
- def _is_valid_num_shards(num_shards):
- """Returns True if num_shards is compatible with FLAGS.num_threads."""
- return num_shards < FLAGS.num_threads or not num_shards % FLAGS.num_threads
-
- assert _is_valid_num_shards(FLAGS.train_shards), (
- "Please make the FLAGS.num_threads commensurate with FLAGS.train_shards")
- assert _is_valid_num_shards(FLAGS.val_shards), (
- "Please make the FLAGS.num_threads commensurate with FLAGS.val_shards")
- assert _is_valid_num_shards(FLAGS.test_shards), (
- "Please make the FLAGS.num_threads commensurate with FLAGS.test_shards")
-
- if not tf.gfile.IsDirectory(FLAGS.output_dir):
- tf.gfile.MakeDirs(FLAGS.output_dir)
-
- # Load image metadata from caption files.
- mscoco_train_dataset = _load_and_process_metadata(FLAGS.train_captions_file,
- FLAGS.train_image_dir)
- mscoco_val_dataset = _load_and_process_metadata(FLAGS.val_captions_file,
- FLAGS.val_image_dir)
-
- # Redistribute the MSCOCO data as follows:
- # train_dataset = 100% of mscoco_train_dataset + 85% of mscoco_val_dataset.
- # val_dataset = 5% of mscoco_val_dataset (for validation during training).
- # test_dataset = 10% of mscoco_val_dataset (for final evaluation).
- train_cutoff = int(0.85 * len(mscoco_val_dataset))
- val_cutoff = int(0.90 * len(mscoco_val_dataset))
- train_dataset = mscoco_train_dataset + mscoco_val_dataset[0:train_cutoff]
- val_dataset = mscoco_val_dataset[train_cutoff:val_cutoff]
- test_dataset = mscoco_val_dataset[val_cutoff:]
-
- # Create vocabulary from the training captions.
- train_captions = [c for image in train_dataset for c in image.captions]
- vocab = _create_vocab(train_captions)
-
- _process_dataset("train", train_dataset, vocab, FLAGS.train_shards)
- _process_dataset("val", val_dataset, vocab, FLAGS.val_shards)
- _process_dataset("test", test_dataset, vocab, FLAGS.test_shards)
-
-
-if __name__ == "__main__":
- tf.app.run()
diff --git a/research/im2txt/im2txt/data/download_and_preprocess_mscoco.sh b/research/im2txt/im2txt/data/download_and_preprocess_mscoco.sh
deleted file mode 100755
index ab3ff28d576adcbf1992de4c00dfa350dd93b1c3..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/data/download_and_preprocess_mscoco.sh
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/bin/bash
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-# Script to download and preprocess the MSCOCO data set.
-#
-# The outputs of this script are sharded TFRecord files containing serialized
-# SequenceExample protocol buffers. See build_mscoco_data.py for details of how
-# the SequenceExample protocol buffers are constructed.
-#
-# usage:
-# ./download_and_preprocess_mscoco.sh
-set -e
-
-if [ -z "$1" ]; then
- echo "usage download_and_preproces_mscoco.sh [data dir]"
- exit
-fi
-
-if [ "$(uname)" == "Darwin" ]; then
- UNZIP="tar -xf"
-else
- UNZIP="unzip -nq"
-fi
-
-# Create the output directories.
-OUTPUT_DIR="${1%/}"
-SCRATCH_DIR="${OUTPUT_DIR}/raw-data"
-mkdir -p "${OUTPUT_DIR}"
-mkdir -p "${SCRATCH_DIR}"
-CURRENT_DIR=$(pwd)
-WORK_DIR="$0.runfiles/im2txt/im2txt"
-
-# Helper function to download and unpack a .zip file.
-function download_and_unzip() {
- local BASE_URL=${1}
- local FILENAME=${2}
-
- if [ ! -f ${FILENAME} ]; then
- echo "Downloading ${FILENAME} to $(pwd)"
- wget -nd -c "${BASE_URL}/${FILENAME}"
- else
- echo "Skipping download of ${FILENAME}"
- fi
- echo "Unzipping ${FILENAME}"
- ${UNZIP} ${FILENAME}
-}
-
-cd ${SCRATCH_DIR}
-
-# Download the images.
-BASE_IMAGE_URL="http://msvocds.blob.core.windows.net/coco2014"
-
-TRAIN_IMAGE_FILE="train2014.zip"
-download_and_unzip ${BASE_IMAGE_URL} ${TRAIN_IMAGE_FILE}
-TRAIN_IMAGE_DIR="${SCRATCH_DIR}/train2014"
-
-VAL_IMAGE_FILE="val2014.zip"
-download_and_unzip ${BASE_IMAGE_URL} ${VAL_IMAGE_FILE}
-VAL_IMAGE_DIR="${SCRATCH_DIR}/val2014"
-
-# Download the captions.
-BASE_CAPTIONS_URL="http://msvocds.blob.core.windows.net/annotations-1-0-3"
-CAPTIONS_FILE="captions_train-val2014.zip"
-download_and_unzip ${BASE_CAPTIONS_URL} ${CAPTIONS_FILE}
-TRAIN_CAPTIONS_FILE="${SCRATCH_DIR}/annotations/captions_train2014.json"
-VAL_CAPTIONS_FILE="${SCRATCH_DIR}/annotations/captions_val2014.json"
-
-# Build TFRecords of the image data.
-cd "${CURRENT_DIR}"
-BUILD_SCRIPT="${WORK_DIR}/build_mscoco_data"
-"${BUILD_SCRIPT}" \
- --train_image_dir="${TRAIN_IMAGE_DIR}" \
- --val_image_dir="${VAL_IMAGE_DIR}" \
- --train_captions_file="${TRAIN_CAPTIONS_FILE}" \
- --val_captions_file="${VAL_CAPTIONS_FILE}" \
- --output_dir="${OUTPUT_DIR}" \
- --word_counts_output_file="${OUTPUT_DIR}/word_counts.txt" \
diff --git a/research/im2txt/im2txt/evaluate.py b/research/im2txt/im2txt/evaluate.py
deleted file mode 100644
index 0c81a59dab56626cb2c6a19433544f4d239cbd9d..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/evaluate.py
+++ /dev/null
@@ -1,198 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Evaluate the model.
-
-This script should be run concurrently with training so that summaries show up
-in TensorBoard.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import math
-import os.path
-import time
-
-
-import numpy as np
-import tensorflow as tf
-
-from im2txt import configuration
-from im2txt import show_and_tell_model
-
-FLAGS = tf.flags.FLAGS
-
-tf.flags.DEFINE_string("input_file_pattern", "",
- "File pattern of sharded TFRecord input files.")
-tf.flags.DEFINE_string("checkpoint_dir", "",
- "Directory containing model checkpoints.")
-tf.flags.DEFINE_string("eval_dir", "", "Directory to write event logs.")
-
-tf.flags.DEFINE_integer("eval_interval_secs", 600,
- "Interval between evaluation runs.")
-tf.flags.DEFINE_integer("num_eval_examples", 10132,
- "Number of examples for evaluation.")
-
-tf.flags.DEFINE_integer("min_global_step", 5000,
- "Minimum global step to run evaluation.")
-
-tf.logging.set_verbosity(tf.logging.INFO)
-
-
-def evaluate_model(sess, model, global_step, summary_writer, summary_op):
- """Computes perplexity-per-word over the evaluation dataset.
-
- Summaries and perplexity-per-word are written out to the eval directory.
-
- Args:
- sess: Session object.
- model: Instance of ShowAndTellModel; the model to evaluate.
- global_step: Integer; global step of the model checkpoint.
- summary_writer: Instance of FileWriter.
- summary_op: Op for generating model summaries.
- """
- # Log model summaries on a single batch.
- summary_str = sess.run(summary_op)
- summary_writer.add_summary(summary_str, global_step)
-
- # Compute perplexity over the entire dataset.
- num_eval_batches = int(
- math.ceil(FLAGS.num_eval_examples / model.config.batch_size))
-
- start_time = time.time()
- sum_losses = 0.
- sum_weights = 0.
- for i in range(num_eval_batches):
- cross_entropy_losses, weights = sess.run([
- model.target_cross_entropy_losses,
- model.target_cross_entropy_loss_weights
- ])
- sum_losses += np.sum(cross_entropy_losses * weights)
- sum_weights += np.sum(weights)
- if not i % 100:
- tf.logging.info("Computed losses for %d of %d batches.", i + 1,
- num_eval_batches)
- eval_time = time.time() - start_time
-
- perplexity = math.exp(sum_losses / sum_weights)
- tf.logging.info("Perplexity = %f (%.2g sec)", perplexity, eval_time)
-
- # Log perplexity to the FileWriter.
- summary = tf.Summary()
- value = summary.value.add()
- value.simple_value = perplexity
- value.tag = "Perplexity"
- summary_writer.add_summary(summary, global_step)
-
- # Write the Events file to the eval directory.
- summary_writer.flush()
- tf.logging.info("Finished processing evaluation at global step %d.",
- global_step)
-
-
-def run_once(model, saver, summary_writer, summary_op):
- """Evaluates the latest model checkpoint.
-
- Args:
- model: Instance of ShowAndTellModel; the model to evaluate.
- saver: Instance of tf.train.Saver for restoring model Variables.
- summary_writer: Instance of FileWriter.
- summary_op: Op for generating model summaries.
- """
- model_path = tf.train.latest_checkpoint(FLAGS.checkpoint_dir)
- if not model_path:
- tf.logging.info("Skipping evaluation. No checkpoint found in: %s",
- FLAGS.checkpoint_dir)
- return
-
- with tf.Session() as sess:
- # Load model from checkpoint.
- tf.logging.info("Loading model from checkpoint: %s", model_path)
- saver.restore(sess, model_path)
- global_step = tf.train.global_step(sess, model.global_step.name)
- tf.logging.info("Successfully loaded %s at global step = %d.",
- os.path.basename(model_path), global_step)
- if global_step < FLAGS.min_global_step:
- tf.logging.info("Skipping evaluation. Global step = %d < %d", global_step,
- FLAGS.min_global_step)
- return
-
- # Start the queue runners.
- coord = tf.train.Coordinator()
- threads = tf.train.start_queue_runners(coord=coord)
-
- # Run evaluation on the latest checkpoint.
- try:
- evaluate_model(
- sess=sess,
- model=model,
- global_step=global_step,
- summary_writer=summary_writer,
- summary_op=summary_op)
- except Exception as e: # pylint: disable=broad-except
- tf.logging.error("Evaluation failed.")
- coord.request_stop(e)
-
- coord.request_stop()
- coord.join(threads, stop_grace_period_secs=10)
-
-
-def run():
- """Runs evaluation in a loop, and logs summaries to TensorBoard."""
- # Create the evaluation directory if it doesn't exist.
- eval_dir = FLAGS.eval_dir
- if not tf.gfile.IsDirectory(eval_dir):
- tf.logging.info("Creating eval directory: %s", eval_dir)
- tf.gfile.MakeDirs(eval_dir)
-
- g = tf.Graph()
- with g.as_default():
- # Build the model for evaluation.
- model_config = configuration.ModelConfig()
- model_config.input_file_pattern = FLAGS.input_file_pattern
- model = show_and_tell_model.ShowAndTellModel(model_config, mode="eval")
- model.build()
-
- # Create the Saver to restore model Variables.
- saver = tf.train.Saver()
-
- # Create the summary operation and the summary writer.
- summary_op = tf.summary.merge_all()
- summary_writer = tf.summary.FileWriter(eval_dir)
-
- g.finalize()
-
- # Run a new evaluation run every eval_interval_secs.
- while True:
- start = time.time()
- tf.logging.info("Starting evaluation at " + time.strftime(
- "%Y-%m-%d-%H:%M:%S", time.localtime()))
- run_once(model, saver, summary_writer, summary_op)
- time_to_next_eval = start + FLAGS.eval_interval_secs - time.time()
- if time_to_next_eval > 0:
- time.sleep(time_to_next_eval)
-
-
-def main(unused_argv):
- assert FLAGS.input_file_pattern, "--input_file_pattern is required"
- assert FLAGS.checkpoint_dir, "--checkpoint_dir is required"
- assert FLAGS.eval_dir, "--eval_dir is required"
- run()
-
-
-if __name__ == "__main__":
- tf.app.run()
diff --git a/research/im2txt/im2txt/inference_utils/BUILD b/research/im2txt/im2txt/inference_utils/BUILD
deleted file mode 100644
index 82a15fd3ca487e542c41ab337404f8caa63b8c63..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/inference_utils/BUILD
+++ /dev/null
@@ -1,31 +0,0 @@
-package(default_visibility = ["//im2txt:internal"])
-
-licenses(["notice"]) # Apache 2.0
-
-exports_files(["LICENSE"])
-
-py_library(
- name = "inference_wrapper_base",
- srcs = ["inference_wrapper_base.py"],
- srcs_version = "PY2AND3",
-)
-
-py_library(
- name = "vocabulary",
- srcs = ["vocabulary.py"],
- srcs_version = "PY2AND3",
-)
-
-py_library(
- name = "caption_generator",
- srcs = ["caption_generator.py"],
- srcs_version = "PY2AND3",
-)
-
-py_test(
- name = "caption_generator_test",
- srcs = ["caption_generator_test.py"],
- deps = [
- ":caption_generator",
- ],
-)
diff --git a/research/im2txt/im2txt/inference_utils/caption_generator.py b/research/im2txt/im2txt/inference_utils/caption_generator.py
deleted file mode 100644
index f158d3d2330e8f839efdad4cbc4d38811b58d826..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/inference_utils/caption_generator.py
+++ /dev/null
@@ -1,213 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Class for generating captions from an image-to-text model."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import heapq
-import math
-
-
-import numpy as np
-
-
-class Caption(object):
- """Represents a complete or partial caption."""
-
- def __init__(self, sentence, state, logprob, score, metadata=None):
- """Initializes the Caption.
-
- Args:
- sentence: List of word ids in the caption.
- state: Model state after generating the previous word.
- logprob: Log-probability of the caption.
- score: Score of the caption.
- metadata: Optional metadata associated with the partial sentence. If not
- None, a list of strings with the same length as 'sentence'.
- """
- self.sentence = sentence
- self.state = state
- self.logprob = logprob
- self.score = score
- self.metadata = metadata
-
- def __cmp__(self, other):
- """Compares Captions by score."""
- assert isinstance(other, Caption)
- if self.score == other.score:
- return 0
- elif self.score < other.score:
- return -1
- else:
- return 1
-
- # For Python 3 compatibility (__cmp__ is deprecated).
- def __lt__(self, other):
- assert isinstance(other, Caption)
- return self.score < other.score
-
- # Also for Python 3 compatibility.
- def __eq__(self, other):
- assert isinstance(other, Caption)
- return self.score == other.score
-
-
-class TopN(object):
- """Maintains the top n elements of an incrementally provided set."""
-
- def __init__(self, n):
- self._n = n
- self._data = []
-
- def size(self):
- assert self._data is not None
- return len(self._data)
-
- def push(self, x):
- """Pushes a new element."""
- assert self._data is not None
- if len(self._data) < self._n:
- heapq.heappush(self._data, x)
- else:
- heapq.heappushpop(self._data, x)
-
- def extract(self, sort=False):
- """Extracts all elements from the TopN. This is a destructive operation.
-
- The only method that can be called immediately after extract() is reset().
-
- Args:
- sort: Whether to return the elements in descending sorted order.
-
- Returns:
- A list of data; the top n elements provided to the set.
- """
- assert self._data is not None
- data = self._data
- self._data = None
- if sort:
- data.sort(reverse=True)
- return data
-
- def reset(self):
- """Returns the TopN to an empty state."""
- self._data = []
-
-
-class CaptionGenerator(object):
- """Class to generate captions from an image-to-text model."""
-
- def __init__(self,
- model,
- vocab,
- beam_size=3,
- max_caption_length=20,
- length_normalization_factor=0.0):
- """Initializes the generator.
-
- Args:
- model: Object encapsulating a trained image-to-text model. Must have
- methods feed_image() and inference_step(). For example, an instance of
- InferenceWrapperBase.
- vocab: A Vocabulary object.
- beam_size: Beam size to use when generating captions.
- max_caption_length: The maximum caption length before stopping the search.
- length_normalization_factor: If != 0, a number x such that captions are
- scored by logprob/length^x, rather than logprob. This changes the
- relative scores of captions depending on their lengths. For example, if
- x > 0 then longer captions will be favored.
- """
- self.vocab = vocab
- self.model = model
-
- self.beam_size = beam_size
- self.max_caption_length = max_caption_length
- self.length_normalization_factor = length_normalization_factor
-
- def beam_search(self, sess, encoded_image):
- """Runs beam search caption generation on a single image.
-
- Args:
- sess: TensorFlow Session object.
- encoded_image: An encoded image string.
-
- Returns:
- A list of Caption sorted by descending score.
- """
- # Feed in the image to get the initial state.
- initial_state = self.model.feed_image(sess, encoded_image)
-
- initial_beam = Caption(
- sentence=[self.vocab.start_id],
- state=initial_state[0],
- logprob=0.0,
- score=0.0,
- metadata=[""])
- partial_captions = TopN(self.beam_size)
- partial_captions.push(initial_beam)
- complete_captions = TopN(self.beam_size)
-
- # Run beam search.
- for _ in range(self.max_caption_length - 1):
- partial_captions_list = partial_captions.extract()
- partial_captions.reset()
- input_feed = np.array([c.sentence[-1] for c in partial_captions_list])
- state_feed = np.array([c.state for c in partial_captions_list])
-
- softmax, new_states, metadata = self.model.inference_step(sess,
- input_feed,
- state_feed)
-
- for i, partial_caption in enumerate(partial_captions_list):
- word_probabilities = softmax[i]
- state = new_states[i]
- # For this partial caption, get the beam_size most probable next words.
- # Sort the indexes with numpy, select the last self.beam_size
- # (3 by default) (ie, the most likely) and then reverse the sorted
- # indexes with [::-1] to sort them from higher to lower.
- most_likely_words = np.argsort(word_probabilities)[:-self.beam_size][::-1]
-
- for w in most_likely_words:
- p = word_probabilities[w]
- if p < 1e-12:
- continue # Avoid log(0).
- sentence = partial_caption.sentence + [w]
- logprob = partial_caption.logprob + math.log(p)
- score = logprob
- if metadata:
- metadata_list = partial_caption.metadata + [metadata[i]]
- else:
- metadata_list = None
- if w == self.vocab.end_id:
- if self.length_normalization_factor > 0:
- score /= len(sentence)**self.length_normalization_factor
- beam = Caption(sentence, state, logprob, score, metadata_list)
- complete_captions.push(beam)
- else:
- beam = Caption(sentence, state, logprob, score, metadata_list)
- partial_captions.push(beam)
- if partial_captions.size() == 0:
- # We have run out of partial candidates; happens when beam_size = 1.
- break
-
- # If we have no complete captions then fall back to the partial captions.
- # But never output a mixture of complete and partial captions because a
- # partial caption could have a higher score than all the complete captions.
- if not complete_captions.size():
- complete_captions = partial_captions
-
- return complete_captions.extract(sort=True)
diff --git a/research/im2txt/im2txt/inference_utils/caption_generator_test.py b/research/im2txt/im2txt/inference_utils/caption_generator_test.py
deleted file mode 100644
index bbd069313ac4ddb10a8463d166ab282b68b2e24d..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/inference_utils/caption_generator_test.py
+++ /dev/null
@@ -1,178 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Unit tests for CaptionGenerator."""
-
-import math
-
-
-
-import numpy as np
-import tensorflow as tf
-
-from im2txt.inference_utils import caption_generator
-
-
-class FakeVocab(object):
- """Fake Vocabulary for testing purposes."""
-
- def __init__(self):
- self.start_id = 0 # Word id denoting sentence start.
- self.end_id = 1 # Word id denoting sentence end.
-
-
-class FakeModel(object):
- """Fake model for testing purposes."""
-
- def __init__(self):
- # Number of words in the vocab.
- self._vocab_size = 12
-
- # Dimensionality of the nominal model state.
- self._state_size = 1
-
- # Map of previous word to the probability distribution of the next word.
- self._probabilities = {
- 0: {1: 0.1,
- 2: 0.2,
- 3: 0.3,
- 4: 0.4},
- 2: {5: 0.1,
- 6: 0.9},
- 3: {1: 0.1,
- 7: 0.4,
- 8: 0.5},
- 4: {1: 0.3,
- 9: 0.3,
- 10: 0.4},
- 5: {1: 1.0},
- 6: {1: 1.0},
- 7: {1: 1.0},
- 8: {1: 1.0},
- 9: {1: 0.5,
- 11: 0.5},
- 10: {1: 1.0},
- 11: {1: 1.0},
- }
-
- # pylint: disable=unused-argument
-
- def feed_image(self, sess, encoded_image):
- # Return a nominal model state.
- return np.zeros([1, self._state_size])
-
- def inference_step(self, sess, input_feed, state_feed):
- # Compute the matrix of softmax distributions for the next batch of words.
- batch_size = input_feed.shape[0]
- softmax_output = np.zeros([batch_size, self._vocab_size])
- for batch_index, word_id in enumerate(input_feed):
- for next_word, probability in self._probabilities[word_id].items():
- softmax_output[batch_index, next_word] = probability
-
- # Nominal state and metadata.
- new_state = np.zeros([batch_size, self._state_size])
- metadata = None
-
- return softmax_output, new_state, metadata
-
- # pylint: enable=unused-argument
-
-
-class CaptionGeneratorTest(tf.test.TestCase):
-
- def _assertExpectedCaptions(self,
- expected_captions,
- beam_size=3,
- max_caption_length=20,
- length_normalization_factor=0):
- """Tests that beam search generates the expected captions.
-
- Args:
- expected_captions: A sequence of pairs (sentence, probability), where
- sentence is a list of integer ids and probability is a float in [0, 1].
- beam_size: Parameter passed to beam_search().
- max_caption_length: Parameter passed to beam_search().
- length_normalization_factor: Parameter passed to beam_search().
- """
- expected_sentences = [c[0] for c in expected_captions]
- expected_probabilities = [c[1] for c in expected_captions]
-
- # Generate captions.
- generator = caption_generator.CaptionGenerator(
- model=FakeModel(),
- vocab=FakeVocab(),
- beam_size=beam_size,
- max_caption_length=max_caption_length,
- length_normalization_factor=length_normalization_factor)
- actual_captions = generator.beam_search(sess=None, encoded_image=None)
-
- actual_sentences = [c.sentence for c in actual_captions]
- actual_probabilities = [math.exp(c.logprob) for c in actual_captions]
-
- self.assertEqual(expected_sentences, actual_sentences)
- self.assertAllClose(expected_probabilities, actual_probabilities)
-
- def testBeamSize(self):
- # Beam size = 1.
- expected = [([0, 4, 10, 1], 0.16)]
- self._assertExpectedCaptions(expected, beam_size=1)
-
- # Beam size = 2.
- expected = [([0, 4, 10, 1], 0.16), ([0, 3, 8, 1], 0.15)]
- self._assertExpectedCaptions(expected, beam_size=2)
-
- # Beam size = 3.
- expected = [
- ([0, 2, 6, 1], 0.18), ([0, 4, 10, 1], 0.16), ([0, 3, 8, 1], 0.15)
- ]
- self._assertExpectedCaptions(expected, beam_size=3)
-
- def testMaxLength(self):
- # Max length = 1.
- expected = [([0], 1.0)]
- self._assertExpectedCaptions(expected, max_caption_length=1)
-
- # Max length = 2.
- # There are no complete sentences, so partial sentences are returned.
- expected = [([0, 4], 0.4), ([0, 3], 0.3), ([0, 2], 0.2)]
- self._assertExpectedCaptions(expected, max_caption_length=2)
-
- # Max length = 3.
- # There is at least one complete sentence, so only complete sentences are
- # returned.
- expected = [([0, 4, 1], 0.12), ([0, 3, 1], 0.03)]
- self._assertExpectedCaptions(expected, max_caption_length=3)
-
- # Max length = 4.
- expected = [
- ([0, 2, 6, 1], 0.18), ([0, 4, 10, 1], 0.16), ([0, 3, 8, 1], 0.15)
- ]
- self._assertExpectedCaptions(expected, max_caption_length=4)
-
- def testLengthNormalization(self):
- # Length normalization factor = 3.
- # The longest caption is returned first, despite having low probability,
- # because it has the highest log(probability)/length**3.
- expected = [
- ([0, 4, 9, 11, 1], 0.06),
- ([0, 2, 6, 1], 0.18),
- ([0, 4, 10, 1], 0.16),
- ([0, 3, 8, 1], 0.15),
- ]
- self._assertExpectedCaptions(
- expected, beam_size=4, length_normalization_factor=3)
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/im2txt/im2txt/inference_utils/inference_wrapper_base.py b/research/im2txt/im2txt/inference_utils/inference_wrapper_base.py
deleted file mode 100644
index e94cd6af474488e4b8175fc959e1dbe33cca18c9..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/inference_utils/inference_wrapper_base.py
+++ /dev/null
@@ -1,181 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Base wrapper class for performing inference with an image-to-text model.
-
-Subclasses must implement the following methods:
-
- build_model():
- Builds the model for inference and returns the model object.
-
- feed_image():
- Takes an encoded image and returns the initial model state, where "state"
- is a numpy array whose specifics are defined by the subclass, e.g.
- concatenated LSTM state. It's assumed that feed_image() will be called
- precisely once at the start of inference for each image. Subclasses may
- compute and/or save per-image internal context in this method.
-
- inference_step():
- Takes a batch of inputs and states at a single time-step. Returns the
- softmax output corresponding to the inputs, and the new states of the batch.
- Optionally also returns metadata about the current inference step, e.g. a
- serialized numpy array containing activations from a particular model layer.
-
-Client usage:
- 1. Build the model inference graph via build_graph_from_config() or
- build_graph_from_proto().
- 2. Call the resulting restore_fn to load the model checkpoint.
- 3. For each image in a batch of images:
- a) Call feed_image() once to get the initial state.
- b) For each step of caption generation, call inference_step().
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os.path
-
-
-import tensorflow as tf
-
-# pylint: disable=unused-argument
-
-
-class InferenceWrapperBase(object):
- """Base wrapper class for performing inference with an image-to-text model."""
-
- def __init__(self):
- pass
-
- def build_model(self, model_config):
- """Builds the model for inference.
-
- Args:
- model_config: Object containing configuration for building the model.
-
- Returns:
- model: The model object.
- """
- tf.logging.fatal("Please implement build_model in subclass")
-
- def _create_restore_fn(self, checkpoint_path, saver):
- """Creates a function that restores a model from checkpoint.
-
- Args:
- checkpoint_path: Checkpoint file or a directory containing a checkpoint
- file.
- saver: Saver for restoring variables from the checkpoint file.
-
- Returns:
- restore_fn: A function such that restore_fn(sess) loads model variables
- from the checkpoint file.
-
- Raises:
- ValueError: If checkpoint_path does not refer to a checkpoint file or a
- directory containing a checkpoint file.
- """
- if tf.gfile.IsDirectory(checkpoint_path):
- checkpoint_path = tf.train.latest_checkpoint(checkpoint_path)
- if not checkpoint_path:
- raise ValueError("No checkpoint file found in: %s" % checkpoint_path)
-
- def _restore_fn(sess):
- tf.logging.info("Loading model from checkpoint: %s", checkpoint_path)
- saver.restore(sess, checkpoint_path)
- tf.logging.info("Successfully loaded checkpoint: %s",
- os.path.basename(checkpoint_path))
-
- return _restore_fn
-
- def build_graph_from_config(self, model_config, checkpoint_path):
- """Builds the inference graph from a configuration object.
-
- Args:
- model_config: Object containing configuration for building the model.
- checkpoint_path: Checkpoint file or a directory containing a checkpoint
- file.
-
- Returns:
- restore_fn: A function such that restore_fn(sess) loads model variables
- from the checkpoint file.
- """
- tf.logging.info("Building model.")
- self.build_model(model_config)
- saver = tf.train.Saver()
-
- return self._create_restore_fn(checkpoint_path, saver)
-
- def build_graph_from_proto(self, graph_def_file, saver_def_file,
- checkpoint_path):
- """Builds the inference graph from serialized GraphDef and SaverDef protos.
-
- Args:
- graph_def_file: File containing a serialized GraphDef proto.
- saver_def_file: File containing a serialized SaverDef proto.
- checkpoint_path: Checkpoint file or a directory containing a checkpoint
- file.
-
- Returns:
- restore_fn: A function such that restore_fn(sess) loads model variables
- from the checkpoint file.
- """
- # Load the Graph.
- tf.logging.info("Loading GraphDef from file: %s", graph_def_file)
- graph_def = tf.GraphDef()
- with tf.gfile.FastGFile(graph_def_file, "rb") as f:
- graph_def.ParseFromString(f.read())
- tf.import_graph_def(graph_def, name="")
-
- # Load the Saver.
- tf.logging.info("Loading SaverDef from file: %s", saver_def_file)
- saver_def = tf.train.SaverDef()
- with tf.gfile.FastGFile(saver_def_file, "rb") as f:
- saver_def.ParseFromString(f.read())
- saver = tf.train.Saver(saver_def=saver_def)
-
- return self._create_restore_fn(checkpoint_path, saver)
-
- def feed_image(self, sess, encoded_image):
- """Feeds an image and returns the initial model state.
-
- See comments at the top of file.
-
- Args:
- sess: TensorFlow Session object.
- encoded_image: An encoded image string.
-
- Returns:
- state: A numpy array of shape [1, state_size].
- """
- tf.logging.fatal("Please implement feed_image in subclass")
-
- def inference_step(self, sess, input_feed, state_feed):
- """Runs one step of inference.
-
- Args:
- sess: TensorFlow Session object.
- input_feed: A numpy array of shape [batch_size].
- state_feed: A numpy array of shape [batch_size, state_size].
-
- Returns:
- softmax_output: A numpy array of shape [batch_size, vocab_size].
- new_state: A numpy array of shape [batch_size, state_size].
- metadata: Optional. If not None, a string containing metadata about the
- current inference step (e.g. serialized numpy array containing
- activations from a particular model layer.).
- """
- tf.logging.fatal("Please implement inference_step in subclass")
-
-# pylint: enable=unused-argument
diff --git a/research/im2txt/im2txt/inference_utils/vocabulary.py b/research/im2txt/im2txt/inference_utils/vocabulary.py
deleted file mode 100644
index ecf0ada9c2242cb32c2ea9a300d16411f5e83fab..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/inference_utils/vocabulary.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Vocabulary class for an image-to-text model."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import tensorflow as tf
-
-
-class Vocabulary(object):
- """Vocabulary class for an image-to-text model."""
-
- def __init__(self,
- vocab_file,
- start_word="",
- end_word="",
- unk_word=""):
- """Initializes the vocabulary.
-
- Args:
- vocab_file: File containing the vocabulary, where the words are the first
- whitespace-separated token on each line (other tokens are ignored) and
- the word ids are the corresponding line numbers.
- start_word: Special word denoting sentence start.
- end_word: Special word denoting sentence end.
- unk_word: Special word denoting unknown words.
- """
- if not tf.gfile.Exists(vocab_file):
- tf.logging.fatal("Vocab file %s not found.", vocab_file)
- tf.logging.info("Initializing vocabulary from file: %s", vocab_file)
-
- with tf.gfile.GFile(vocab_file, mode="r") as f:
- reverse_vocab = list(f.readlines())
- reverse_vocab = [line.split()[0] for line in reverse_vocab]
- assert start_word in reverse_vocab
- assert end_word in reverse_vocab
- if unk_word not in reverse_vocab:
- reverse_vocab.append(unk_word)
- vocab = dict([(x, y) for (y, x) in enumerate(reverse_vocab)])
-
- tf.logging.info("Created vocabulary with %d words" % len(vocab))
-
- self.vocab = vocab # vocab[word] = id
- self.reverse_vocab = reverse_vocab # reverse_vocab[id] = word
-
- # Save special word ids.
- self.start_id = vocab[start_word]
- self.end_id = vocab[end_word]
- self.unk_id = vocab[unk_word]
-
- def word_to_id(self, word):
- """Returns the integer word id of a word string."""
- if word in self.vocab:
- return self.vocab[word]
- else:
- return self.unk_id
-
- def id_to_word(self, word_id):
- """Returns the word string of an integer word id."""
- if word_id >= len(self.reverse_vocab):
- return self.reverse_vocab[self.unk_id]
- else:
- return self.reverse_vocab[word_id]
diff --git a/research/im2txt/im2txt/inference_wrapper.py b/research/im2txt/im2txt/inference_wrapper.py
deleted file mode 100644
index a047a9c8d084fd9e69c937915cea8553c2d51817..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/inference_wrapper.py
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Model wrapper class for performing inference with a ShowAndTellModel."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-
-from im2txt import show_and_tell_model
-from im2txt.inference_utils import inference_wrapper_base
-
-
-class InferenceWrapper(inference_wrapper_base.InferenceWrapperBase):
- """Model wrapper class for performing inference with a ShowAndTellModel."""
-
- def __init__(self):
- super(InferenceWrapper, self).__init__()
-
- def build_model(self, model_config):
- model = show_and_tell_model.ShowAndTellModel(model_config, mode="inference")
- model.build()
- return model
-
- def feed_image(self, sess, encoded_image):
- initial_state = sess.run(fetches="lstm/initial_state:0",
- feed_dict={"image_feed:0": encoded_image})
- return initial_state
-
- def inference_step(self, sess, input_feed, state_feed):
- softmax_output, state_output = sess.run(
- fetches=["softmax:0", "lstm/state:0"],
- feed_dict={
- "input_feed:0": input_feed,
- "lstm/state_feed:0": state_feed,
- })
- return softmax_output, state_output, None
diff --git a/research/im2txt/im2txt/ops/BUILD b/research/im2txt/im2txt/ops/BUILD
deleted file mode 100644
index 7d48bf3938c7ecfc94ac6498386e7ce214b8be92..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/ops/BUILD
+++ /dev/null
@@ -1,32 +0,0 @@
-package(default_visibility = ["//im2txt:internal"])
-
-licenses(["notice"]) # Apache 2.0
-
-exports_files(["LICENSE"])
-
-py_library(
- name = "image_processing",
- srcs = ["image_processing.py"],
- srcs_version = "PY2AND3",
-)
-
-py_library(
- name = "image_embedding",
- srcs = ["image_embedding.py"],
- srcs_version = "PY2AND3",
-)
-
-py_test(
- name = "image_embedding_test",
- size = "small",
- srcs = ["image_embedding_test.py"],
- deps = [
- ":image_embedding",
- ],
-)
-
-py_library(
- name = "inputs",
- srcs = ["inputs.py"],
- srcs_version = "PY2AND3",
-)
diff --git a/research/im2txt/im2txt/ops/image_embedding.py b/research/im2txt/im2txt/ops/image_embedding.py
deleted file mode 100644
index 58e3ddaa95fa799f245fe2a46f2e948be7d9ebf2..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/ops/image_embedding.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Image embedding ops."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import tensorflow as tf
-
-from tensorflow.contrib.slim.python.slim.nets.inception_v3 import inception_v3_base
-
-slim = tf.contrib.slim
-
-
-def inception_v3(images,
- trainable=True,
- is_training=True,
- weight_decay=0.00004,
- stddev=0.1,
- dropout_keep_prob=0.8,
- use_batch_norm=True,
- batch_norm_params=None,
- add_summaries=True,
- scope="InceptionV3"):
- """Builds an Inception V3 subgraph for image embeddings.
-
- Args:
- images: A float32 Tensor of shape [batch, height, width, channels].
- trainable: Whether the inception submodel should be trainable or not.
- is_training: Boolean indicating training mode or not.
- weight_decay: Coefficient for weight regularization.
- stddev: The standard deviation of the trunctated normal weight initializer.
- dropout_keep_prob: Dropout keep probability.
- use_batch_norm: Whether to use batch normalization.
- batch_norm_params: Parameters for batch normalization. See
- tf.contrib.layers.batch_norm for details.
- add_summaries: Whether to add activation summaries.
- scope: Optional Variable scope.
-
- Returns:
- end_points: A dictionary of activations from inception_v3 layers.
- """
- # Only consider the inception model to be in training mode if it's trainable.
- is_inception_model_training = trainable and is_training
-
- if use_batch_norm:
- # Default parameters for batch normalization.
- if not batch_norm_params:
- batch_norm_params = {
- "is_training": is_inception_model_training,
- "trainable": trainable,
- # Decay for the moving averages.
- "decay": 0.9997,
- # Epsilon to prevent 0s in variance.
- "epsilon": 0.001,
- # Collection containing the moving mean and moving variance.
- "variables_collections": {
- "beta": None,
- "gamma": None,
- "moving_mean": ["moving_vars"],
- "moving_variance": ["moving_vars"],
- }
- }
- else:
- batch_norm_params = None
-
- if trainable:
- weights_regularizer = tf.contrib.layers.l2_regularizer(weight_decay)
- else:
- weights_regularizer = None
-
- with tf.variable_scope(scope, "InceptionV3", [images]) as scope:
- with slim.arg_scope(
- [slim.conv2d, slim.fully_connected],
- weights_regularizer=weights_regularizer,
- trainable=trainable):
- with slim.arg_scope(
- [slim.conv2d],
- weights_initializer=tf.truncated_normal_initializer(stddev=stddev),
- activation_fn=tf.nn.relu,
- normalizer_fn=slim.batch_norm,
- normalizer_params=batch_norm_params):
- net, end_points = inception_v3_base(images, scope=scope)
- with tf.variable_scope("logits"):
- shape = net.get_shape()
- net = slim.avg_pool2d(net, shape[1:3], padding="VALID", scope="pool")
- net = slim.dropout(
- net,
- keep_prob=dropout_keep_prob,
- is_training=is_inception_model_training,
- scope="dropout")
- net = slim.flatten(net, scope="flatten")
-
- # Add summaries.
- if add_summaries:
- for v in end_points.values():
- tf.contrib.layers.summaries.summarize_activation(v)
-
- return net
diff --git a/research/im2txt/im2txt/ops/image_embedding_test.py b/research/im2txt/im2txt/ops/image_embedding_test.py
deleted file mode 100644
index 66324d68eee0ec9c450375c25229d80283fc909f..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/ops/image_embedding_test.py
+++ /dev/null
@@ -1,136 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests for tensorflow_models.im2txt.ops.image_embedding."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import tensorflow as tf
-
-from im2txt.ops import image_embedding
-
-
-class InceptionV3Test(tf.test.TestCase):
-
- def setUp(self):
- super(InceptionV3Test, self).setUp()
-
- batch_size = 4
- height = 299
- width = 299
- num_channels = 3
- self._images = tf.placeholder(tf.float32,
- [batch_size, height, width, num_channels])
- self._batch_size = batch_size
-
- def _countInceptionParameters(self):
- """Counts the number of parameters in the inception model at top scope."""
- counter = {}
- for v in tf.global_variables():
- name_tokens = v.op.name.split("/")
- if name_tokens[0] == "InceptionV3":
- name = "InceptionV3/" + name_tokens[1]
- num_params = v.get_shape().num_elements()
- assert num_params
- counter[name] = counter.get(name, 0) + num_params
- return counter
-
- def _verifyParameterCounts(self):
- """Verifies the number of parameters in the inception model."""
- param_counts = self._countInceptionParameters()
- expected_param_counts = {
- "InceptionV3/Conv2d_1a_3x3": 960,
- "InceptionV3/Conv2d_2a_3x3": 9312,
- "InceptionV3/Conv2d_2b_3x3": 18624,
- "InceptionV3/Conv2d_3b_1x1": 5360,
- "InceptionV3/Conv2d_4a_3x3": 138816,
- "InceptionV3/Mixed_5b": 256368,
- "InceptionV3/Mixed_5c": 277968,
- "InceptionV3/Mixed_5d": 285648,
- "InceptionV3/Mixed_6a": 1153920,
- "InceptionV3/Mixed_6b": 1298944,
- "InceptionV3/Mixed_6c": 1692736,
- "InceptionV3/Mixed_6d": 1692736,
- "InceptionV3/Mixed_6e": 2143872,
- "InceptionV3/Mixed_7a": 1699584,
- "InceptionV3/Mixed_7b": 5047872,
- "InceptionV3/Mixed_7c": 6080064,
- }
- self.assertDictEqual(expected_param_counts, param_counts)
-
- def _assertCollectionSize(self, expected_size, collection):
- actual_size = len(tf.get_collection(collection))
- if expected_size != actual_size:
- self.fail("Found %d items in collection %s (expected %d)." %
- (actual_size, collection, expected_size))
-
- def testTrainableTrueIsTrainingTrue(self):
- embeddings = image_embedding.inception_v3(
- self._images, trainable=True, is_training=True)
- self.assertEqual([self._batch_size, 2048], embeddings.get_shape().as_list())
-
- self._verifyParameterCounts()
- self._assertCollectionSize(376, tf.GraphKeys.GLOBAL_VARIABLES)
- self._assertCollectionSize(188, tf.GraphKeys.TRAINABLE_VARIABLES)
- self._assertCollectionSize(188, tf.GraphKeys.UPDATE_OPS)
- self._assertCollectionSize(94, tf.GraphKeys.REGULARIZATION_LOSSES)
- self._assertCollectionSize(0, tf.GraphKeys.LOSSES)
- self._assertCollectionSize(23, tf.GraphKeys.SUMMARIES)
-
- def testTrainableTrueIsTrainingFalse(self):
- embeddings = image_embedding.inception_v3(
- self._images, trainable=True, is_training=False)
- self.assertEqual([self._batch_size, 2048], embeddings.get_shape().as_list())
-
- self._verifyParameterCounts()
- self._assertCollectionSize(376, tf.GraphKeys.GLOBAL_VARIABLES)
- self._assertCollectionSize(188, tf.GraphKeys.TRAINABLE_VARIABLES)
- self._assertCollectionSize(0, tf.GraphKeys.UPDATE_OPS)
- self._assertCollectionSize(94, tf.GraphKeys.REGULARIZATION_LOSSES)
- self._assertCollectionSize(0, tf.GraphKeys.LOSSES)
- self._assertCollectionSize(23, tf.GraphKeys.SUMMARIES)
-
- def testTrainableFalseIsTrainingTrue(self):
- embeddings = image_embedding.inception_v3(
- self._images, trainable=False, is_training=True)
- self.assertEqual([self._batch_size, 2048], embeddings.get_shape().as_list())
-
- self._verifyParameterCounts()
- self._assertCollectionSize(376, tf.GraphKeys.GLOBAL_VARIABLES)
- self._assertCollectionSize(0, tf.GraphKeys.TRAINABLE_VARIABLES)
- self._assertCollectionSize(0, tf.GraphKeys.UPDATE_OPS)
- self._assertCollectionSize(0, tf.GraphKeys.REGULARIZATION_LOSSES)
- self._assertCollectionSize(0, tf.GraphKeys.LOSSES)
- self._assertCollectionSize(23, tf.GraphKeys.SUMMARIES)
-
- def testTrainableFalseIsTrainingFalse(self):
- embeddings = image_embedding.inception_v3(
- self._images, trainable=False, is_training=False)
- self.assertEqual([self._batch_size, 2048], embeddings.get_shape().as_list())
-
- self._verifyParameterCounts()
- self._assertCollectionSize(376, tf.GraphKeys.GLOBAL_VARIABLES)
- self._assertCollectionSize(0, tf.GraphKeys.TRAINABLE_VARIABLES)
- self._assertCollectionSize(0, tf.GraphKeys.UPDATE_OPS)
- self._assertCollectionSize(0, tf.GraphKeys.REGULARIZATION_LOSSES)
- self._assertCollectionSize(0, tf.GraphKeys.LOSSES)
- self._assertCollectionSize(23, tf.GraphKeys.SUMMARIES)
-
-
-if __name__ == "__main__":
- tf.test.main()
diff --git a/research/im2txt/im2txt/ops/image_processing.py b/research/im2txt/im2txt/ops/image_processing.py
deleted file mode 100644
index 6a7545547d5507febaabebf642ee81b6f94319f6..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/ops/image_processing.py
+++ /dev/null
@@ -1,133 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Helper functions for image preprocessing."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import tensorflow as tf
-
-
-def distort_image(image, thread_id):
- """Perform random distortions on an image.
-
- Args:
- image: A float32 Tensor of shape [height, width, 3] with values in [0, 1).
- thread_id: Preprocessing thread id used to select the ordering of color
- distortions. There should be a multiple of 2 preprocessing threads.
-
- Returns:
- distorted_image: A float32 Tensor of shape [height, width, 3] with values in
- [0, 1].
- """
- # Randomly flip horizontally.
- with tf.name_scope("flip_horizontal", values=[image]):
- image = tf.image.random_flip_left_right(image)
-
- # Randomly distort the colors based on thread id.
- color_ordering = thread_id % 2
- with tf.name_scope("distort_color", values=[image]):
- if color_ordering == 0:
- image = tf.image.random_brightness(image, max_delta=32. / 255.)
- image = tf.image.random_saturation(image, lower=0.5, upper=1.5)
- image = tf.image.random_hue(image, max_delta=0.032)
- image = tf.image.random_contrast(image, lower=0.5, upper=1.5)
- elif color_ordering == 1:
- image = tf.image.random_brightness(image, max_delta=32. / 255.)
- image = tf.image.random_contrast(image, lower=0.5, upper=1.5)
- image = tf.image.random_saturation(image, lower=0.5, upper=1.5)
- image = tf.image.random_hue(image, max_delta=0.032)
-
- # The random_* ops do not necessarily clamp.
- image = tf.clip_by_value(image, 0.0, 1.0)
-
- return image
-
-
-def process_image(encoded_image,
- is_training,
- height,
- width,
- resize_height=346,
- resize_width=346,
- thread_id=0,
- image_format="jpeg"):
- """Decode an image, resize and apply random distortions.
-
- In training, images are distorted slightly differently depending on thread_id.
-
- Args:
- encoded_image: String Tensor containing the image.
- is_training: Boolean; whether preprocessing for training or eval.
- height: Height of the output image.
- width: Width of the output image.
- resize_height: If > 0, resize height before crop to final dimensions.
- resize_width: If > 0, resize width before crop to final dimensions.
- thread_id: Preprocessing thread id used to select the ordering of color
- distortions. There should be a multiple of 2 preprocessing threads.
- image_format: "jpeg" or "png".
-
- Returns:
- A float32 Tensor of shape [height, width, 3] with values in [-1, 1].
-
- Raises:
- ValueError: If image_format is invalid.
- """
- # Helper function to log an image summary to the visualizer. Summaries are
- # only logged in thread 0.
- def image_summary(name, image):
- if not thread_id:
- tf.summary.image(name, tf.expand_dims(image, 0))
-
- # Decode image into a float32 Tensor of shape [?, ?, 3] with values in [0, 1).
- with tf.name_scope("decode", values=[encoded_image]):
- if image_format == "jpeg":
- image = tf.image.decode_jpeg(encoded_image, channels=3)
- elif image_format == "png":
- image = tf.image.decode_png(encoded_image, channels=3)
- else:
- raise ValueError("Invalid image format: %s" % image_format)
- image = tf.image.convert_image_dtype(image, dtype=tf.float32)
- image_summary("original_image", image)
-
- # Resize image.
- assert (resize_height > 0) == (resize_width > 0)
- if resize_height:
- image = tf.image.resize_images(image,
- size=[resize_height, resize_width],
- method=tf.image.ResizeMethod.BILINEAR)
-
- # Crop to final dimensions.
- if is_training:
- image = tf.random_crop(image, [height, width, 3])
- else:
- # Central crop, assuming resize_height > height, resize_width > width.
- image = tf.image.resize_image_with_crop_or_pad(image, height, width)
-
- image_summary("resized_image", image)
-
- # Randomly distort the image.
- if is_training:
- image = distort_image(image, thread_id)
-
- image_summary("final_image", image)
-
- # Rescale to [-1,1] instead of [0, 1]
- image = tf.subtract(image, 0.5)
- image = tf.multiply(image, 2.0)
- return image
diff --git a/research/im2txt/im2txt/ops/inputs.py b/research/im2txt/im2txt/ops/inputs.py
deleted file mode 100644
index 5dc90c0ce5dfd5c30fe0e0e543999bb15cc13a8c..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/ops/inputs.py
+++ /dev/null
@@ -1,204 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Input ops."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import tensorflow as tf
-
-
-def parse_sequence_example(serialized, image_feature, caption_feature):
- """Parses a tensorflow.SequenceExample into an image and caption.
-
- Args:
- serialized: A scalar string Tensor; a single serialized SequenceExample.
- image_feature: Name of SequenceExample context feature containing image
- data.
- caption_feature: Name of SequenceExample feature list containing integer
- captions.
-
- Returns:
- encoded_image: A scalar string Tensor containing a JPEG encoded image.
- caption: A 1-D uint64 Tensor with dynamically specified length.
- """
- context, sequence = tf.parse_single_sequence_example(
- serialized,
- context_features={
- image_feature: tf.FixedLenFeature([], dtype=tf.string)
- },
- sequence_features={
- caption_feature: tf.FixedLenSequenceFeature([], dtype=tf.int64),
- })
-
- encoded_image = context[image_feature]
- caption = sequence[caption_feature]
- return encoded_image, caption
-
-
-def prefetch_input_data(reader,
- file_pattern,
- is_training,
- batch_size,
- values_per_shard,
- input_queue_capacity_factor=16,
- num_reader_threads=1,
- shard_queue_name="filename_queue",
- value_queue_name="input_queue"):
- """Prefetches string values from disk into an input queue.
-
- In training the capacity of the queue is important because a larger queue
- means better mixing of training examples between shards. The minimum number of
- values kept in the queue is values_per_shard * input_queue_capacity_factor,
- where input_queue_memory factor should be chosen to trade-off better mixing
- with memory usage.
-
- Args:
- reader: Instance of tf.ReaderBase.
- file_pattern: Comma-separated list of file patterns (e.g.
- /tmp/train_data-?????-of-00100).
- is_training: Boolean; whether prefetching for training or eval.
- batch_size: Model batch size used to determine queue capacity.
- values_per_shard: Approximate number of values per shard.
- input_queue_capacity_factor: Minimum number of values to keep in the queue
- in multiples of values_per_shard. See comments above.
- num_reader_threads: Number of reader threads to fill the queue.
- shard_queue_name: Name for the shards filename queue.
- value_queue_name: Name for the values input queue.
-
- Returns:
- A Queue containing prefetched string values.
- """
- data_files = []
- for pattern in file_pattern.split(","):
- data_files.extend(tf.gfile.Glob(pattern))
- if not data_files:
- tf.logging.fatal("Found no input files matching %s", file_pattern)
- else:
- tf.logging.info("Prefetching values from %d files matching %s",
- len(data_files), file_pattern)
-
- if is_training:
- filename_queue = tf.train.string_input_producer(
- data_files, shuffle=True, capacity=16, name=shard_queue_name)
- min_queue_examples = values_per_shard * input_queue_capacity_factor
- capacity = min_queue_examples + 100 * batch_size
- values_queue = tf.RandomShuffleQueue(
- capacity=capacity,
- min_after_dequeue=min_queue_examples,
- dtypes=[tf.string],
- name="random_" + value_queue_name)
- else:
- filename_queue = tf.train.string_input_producer(
- data_files, shuffle=False, capacity=1, name=shard_queue_name)
- capacity = values_per_shard + 3 * batch_size
- values_queue = tf.FIFOQueue(
- capacity=capacity, dtypes=[tf.string], name="fifo_" + value_queue_name)
-
- enqueue_ops = []
- for _ in range(num_reader_threads):
- _, value = reader.read(filename_queue)
- enqueue_ops.append(values_queue.enqueue([value]))
- tf.train.queue_runner.add_queue_runner(tf.train.queue_runner.QueueRunner(
- values_queue, enqueue_ops))
- tf.summary.scalar(
- "queue/%s/fraction_of_%d_full" % (values_queue.name, capacity),
- tf.cast(values_queue.size(), tf.float32) * (1. / capacity))
-
- return values_queue
-
-
-def batch_with_dynamic_pad(images_and_captions,
- batch_size,
- queue_capacity,
- add_summaries=True):
- """Batches input images and captions.
-
- This function splits the caption into an input sequence and a target sequence,
- where the target sequence is the input sequence right-shifted by 1. Input and
- target sequences are batched and padded up to the maximum length of sequences
- in the batch. A mask is created to distinguish real words from padding words.
-
- Example:
- Actual captions in the batch ('-' denotes padded character):
- [
- [ 1 2 3 4 5 ],
- [ 1 2 3 4 - ],
- [ 1 2 3 - - ],
- ]
-
- input_seqs:
- [
- [ 1 2 3 4 ],
- [ 1 2 3 - ],
- [ 1 2 - - ],
- ]
-
- target_seqs:
- [
- [ 2 3 4 5 ],
- [ 2 3 4 - ],
- [ 2 3 - - ],
- ]
-
- mask:
- [
- [ 1 1 1 1 ],
- [ 1 1 1 0 ],
- [ 1 1 0 0 ],
- ]
-
- Args:
- images_and_captions: A list of pairs [image, caption], where image is a
- Tensor of shape [height, width, channels] and caption is a 1-D Tensor of
- any length. Each pair will be processed and added to the queue in a
- separate thread.
- batch_size: Batch size.
- queue_capacity: Queue capacity.
- add_summaries: If true, add caption length summaries.
-
- Returns:
- images: A Tensor of shape [batch_size, height, width, channels].
- input_seqs: An int32 Tensor of shape [batch_size, padded_length].
- target_seqs: An int32 Tensor of shape [batch_size, padded_length].
- mask: An int32 0/1 Tensor of shape [batch_size, padded_length].
- """
- enqueue_list = []
- for image, caption in images_and_captions:
- caption_length = tf.shape(caption)[0]
- input_length = tf.expand_dims(tf.subtract(caption_length, 1), 0)
-
- input_seq = tf.slice(caption, [0], input_length)
- target_seq = tf.slice(caption, [1], input_length)
- indicator = tf.ones(input_length, dtype=tf.int32)
- enqueue_list.append([image, input_seq, target_seq, indicator])
-
- images, input_seqs, target_seqs, mask = tf.train.batch_join(
- enqueue_list,
- batch_size=batch_size,
- capacity=queue_capacity,
- dynamic_pad=True,
- name="batch_and_pad")
-
- if add_summaries:
- lengths = tf.add(tf.reduce_sum(mask, 1), 1)
- tf.summary.scalar("caption_length/batch_min", tf.reduce_min(lengths))
- tf.summary.scalar("caption_length/batch_max", tf.reduce_max(lengths))
- tf.summary.scalar("caption_length/batch_mean", tf.reduce_mean(lengths))
-
- return images, input_seqs, target_seqs, mask
diff --git a/research/im2txt/im2txt/run_inference.py b/research/im2txt/im2txt/run_inference.py
deleted file mode 100644
index 9848522df162e52394ee8349dab1f5220aeb88f6..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/run_inference.py
+++ /dev/null
@@ -1,85 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-r"""Generate captions for images using default beam search parameters."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import math
-import os
-
-
-import tensorflow as tf
-
-from im2txt import configuration
-from im2txt import inference_wrapper
-from im2txt.inference_utils import caption_generator
-from im2txt.inference_utils import vocabulary
-
-FLAGS = tf.flags.FLAGS
-
-tf.flags.DEFINE_string("checkpoint_path", "",
- "Model checkpoint file or directory containing a "
- "model checkpoint file.")
-tf.flags.DEFINE_string("vocab_file", "", "Text file containing the vocabulary.")
-tf.flags.DEFINE_string("input_files", "",
- "File pattern or comma-separated list of file patterns "
- "of image files.")
-
-tf.logging.set_verbosity(tf.logging.INFO)
-
-
-def main(_):
- # Build the inference graph.
- g = tf.Graph()
- with g.as_default():
- model = inference_wrapper.InferenceWrapper()
- restore_fn = model.build_graph_from_config(configuration.ModelConfig(),
- FLAGS.checkpoint_path)
- g.finalize()
-
- # Create the vocabulary.
- vocab = vocabulary.Vocabulary(FLAGS.vocab_file)
-
- filenames = []
- for file_pattern in FLAGS.input_files.split(","):
- filenames.extend(tf.gfile.Glob(file_pattern))
- tf.logging.info("Running caption generation on %d files matching %s",
- len(filenames), FLAGS.input_files)
-
- with tf.Session(graph=g) as sess:
- # Load the model from checkpoint.
- restore_fn(sess)
-
- # Prepare the caption generator. Here we are implicitly using the default
- # beam search parameters. See caption_generator.py for a description of the
- # available beam search parameters.
- generator = caption_generator.CaptionGenerator(model, vocab)
-
- for filename in filenames:
- with tf.gfile.GFile(filename, "rb") as f:
- image = f.read()
- captions = generator.beam_search(sess, image)
- print("Captions for image %s:" % os.path.basename(filename))
- for i, caption in enumerate(captions):
- # Ignore begin and end words.
- sentence = [vocab.id_to_word(w) for w in caption.sentence[1:-1]]
- sentence = " ".join(sentence)
- print(" %d) %s (p=%f)" % (i, sentence, math.exp(caption.logprob)))
-
-
-if __name__ == "__main__":
- tf.app.run()
diff --git a/research/im2txt/im2txt/show_and_tell_model.py b/research/im2txt/im2txt/show_and_tell_model.py
deleted file mode 100644
index 0ac29e7fdb80fbefe3594eabc972648a3fb32312..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/show_and_tell_model.py
+++ /dev/null
@@ -1,358 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Image-to-text implementation based on http://arxiv.org/abs/1411.4555.
-
-"Show and Tell: A Neural Image Caption Generator"
-Oriol Vinyals, Alexander Toshev, Samy Bengio, Dumitru Erhan
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import tensorflow as tf
-
-from im2txt.ops import image_embedding
-from im2txt.ops import image_processing
-from im2txt.ops import inputs as input_ops
-
-
-class ShowAndTellModel(object):
- """Image-to-text implementation based on http://arxiv.org/abs/1411.4555.
-
- "Show and Tell: A Neural Image Caption Generator"
- Oriol Vinyals, Alexander Toshev, Samy Bengio, Dumitru Erhan
- """
-
- def __init__(self, config, mode, train_inception=False):
- """Basic setup.
-
- Args:
- config: Object containing configuration parameters.
- mode: "train", "eval" or "inference".
- train_inception: Whether the inception submodel variables are trainable.
- """
- assert mode in ["train", "eval", "inference"]
- self.config = config
- self.mode = mode
- self.train_inception = train_inception
-
- # Reader for the input data.
- self.reader = tf.TFRecordReader()
-
- # To match the "Show and Tell" paper we initialize all variables with a
- # random uniform initializer.
- self.initializer = tf.random_uniform_initializer(
- minval=-self.config.initializer_scale,
- maxval=self.config.initializer_scale)
-
- # A float32 Tensor with shape [batch_size, height, width, channels].
- self.images = None
-
- # An int32 Tensor with shape [batch_size, padded_length].
- self.input_seqs = None
-
- # An int32 Tensor with shape [batch_size, padded_length].
- self.target_seqs = None
-
- # An int32 0/1 Tensor with shape [batch_size, padded_length].
- self.input_mask = None
-
- # A float32 Tensor with shape [batch_size, embedding_size].
- self.image_embeddings = None
-
- # A float32 Tensor with shape [batch_size, padded_length, embedding_size].
- self.seq_embeddings = None
-
- # A float32 scalar Tensor; the total loss for the trainer to optimize.
- self.total_loss = None
-
- # A float32 Tensor with shape [batch_size * padded_length].
- self.target_cross_entropy_losses = None
-
- # A float32 Tensor with shape [batch_size * padded_length].
- self.target_cross_entropy_loss_weights = None
-
- # Collection of variables from the inception submodel.
- self.inception_variables = []
-
- # Function to restore the inception submodel from checkpoint.
- self.init_fn = None
-
- # Global step Tensor.
- self.global_step = None
-
- def is_training(self):
- """Returns true if the model is built for training mode."""
- return self.mode == "train"
-
- def process_image(self, encoded_image, thread_id=0):
- """Decodes and processes an image string.
-
- Args:
- encoded_image: A scalar string Tensor; the encoded image.
- thread_id: Preprocessing thread id used to select the ordering of color
- distortions.
-
- Returns:
- A float32 Tensor of shape [height, width, 3]; the processed image.
- """
- return image_processing.process_image(encoded_image,
- is_training=self.is_training(),
- height=self.config.image_height,
- width=self.config.image_width,
- thread_id=thread_id,
- image_format=self.config.image_format)
-
- def build_inputs(self):
- """Input prefetching, preprocessing and batching.
-
- Outputs:
- self.images
- self.input_seqs
- self.target_seqs (training and eval only)
- self.input_mask (training and eval only)
- """
- if self.mode == "inference":
- # In inference mode, images and inputs are fed via placeholders.
- image_feed = tf.placeholder(dtype=tf.string, shape=[], name="image_feed")
- input_feed = tf.placeholder(dtype=tf.int64,
- shape=[None], # batch_size
- name="input_feed")
-
- # Process image and insert batch dimensions.
- images = tf.expand_dims(self.process_image(image_feed), 0)
- input_seqs = tf.expand_dims(input_feed, 1)
-
- # No target sequences or input mask in inference mode.
- target_seqs = None
- input_mask = None
- else:
- # Prefetch serialized SequenceExample protos.
- input_queue = input_ops.prefetch_input_data(
- self.reader,
- self.config.input_file_pattern,
- is_training=self.is_training(),
- batch_size=self.config.batch_size,
- values_per_shard=self.config.values_per_input_shard,
- input_queue_capacity_factor=self.config.input_queue_capacity_factor,
- num_reader_threads=self.config.num_input_reader_threads)
-
- # Image processing and random distortion. Split across multiple threads
- # with each thread applying a slightly different distortion.
- assert self.config.num_preprocess_threads % 2 == 0
- images_and_captions = []
- for thread_id in range(self.config.num_preprocess_threads):
- serialized_sequence_example = input_queue.dequeue()
- encoded_image, caption = input_ops.parse_sequence_example(
- serialized_sequence_example,
- image_feature=self.config.image_feature_name,
- caption_feature=self.config.caption_feature_name)
- image = self.process_image(encoded_image, thread_id=thread_id)
- images_and_captions.append([image, caption])
-
- # Batch inputs.
- queue_capacity = (2 * self.config.num_preprocess_threads *
- self.config.batch_size)
- images, input_seqs, target_seqs, input_mask = (
- input_ops.batch_with_dynamic_pad(images_and_captions,
- batch_size=self.config.batch_size,
- queue_capacity=queue_capacity))
-
- self.images = images
- self.input_seqs = input_seqs
- self.target_seqs = target_seqs
- self.input_mask = input_mask
-
- def build_image_embeddings(self):
- """Builds the image model subgraph and generates image embeddings.
-
- Inputs:
- self.images
-
- Outputs:
- self.image_embeddings
- """
- inception_output = image_embedding.inception_v3(
- self.images,
- trainable=self.train_inception,
- is_training=self.is_training())
- self.inception_variables = tf.get_collection(
- tf.GraphKeys.GLOBAL_VARIABLES, scope="InceptionV3")
-
- # Map inception output into embedding space.
- with tf.variable_scope("image_embedding") as scope:
- image_embeddings = tf.contrib.layers.fully_connected(
- inputs=inception_output,
- num_outputs=self.config.embedding_size,
- activation_fn=None,
- weights_initializer=self.initializer,
- biases_initializer=None,
- scope=scope)
-
- # Save the embedding size in the graph.
- tf.constant(self.config.embedding_size, name="embedding_size")
-
- self.image_embeddings = image_embeddings
-
- def build_seq_embeddings(self):
- """Builds the input sequence embeddings.
-
- Inputs:
- self.input_seqs
-
- Outputs:
- self.seq_embeddings
- """
- with tf.variable_scope("seq_embedding"), tf.device("/cpu:0"):
- embedding_map = tf.get_variable(
- name="map",
- shape=[self.config.vocab_size, self.config.embedding_size],
- initializer=self.initializer)
- seq_embeddings = tf.nn.embedding_lookup(embedding_map, self.input_seqs)
-
- self.seq_embeddings = seq_embeddings
-
- def build_model(self):
- """Builds the model.
-
- Inputs:
- self.image_embeddings
- self.seq_embeddings
- self.target_seqs (training and eval only)
- self.input_mask (training and eval only)
-
- Outputs:
- self.total_loss (training and eval only)
- self.target_cross_entropy_losses (training and eval only)
- self.target_cross_entropy_loss_weights (training and eval only)
- """
- # This LSTM cell has biases and outputs tanh(new_c) * sigmoid(o), but the
- # modified LSTM in the "Show and Tell" paper has no biases and outputs
- # new_c * sigmoid(o).
- lstm_cell = tf.contrib.rnn.BasicLSTMCell(
- num_units=self.config.num_lstm_units, state_is_tuple=True)
- if self.mode == "train":
- lstm_cell = tf.contrib.rnn.DropoutWrapper(
- lstm_cell,
- input_keep_prob=self.config.lstm_dropout_keep_prob,
- output_keep_prob=self.config.lstm_dropout_keep_prob)
-
- with tf.variable_scope("lstm", initializer=self.initializer) as lstm_scope:
- # Feed the image embeddings to set the initial LSTM state.
- zero_state = lstm_cell.zero_state(
- batch_size=self.image_embeddings.get_shape()[0], dtype=tf.float32)
- _, initial_state = lstm_cell(self.image_embeddings, zero_state)
-
- # Allow the LSTM variables to be reused.
- lstm_scope.reuse_variables()
-
- if self.mode == "inference":
- # In inference mode, use concatenated states for convenient feeding and
- # fetching.
- tf.concat(axis=1, values=initial_state, name="initial_state")
-
- # Placeholder for feeding a batch of concatenated states.
- state_feed = tf.placeholder(dtype=tf.float32,
- shape=[None, sum(lstm_cell.state_size)],
- name="state_feed")
- state_tuple = tf.split(value=state_feed, num_or_size_splits=2, axis=1)
-
- # Run a single LSTM step.
- lstm_outputs, state_tuple = lstm_cell(
- inputs=tf.squeeze(self.seq_embeddings, axis=[1]),
- state=state_tuple)
-
- # Concatentate the resulting state.
- tf.concat(axis=1, values=state_tuple, name="state")
- else:
- # Run the batch of sequence embeddings through the LSTM.
- sequence_length = tf.reduce_sum(self.input_mask, 1)
- lstm_outputs, _ = tf.nn.dynamic_rnn(cell=lstm_cell,
- inputs=self.seq_embeddings,
- sequence_length=sequence_length,
- initial_state=initial_state,
- dtype=tf.float32,
- scope=lstm_scope)
-
- # Stack batches vertically.
- lstm_outputs = tf.reshape(lstm_outputs, [-1, lstm_cell.output_size])
-
- with tf.variable_scope("logits") as logits_scope:
- logits = tf.contrib.layers.fully_connected(
- inputs=lstm_outputs,
- num_outputs=self.config.vocab_size,
- activation_fn=None,
- weights_initializer=self.initializer,
- scope=logits_scope)
-
- if self.mode == "inference":
- tf.nn.softmax(logits, name="softmax")
- else:
- targets = tf.reshape(self.target_seqs, [-1])
- weights = tf.to_float(tf.reshape(self.input_mask, [-1]))
-
- # Compute losses.
- losses = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=targets,
- logits=logits)
- batch_loss = tf.div(tf.reduce_sum(tf.multiply(losses, weights)),
- tf.reduce_sum(weights),
- name="batch_loss")
- tf.losses.add_loss(batch_loss)
- total_loss = tf.losses.get_total_loss()
-
- # Add summaries.
- tf.summary.scalar("losses/batch_loss", batch_loss)
- tf.summary.scalar("losses/total_loss", total_loss)
- for var in tf.trainable_variables():
- tf.summary.histogram("parameters/" + var.op.name, var)
-
- self.total_loss = total_loss
- self.target_cross_entropy_losses = losses # Used in evaluation.
- self.target_cross_entropy_loss_weights = weights # Used in evaluation.
-
- def setup_inception_initializer(self):
- """Sets up the function to restore inception variables from checkpoint."""
- if self.mode != "inference":
- # Restore inception variables only.
- saver = tf.train.Saver(self.inception_variables)
-
- def restore_fn(sess):
- tf.logging.info("Restoring Inception variables from checkpoint file %s",
- self.config.inception_checkpoint_file)
- saver.restore(sess, self.config.inception_checkpoint_file)
-
- self.init_fn = restore_fn
-
- def setup_global_step(self):
- """Sets up the global step Tensor."""
- global_step = tf.Variable(
- initial_value=0,
- name="global_step",
- trainable=False,
- collections=[tf.GraphKeys.GLOBAL_STEP, tf.GraphKeys.GLOBAL_VARIABLES])
-
- self.global_step = global_step
-
- def build(self):
- """Creates all ops for training and evaluation."""
- self.build_inputs()
- self.build_image_embeddings()
- self.build_seq_embeddings()
- self.build_model()
- self.setup_inception_initializer()
- self.setup_global_step()
diff --git a/research/im2txt/im2txt/show_and_tell_model_test.py b/research/im2txt/im2txt/show_and_tell_model_test.py
deleted file mode 100644
index 0bdfb6e1a3ae3c15bd1c8daf005fe2542436ca8e..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/show_and_tell_model_test.py
+++ /dev/null
@@ -1,200 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests for tensorflow_models.im2txt.show_and_tell_model."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import numpy as np
-import tensorflow as tf
-
-from im2txt import configuration
-from im2txt import show_and_tell_model
-
-
-class ShowAndTellModel(show_and_tell_model.ShowAndTellModel):
- """Subclass of ShowAndTellModel without the disk I/O."""
-
- def build_inputs(self):
- if self.mode == "inference":
- # Inference mode doesn't read from disk, so defer to parent.
- return super(ShowAndTellModel, self).build_inputs()
- else:
- # Replace disk I/O with random Tensors.
- self.images = tf.random_uniform(
- shape=[self.config.batch_size, self.config.image_height,
- self.config.image_width, 3],
- minval=-1,
- maxval=1)
- self.input_seqs = tf.random_uniform(
- [self.config.batch_size, 15],
- minval=0,
- maxval=self.config.vocab_size,
- dtype=tf.int64)
- self.target_seqs = tf.random_uniform(
- [self.config.batch_size, 15],
- minval=0,
- maxval=self.config.vocab_size,
- dtype=tf.int64)
- self.input_mask = tf.ones_like(self.input_seqs)
-
-
-class ShowAndTellModelTest(tf.test.TestCase):
-
- def setUp(self):
- super(ShowAndTellModelTest, self).setUp()
- self._model_config = configuration.ModelConfig()
-
- def _countModelParameters(self):
- """Counts the number of parameters in the model at top level scope."""
- counter = {}
- for v in tf.global_variables():
- name = v.op.name.split("/")[0]
- num_params = v.get_shape().num_elements()
- assert num_params
- counter[name] = counter.get(name, 0) + num_params
- return counter
-
- def _checkModelParameters(self):
- """Verifies the number of parameters in the model."""
- param_counts = self._countModelParameters()
- expected_param_counts = {
- "InceptionV3": 21802784,
- # inception_output_size * embedding_size
- "image_embedding": 1048576,
- # vocab_size * embedding_size
- "seq_embedding": 6144000,
- # (embedding_size + num_lstm_units + 1) * 4 * num_lstm_units
- "lstm": 2099200,
- # (num_lstm_units + 1) * vocab_size
- "logits": 6156000,
- "global_step": 1,
- }
- self.assertDictEqual(expected_param_counts, param_counts)
-
- def _checkOutputs(self, expected_shapes, feed_dict=None):
- """Verifies that the model produces expected outputs.
-
- Args:
- expected_shapes: A dict mapping Tensor or Tensor name to expected output
- shape.
- feed_dict: Values of Tensors to feed into Session.run().
- """
- fetches = expected_shapes.keys()
-
- with self.test_session() as sess:
- sess.run(tf.global_variables_initializer())
- outputs = sess.run(fetches, feed_dict)
-
- for index, output in enumerate(outputs):
- tensor = fetches[index]
- expected = expected_shapes[tensor]
- actual = output.shape
- if expected != actual:
- self.fail("Tensor %s has shape %s (expected %s)." %
- (tensor, actual, expected))
-
- def testBuildForTraining(self):
- model = ShowAndTellModel(self._model_config, mode="train")
- model.build()
-
- self._checkModelParameters()
-
- expected_shapes = {
- # [batch_size, image_height, image_width, 3]
- model.images: (32, 299, 299, 3),
- # [batch_size, sequence_length]
- model.input_seqs: (32, 15),
- # [batch_size, sequence_length]
- model.target_seqs: (32, 15),
- # [batch_size, sequence_length]
- model.input_mask: (32, 15),
- # [batch_size, embedding_size]
- model.image_embeddings: (32, 512),
- # [batch_size, sequence_length, embedding_size]
- model.seq_embeddings: (32, 15, 512),
- # Scalar
- model.total_loss: (),
- # [batch_size * sequence_length]
- model.target_cross_entropy_losses: (480,),
- # [batch_size * sequence_length]
- model.target_cross_entropy_loss_weights: (480,),
- }
- self._checkOutputs(expected_shapes)
-
- def testBuildForEval(self):
- model = ShowAndTellModel(self._model_config, mode="eval")
- model.build()
-
- self._checkModelParameters()
-
- expected_shapes = {
- # [batch_size, image_height, image_width, 3]
- model.images: (32, 299, 299, 3),
- # [batch_size, sequence_length]
- model.input_seqs: (32, 15),
- # [batch_size, sequence_length]
- model.target_seqs: (32, 15),
- # [batch_size, sequence_length]
- model.input_mask: (32, 15),
- # [batch_size, embedding_size]
- model.image_embeddings: (32, 512),
- # [batch_size, sequence_length, embedding_size]
- model.seq_embeddings: (32, 15, 512),
- # Scalar
- model.total_loss: (),
- # [batch_size * sequence_length]
- model.target_cross_entropy_losses: (480,),
- # [batch_size * sequence_length]
- model.target_cross_entropy_loss_weights: (480,),
- }
- self._checkOutputs(expected_shapes)
-
- def testBuildForInference(self):
- model = ShowAndTellModel(self._model_config, mode="inference")
- model.build()
-
- self._checkModelParameters()
-
- # Test feeding an image to get the initial LSTM state.
- images_feed = np.random.rand(1, 299, 299, 3)
- feed_dict = {model.images: images_feed}
- expected_shapes = {
- # [batch_size, embedding_size]
- model.image_embeddings: (1, 512),
- # [batch_size, 2 * num_lstm_units]
- "lstm/initial_state:0": (1, 1024),
- }
- self._checkOutputs(expected_shapes, feed_dict)
-
- # Test feeding a batch of inputs and LSTM states to get softmax output and
- # LSTM states.
- input_feed = np.random.randint(0, 10, size=3)
- state_feed = np.random.rand(3, 1024)
- feed_dict = {"input_feed:0": input_feed, "lstm/state_feed:0": state_feed}
- expected_shapes = {
- # [batch_size, 2 * num_lstm_units]
- "lstm/state:0": (3, 1024),
- # [batch_size, vocab_size]
- "softmax:0": (3, 12000),
- }
- self._checkOutputs(expected_shapes, feed_dict)
-
-
-if __name__ == "__main__":
- tf.test.main()
diff --git a/research/im2txt/im2txt/train.py b/research/im2txt/im2txt/train.py
deleted file mode 100644
index db602735ba11e7f540a4e985333d8a457512c977..0000000000000000000000000000000000000000
--- a/research/im2txt/im2txt/train.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Train the model."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import tensorflow as tf
-
-from im2txt import configuration
-from im2txt import show_and_tell_model
-
-FLAGS = tf.app.flags.FLAGS
-
-tf.flags.DEFINE_string("input_file_pattern", "",
- "File pattern of sharded TFRecord input files.")
-tf.flags.DEFINE_string("inception_checkpoint_file", "",
- "Path to a pretrained inception_v3 model.")
-tf.flags.DEFINE_string("train_dir", "",
- "Directory for saving and loading model checkpoints.")
-tf.flags.DEFINE_boolean("train_inception", False,
- "Whether to train inception submodel variables.")
-tf.flags.DEFINE_integer("number_of_steps", 1000000, "Number of training steps.")
-tf.flags.DEFINE_integer("log_every_n_steps", 1,
- "Frequency at which loss and global step are logged.")
-
-tf.logging.set_verbosity(tf.logging.INFO)
-
-
-def main(unused_argv):
- assert FLAGS.input_file_pattern, "--input_file_pattern is required"
- assert FLAGS.train_dir, "--train_dir is required"
-
- model_config = configuration.ModelConfig()
- model_config.input_file_pattern = FLAGS.input_file_pattern
- model_config.inception_checkpoint_file = FLAGS.inception_checkpoint_file
- training_config = configuration.TrainingConfig()
-
- # Create training directory.
- train_dir = FLAGS.train_dir
- if not tf.gfile.IsDirectory(train_dir):
- tf.logging.info("Creating training directory: %s", train_dir)
- tf.gfile.MakeDirs(train_dir)
-
- # Build the TensorFlow graph.
- g = tf.Graph()
- with g.as_default():
- # Build the model.
- model = show_and_tell_model.ShowAndTellModel(
- model_config, mode="train", train_inception=FLAGS.train_inception)
- model.build()
-
- # Set up the learning rate.
- learning_rate_decay_fn = None
- if FLAGS.train_inception:
- learning_rate = tf.constant(training_config.train_inception_learning_rate)
- else:
- learning_rate = tf.constant(training_config.initial_learning_rate)
- if training_config.learning_rate_decay_factor > 0:
- num_batches_per_epoch = (training_config.num_examples_per_epoch /
- model_config.batch_size)
- decay_steps = int(num_batches_per_epoch *
- training_config.num_epochs_per_decay)
-
- def _learning_rate_decay_fn(learning_rate, global_step):
- return tf.train.exponential_decay(
- learning_rate,
- global_step,
- decay_steps=decay_steps,
- decay_rate=training_config.learning_rate_decay_factor,
- staircase=True)
-
- learning_rate_decay_fn = _learning_rate_decay_fn
-
- # Set up the training ops.
- train_op = tf.contrib.layers.optimize_loss(
- loss=model.total_loss,
- global_step=model.global_step,
- learning_rate=learning_rate,
- optimizer=training_config.optimizer,
- clip_gradients=training_config.clip_gradients,
- learning_rate_decay_fn=learning_rate_decay_fn)
-
- # Set up the Saver for saving and restoring model checkpoints.
- saver = tf.train.Saver(max_to_keep=training_config.max_checkpoints_to_keep)
-
- # Run training.
- tf.contrib.slim.learning.train(
- train_op,
- train_dir,
- log_every_n_steps=FLAGS.log_every_n_steps,
- graph=g,
- global_step=model.global_step,
- number_of_steps=FLAGS.number_of_steps,
- init_fn=model.init_fn,
- saver=saver)
-
-
-if __name__ == "__main__":
- tf.app.run()
diff --git a/research/inception/.gitignore b/research/inception/.gitignore
deleted file mode 100644
index 58cbf2f4e0d5d39a0e3910d6993508546dad429f..0000000000000000000000000000000000000000
--- a/research/inception/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-/bazel-bin
-/bazel-ci_build-cache
-/bazel-genfiles
-/bazel-out
-/bazel-inception
-/bazel-testlogs
-/bazel-tf
diff --git a/research/inception/README.md b/research/inception/README.md
deleted file mode 100644
index beed66cf5cd83a6843ec39b28b5dbd88f1c0d3d0..0000000000000000000000000000000000000000
--- a/research/inception/README.md
+++ /dev/null
@@ -1,858 +0,0 @@
-
-
-
-
-**NOTE: For the most part, you will find a newer version of this code at [models/research/slim](https://github.com/tensorflow/models/tree/master/research/slim).** In particular:
-
-* `inception_train.py` and `imagenet_train.py` should no longer be used. The slim editions for running on multiple GPUs are the current best examples.
-* `inception_distributed_train.py` and `imagenet_distributed_train.py` are still valid examples of distributed training.
-
-For performance benchmarking, please see https://www.tensorflow.org/performance/benchmarks.
-
----
-
-# Inception in TensorFlow
-
-[ImageNet](http://www.image-net.org/) is a common academic data set in machine
-learning for training an image recognition system. Code in this directory
-demonstrates how to use TensorFlow to train and evaluate a type of convolutional
-neural network (CNN) on this academic data set. In particular, we demonstrate
-how to train the Inception v3 architecture as specified in:
-
-_Rethinking the Inception Architecture for Computer Vision_
-
-Christian Szegedy, Vincent Vanhoucke, Sergey Ioffe, Jonathon Shlens, Zbigniew
-Wojna
-
-http://arxiv.org/abs/1512.00567
-
-This network achieves 21.2% top-1 and 5.6% top-5 error for single frame
-evaluation with a computational cost of 5 billion multiply-adds per inference
-and with using less than 25 million parameters. Below is a visualization of the
-model architecture.
-
-
-
-## Description of Code
-
-The code base provides three core binaries for:
-
-* Training an Inception v3 network from scratch across multiple GPUs and/or
- multiple machines using the ImageNet 2012 Challenge training data set.
-* Evaluating an Inception v3 network using the ImageNet 2012 Challenge
- validation data set.
-* Retraining an Inception v3 network on a novel task and back-propagating the
- errors to fine tune the network weights.
-
-The training procedure employs synchronous stochastic gradient descent across
-multiple GPUs. The user may specify the number of GPUs they wish to harness. The
-synchronous training performs *batch-splitting* by dividing a given batch across
-multiple GPUs.
-
-The training set up is nearly identical to the section [Training a Model Using
-Multiple GPU Cards](https://www.tensorflow.org/tutorials/deep_cnn/index.html#launching_and_training_the_model_on_multiple_gpu_cards)
-where we have substituted the CIFAR-10 model architecture with Inception v3. The
-primary differences with that setup are:
-
-* Calculate and update the batch-norm statistics during training so that they
- may be substituted in during evaluation.
-* Specify the model architecture using a (still experimental) higher level
- language called TensorFlow-Slim.
-
-For more details about TensorFlow-Slim, please see the [Slim README](inception/slim/README.md). Please note that this higher-level language is still
-*experimental* and the API may change over time depending on usage and
-subsequent research.
-
-## Getting Started
-
-Before you run the training script for the first time, you will need to download
-and convert the ImageNet data to native TFRecord format. The TFRecord format
-consists of a set of sharded files where each entry is a serialized `tf.Example`
-proto. Each `tf.Example` proto contains the ImageNet image (JPEG encoded) as
-well as metadata such as label and bounding box information. See
-[`parse_example_proto`](inception/image_processing.py) for details.
-
-We provide a single [script](inception/data/download_and_preprocess_imagenet.sh) for
-downloading and converting ImageNet data to TFRecord format. Downloading and
-preprocessing the data may take several hours (up to half a day) depending on
-your network and computer speed. Please be patient.
-
-To begin, you will need to sign up for an account with [ImageNet](http://image-net.org) to gain access to the data. Look for the sign up page,
-create an account and request an access key to download the data.
-
-After you have `USERNAME` and `PASSWORD`, you are ready to run our script. Make
-sure that your hard disk has at least 500 GB of free space for downloading and
-storing the data. Here we select `DATA_DIR=$HOME/imagenet-data` as such a
-location but feel free to edit accordingly.
-
-When you run the below script, please enter *USERNAME* and *PASSWORD* when
-prompted. This will occur at the very beginning. Once these values are entered,
-you will not need to interact with the script again.
-
-```shell
-# location of where to place the ImageNet data
-DATA_DIR=$HOME/imagenet-data
-
-# build the preprocessing script.
-cd tensorflow-models/inception
-bazel build //inception:download_and_preprocess_imagenet
-
-# run it
-bazel-bin/inception/download_and_preprocess_imagenet "${DATA_DIR}"
-```
-
-The final line of the output script should read:
-
-```shell
-2016-02-17 14:30:17.287989: Finished writing all 1281167 images in data set.
-```
-
-When the script finishes, you will find 1024 training files and 128 validation
-files in the `DATA_DIR`. The files will match the patterns
-`train-?????-of-01024` and `validation-?????-of-00128`, respectively.
-
-[Congratulations!](https://www.youtube.com/watch?v=9bZkp7q19f0) You are now
-ready to train or evaluate with the ImageNet data set.
-
-## How to Train from Scratch
-
-**WARNING** Training an Inception v3 network from scratch is a computationally
-intensive task and depending on your compute setup may take several days or even
-weeks.
-
-*Before proceeding* please read the [Convolutional Neural Networks](https://www.tensorflow.org/tutorials/deep_cnn/index.html) tutorial; in
-particular, focus on [Training a Model Using Multiple GPU Cards](https://www.tensorflow.org/tutorials/deep_cnn/index.html#launching_and_training_the_model_on_multiple_gpu_cards). The model training method is nearly identical to that described in the
-CIFAR-10 multi-GPU model training. Briefly, the model training
-
-* Places an individual model replica on each GPU.
-* Splits the batch across the GPUs.
-* Updates model parameters synchronously by waiting for all GPUs to finish
- processing a batch of data.
-
-The training procedure is encapsulated by this diagram of how operations and
-variables are placed on CPU and GPUs respectively.
-
-
-

-
-
-Each tower computes the gradients for a portion of the batch and the gradients
-are combined and averaged across the multiple towers in order to provide a
-single update of the Variables stored on the CPU.
-
-A crucial aspect of training a network of this size is *training speed* in terms
-of wall-clock time. The training speed is dictated by many factors -- most
-importantly the batch size and the learning rate schedule. Both of these
-parameters are heavily coupled to the hardware set up.
-
-Generally speaking, a batch size is a difficult parameter to tune as it requires
-balancing memory demands of the model, memory available on the GPU and speed of
-computation. Generally speaking, employing larger batch sizes leads to more
-efficient computation and potentially more efficient training steps.
-
-We have tested several hardware setups for training this model from scratch but
-we emphasize that depending your hardware set up, you may need to adapt the
-batch size and learning rate schedule.
-
-Please see the comments in `inception_train.py` for a few selected learning rate
-plans based on some selected hardware setups.
-
-To train this model, you simply need to specify the following:
-
-```shell
-# Build the model. Note that we need to make sure the TensorFlow is ready to
-# use before this as this command will not build TensorFlow.
-cd tensorflow-models/inception
-bazel build //inception:imagenet_train
-
-# run it
-bazel-bin/inception/imagenet_train --num_gpus=1 --batch_size=32 --train_dir=/tmp/imagenet_train --data_dir=/tmp/imagenet_data
-```
-
-The model reads in the ImageNet training data from `--data_dir`. If you followed
-the instructions in [Getting Started](#getting-started), then set
-`--data_dir="${DATA_DIR}"`. The script assumes that there exists a set of
-sharded TFRecord files containing the ImageNet data. If you have not created
-TFRecord files, please refer to [Getting Started](#getting-started)
-
-Here is the output of the above command line when running on a Tesla K40c:
-
-```shell
-2016-03-07 12:24:59.922898: step 0, loss = 13.11 (5.3 examples/sec; 6.064 sec/batch)
-2016-03-07 12:25:55.206783: step 10, loss = 13.71 (9.4 examples/sec; 3.394 sec/batch)
-2016-03-07 12:26:28.905231: step 20, loss = 14.81 (9.5 examples/sec; 3.380 sec/batch)
-2016-03-07 12:27:02.699719: step 30, loss = 14.45 (9.5 examples/sec; 3.378 sec/batch)
-2016-03-07 12:27:36.515699: step 40, loss = 13.98 (9.5 examples/sec; 3.376 sec/batch)
-2016-03-07 12:28:10.220956: step 50, loss = 13.92 (9.6 examples/sec; 3.327 sec/batch)
-2016-03-07 12:28:43.658223: step 60, loss = 13.28 (9.6 examples/sec; 3.350 sec/batch)
-...
-```
-
-In this example, a log entry is printed every 10 step and the line includes the
-total loss (starts around 13.0-14.0) and the speed of processing in terms of
-throughput (examples / sec) and batch speed (sec/batch).
-
-The number of GPU devices is specified by `--num_gpus` (which defaults to 1).
-Specifying `--num_gpus` greater then 1 splits the batch evenly split across the
-GPU cards.
-
-```shell
-# Build the model. Note that we need to make sure the TensorFlow is ready to
-# use before this as this command will not build TensorFlow.
-cd tensorflow-models/inception
-bazel build //inception:imagenet_train
-
-# run it
-bazel-bin/inception/imagenet_train --num_gpus=2 --batch_size=64 --train_dir=/tmp/imagenet_train
-```
-
-This model splits the batch of 64 images across 2 GPUs and calculates the
-average gradient by waiting for both GPUs to finish calculating the gradients
-from their respective data (See diagram above). Generally speaking, using larger
-numbers of GPUs leads to higher throughput as well as the opportunity to use
-larger batch sizes. In turn, larger batch sizes imply better estimates of the
-gradient enabling the usage of higher learning rates. In summary, using more
-GPUs results in simply faster training speed.
-
-Note that selecting a batch size is a difficult parameter to tune as it requires
-balancing memory demands of the model, memory available on the GPU and speed of
-computation. Generally speaking, employing larger batch sizes leads to more
-efficient computation and potentially more efficient training steps.
-
-Note that there is considerable noise in the loss function on individual steps
-in the previous log. Because of this noise, it is difficult to discern how well
-a model is learning. The solution to the last problem is to launch TensorBoard
-pointing to the directory containing the events log.
-
-```shell
-tensorboard --logdir=/tmp/imagenet_train
-```
-
-TensorBoard has access to the many Summaries produced by the model that describe
-multitudes of statistics tracking the model behavior and the quality of the
-learned model. In particular, TensorBoard tracks a exponentially smoothed
-version of the loss. In practice, it is far easier to judge how well a model
-learns by monitoring the smoothed version of the loss.
-
-## How to Train from Scratch in a Distributed Setting
-
-**NOTE** Distributed TensorFlow requires version 0.8 or later.
-
-Distributed TensorFlow lets us use multiple machines to train a model faster.
-This is quite different from the training with multiple GPU towers on a single
-machine where all parameters and gradients computation are in the same place. We
-coordinate the computation across multiple machines by employing a centralized
-repository for parameters that maintains a unified, single copy of model
-parameters. Each individual machine sends gradient updates to the centralized
-parameter repository which coordinates these updates and sends back updated
-parameters to the individual machines running the model training.
-
-We term each machine that runs a copy of the training a `worker` or `replica`.
-We term each machine that maintains model parameters a `ps`, short for
-`parameter server`. Note that we might have more than one machine acting as a
-`ps` as the model parameters may be sharded across multiple machines.
-
-Variables may be updated with synchronous or asynchronous gradient updates. One
-may construct a an [`Optimizer`](https://www.tensorflow.org/api_docs/python/train.html#optimizers) in TensorFlow
-that constructs the necessary graph for either case diagrammed below from the
-TensorFlow [Whitepaper](http://download.tensorflow.org/paper/whitepaper2015.pdf):
-
-
-

-
-
-In [a recent paper](https://arxiv.org/abs/1604.00981), synchronous gradient
-updates have demonstrated to reach higher accuracy in a shorter amount of time.
-In this distributed Inception example we employ synchronous gradient updates.
-
-Note that in this example each replica has a single tower that uses one GPU.
-
-The command-line flags `worker_hosts` and `ps_hosts` specify available servers.
-The same binary will be used for both the `worker` jobs and the `ps` jobs.
-Command line flag `job_name` will be used to specify what role a task will be
-playing and `task_id` will be used to identify which one of the jobs it is
-running. Several things to note here:
-
-* The numbers of `ps` and `worker` tasks are inferred from the lists of hosts
- specified in the flags. The `task_id` should be within the range `[0,
- num_ps_tasks)` for `ps` tasks and `[0, num_worker_tasks)` for `worker`
- tasks.
-* `ps` and `worker` tasks can run on the same machine, as long as that machine
- has sufficient resources to handle both tasks. Note that the `ps` task does
- not benefit from a GPU, so it should not attempt to use one (see below).
-* Multiple `worker` tasks can run on the same machine with multiple GPUs so
- machine_A with 2 GPUs may have 2 workers while machine_B with 1 GPU just has
- 1 worker.
-* The default learning rate schedule works well for a wide range of number of
- replicas [25, 50, 100] but feel free to tune it for even better results.
-* The command line of both `ps` and `worker` tasks should include the complete
- list of `ps_hosts` and `worker_hosts`.
-* There is a chief `worker` among all workers which defaults to `worker` 0.
- The chief will be in charge of initializing all the parameters, writing out
- the summaries and the checkpoint. The checkpoint and summary will be in the
- `train_dir` of the host for `worker` 0.
-* Each worker processes a batch_size number of examples but each gradient
- update is computed from all replicas. Hence, the effective batch size of
- this model is batch_size * num_workers.
-
-```shell
-# Build the model. Note that we need to make sure the TensorFlow is ready to
-# use before this as this command will not build TensorFlow.
-cd tensorflow-models/inception
-bazel build //inception:imagenet_distributed_train
-
-# To start worker 0, go to the worker0 host and run the following (Note that
-# task_id should be in the range [0, num_worker_tasks):
-bazel-bin/inception/imagenet_distributed_train \
---batch_size=32 \
---data_dir=$HOME/imagenet-data \
---job_name='worker' \
---task_id=0 \
---ps_hosts='ps0.example.com:2222' \
---worker_hosts='worker0.example.com:2222,worker1.example.com:2222'
-
-# To start worker 1, go to the worker1 host and run the following (Note that
-# task_id should be in the range [0, num_worker_tasks):
-bazel-bin/inception/imagenet_distributed_train \
---batch_size=32 \
---data_dir=$HOME/imagenet-data \
---job_name='worker' \
---task_id=1 \
---ps_hosts='ps0.example.com:2222' \
---worker_hosts='worker0.example.com:2222,worker1.example.com:2222'
-
-# To start the parameter server (ps), go to the ps host and run the following (Note
-# that task_id should be in the range [0, num_ps_tasks):
-bazel-bin/inception/imagenet_distributed_train \
---job_name='ps' \
---task_id=0 \
---ps_hosts='ps0.example.com:2222' \
---worker_hosts='worker0.example.com:2222,worker1.example.com:2222'
-```
-
-If you have installed a GPU-compatible version of TensorFlow, the `ps` will also
-try to allocate GPU memory although it is not helpful. This could potentially
-crash the worker on the same machine as it has little to no GPU memory to
-allocate. To avoid this, you can prepend the previous command to start `ps`
-with: `CUDA_VISIBLE_DEVICES=''`
-
-```shell
-CUDA_VISIBLE_DEVICES='' bazel-bin/inception/imagenet_distributed_train \
---job_name='ps' \
---task_id=0 \
---ps_hosts='ps0.example.com:2222' \
---worker_hosts='worker0.example.com:2222,worker1.example.com:2222'
-```
-
-If you have run everything correctly, you should see a log in each `worker` job
-that looks like the following. Note the training speed varies depending on your
-hardware and the first several steps could take much longer.
-
-```shell
-INFO:tensorflow:PS hosts are: ['ps0.example.com:2222', 'ps1.example.com:2222']
-INFO:tensorflow:Worker hosts are: ['worker0.example.com:2222', 'worker1.example.com:2222']
-I tensorflow/core/distributed_runtime/rpc/grpc_channel.cc:206] Initialize HostPortsGrpcChannelCache for job ps -> {ps0.example.com:2222, ps1.example.com:2222}
-I tensorflow/core/distributed_runtime/rpc/grpc_channel.cc:206] Initialize HostPortsGrpcChannelCache for job worker -> {localhost:2222, worker1.example.com:2222}
-I tensorflow/core/distributed_runtime/rpc/grpc_server_lib.cc:202] Started server with target: grpc://localhost:2222
-INFO:tensorflow:Created variable global_step:0 with shape () and init
-
-...
-
-INFO:tensorflow:Created variable logits/logits/biases:0 with shape (1001,) and init
-INFO:tensorflow:SyncReplicas enabled: replicas_to_aggregate=2; total_num_replicas=2
-INFO:tensorflow:2016-04-13 01:56:26.405639 Supervisor
-INFO:tensorflow:Started 2 queues for processing input data.
-INFO:tensorflow:global_step/sec: 0
-INFO:tensorflow:Worker 0: 2016-04-13 01:58:40.342404: step 0, loss = 12.97(0.0 examples/sec; 65.428 sec/batch)
-INFO:tensorflow:global_step/sec: 0.0172907
-...
-```
-
-and a log in each `ps` job that looks like the following:
-
-```shell
-INFO:tensorflow:PS hosts are: ['ps0.example.com:2222', 'ps1.example.com:2222']
-INFO:tensorflow:Worker hosts are: ['worker0.example.com:2222', 'worker1.example.com:2222']
-I tensorflow/core/distributed_runtime/rpc/grpc_channel.cc:206] Initialize HostPortsGrpcChannelCache for job ps -> {localhost:2222, ps1.example.com:2222}
-I tensorflow/core/distributed_runtime/rpc/grpc_channel.cc:206] Initialize HostPortsGrpcChannelCache for job worker -> {worker0.example.com:2222, worker1.example.com:2222}
-I tensorflow/core/distributed_runtime/rpc/grpc_server_lib.cc:202] Started server with target: grpc://localhost:2222
-```
-
-If you compiled TensorFlow (from v1.1-rc3) with VERBS support and you have the
-required device and IB verbs SW stack, you can specify --protocol='grpc+verbs'
-In order to use Verbs RDMA for Tensor passing between workers and ps.
-Need to add the the --protocol flag in all tasks (ps and workers).
-The default protocol is the TensorFlow default protocol of grpc.
-
-
-[Congratulations!](https://www.youtube.com/watch?v=9bZkp7q19f0) You are now
-training Inception in a distributed manner.
-
-## How to Evaluate
-
-Evaluating an Inception v3 model on the ImageNet 2012 validation data set
-requires running a separate binary.
-
-The evaluation procedure is nearly identical to [Evaluating a Model](https://www.tensorflow.org/tutorials/deep_cnn/index.html#evaluating_a_model)
-described in the [Convolutional Neural Network](https://www.tensorflow.org/tutorials/deep_cnn/index.html) tutorial.
-
-**WARNING** Be careful not to run the evaluation and training binary on the same
-GPU or else you might run out of memory. Consider running the evaluation on a
-separate GPU if available or suspending the training binary while running the
-evaluation on the same GPU.
-
-Briefly, one can evaluate the model by running:
-
-```shell
-# Build the model. Note that we need to make sure the TensorFlow is ready to
-# use before this as this command will not build TensorFlow.
-cd tensorflow-models/inception
-bazel build //inception:imagenet_eval
-
-# run it
-bazel-bin/inception/imagenet_eval --checkpoint_dir=/tmp/imagenet_train --eval_dir=/tmp/imagenet_eval
-```
-
-Note that we point `--checkpoint_dir` to the location of the checkpoints saved
-by `inception_train.py` above. Running the above command results in the
-following output:
-
-```shell
-2016-02-17 22:32:50.391206: precision @ 1 = 0.735
-...
-```
-
-The script calculates the precision @ 1 over the entire validation data
-periodically. The precision @ 1 measures the how often the highest scoring
-prediction from the model matched the ImageNet label -- in this case, 73.5%. If
-you wish to run the eval just once and not periodically, append the `--run_once`
-option.
-
-Much like the training script, `imagenet_eval.py` also exports summaries that
-may be visualized in TensorBoard. These summaries calculate additional
-statistics on the predictions (e.g. recall @ 5) as well as monitor the
-statistics of the model activations and weights during evaluation.
-
-## How to Fine-Tune a Pre-Trained Model on a New Task
-
-### Getting Started
-
-Much like training the ImageNet model we must first convert a new data set to
-the sharded TFRecord format which each entry is a serialized `tf.Example` proto.
-
-We have provided a script demonstrating how to do this for small data set of of
-a few thousand flower images spread across 5 labels:
-
-```shell
-daisy, dandelion, roses, sunflowers, tulips
-```
-
-There is a single automated script that downloads the data set and converts it
-to the TFRecord format. Much like the ImageNet data set, each record in the
-TFRecord format is a serialized `tf.Example` proto whose entries include a
-JPEG-encoded string and an integer label. Please see [`parse_example_proto`](inception/image_processing.py) for details.
-
-The script just takes a few minutes to run depending your network connection
-speed for downloading and processing the images. Your hard disk requires 200MB
-of free storage. Here we select `DATA_DIR=/tmp/flowers-data/` as such a location
-but feel free to edit accordingly.
-
-```shell
-# location of where to place the flowers data
-FLOWERS_DATA_DIR=/tmp/flowers-data/
-
-# build the preprocessing script.
-cd tensorflow-models/inception
-bazel build //inception:download_and_preprocess_flowers
-
-# run it
-bazel-bin/inception/download_and_preprocess_flowers "${FLOWERS_DATA_DIR}"
-```
-
-If the script runs successfully, the final line of the terminal output should
-look like:
-
-```shell
-2016-02-24 20:42:25.067551: Finished writing all 3170 images in data set.
-```
-
-When the script finishes you will find 2 shards for the training and validation
-files in the `DATA_DIR`. The files will match the patterns `train-?????-of-00002`
-and `validation-?????-of-00002`, respectively.
-
-**NOTE** If you wish to prepare a custom image data set for transfer learning,
-you will need to invoke [`build_image_data.py`](inception/data/build_image_data.py) on
-your custom data set. Please see the associated options and assumptions behind
-this script by reading the comments section of [`build_image_data.py`](inception/data/build_image_data.py). Also, if your custom data has a different
-number of examples or classes, you need to change the appropriate values in
-[`imagenet_data.py`](inception/imagenet_data.py).
-
-The second piece you will need is a trained Inception v3 image model. You have
-the option of either training one yourself (See [How to Train from Scratch](#how-to-train-from-scratch) for details) or you can download a pre-trained
-model like so:
-
-```shell
-# location of where to place the Inception v3 model
-INCEPTION_MODEL_DIR=$HOME/inception-v3-model
-mkdir -p ${INCEPTION_MODEL_DIR}
-cd ${INCEPTION_MODEL_DIR}
-
-# download the Inception v3 model
-curl -O http://download.tensorflow.org/models/image/imagenet/inception-v3-2016-03-01.tar.gz
-tar xzf inception-v3-2016-03-01.tar.gz
-
-# this will create a directory called inception-v3 which contains the following files.
-> ls inception-v3
-README.txt
-checkpoint
-model.ckpt-157585
-```
-
-[Congratulations!](https://www.youtube.com/watch?v=9bZkp7q19f0) You are now
-ready to fine-tune your pre-trained Inception v3 model with the flower data set.
-
-### How to Retrain a Trained Model on the Flowers Data
-
-We are now ready to fine-tune a pre-trained Inception-v3 model on the flowers
-data set. This requires two distinct changes to our training procedure:
-
-1. Build the exact same model as previously except we change the number of
- labels in the final classification layer.
-
-2. Restore all weights from the pre-trained Inception-v3 except for the final
- classification layer; this will get randomly initialized instead.
-
-We can perform these two operations by specifying two flags:
-`--pretrained_model_checkpoint_path` and `--fine_tune`. The first flag is a
-string that points to the path of a pre-trained Inception-v3 model. If this flag
-is specified, it will load the entire model from the checkpoint before the
-script begins training.
-
-The second flag `--fine_tune` is a boolean that indicates whether the last
-classification layer should be randomly initialized or restored. You may set
-this flag to false if you wish to continue training a pre-trained model from a
-checkpoint. If you set this flag to true, you can train a new classification
-layer from scratch.
-
-In order to understand how `--fine_tune` works, please see the discussion on
-`Variables` in the TensorFlow-Slim [`README.md`](inception/slim/README.md).
-
-Putting this all together you can retrain a pre-trained Inception-v3 model on
-the flowers data set with the following command.
-
-```shell
-# Build the model. Note that we need to make sure the TensorFlow is ready to
-# use before this as this command will not build TensorFlow.
-cd tensorflow-models/inception
-bazel build //inception:flowers_train
-
-# Path to the downloaded Inception-v3 model.
-MODEL_PATH="${INCEPTION_MODEL_DIR}/inception-v3/model.ckpt-157585"
-
-# Directory where the flowers data resides.
-FLOWERS_DATA_DIR=/tmp/flowers-data/
-
-# Directory where to save the checkpoint and events files.
-TRAIN_DIR=/tmp/flowers_train/
-
-# Run the fine-tuning on the flowers data set starting from the pre-trained
-# Imagenet-v3 model.
-bazel-bin/inception/flowers_train \
- --train_dir="${TRAIN_DIR}" \
- --data_dir="${FLOWERS_DATA_DIR}" \
- --pretrained_model_checkpoint_path="${MODEL_PATH}" \
- --fine_tune=True \
- --initial_learning_rate=0.001 \
- --input_queue_memory_factor=1
-```
-
-We have added a few extra options to the training procedure.
-
-* Fine-tuning a model a separate data set requires significantly lowering the
- initial learning rate. We set the initial learning rate to 0.001.
-* The flowers data set is quite small so we shrink the size of the shuffling
- queue of examples. See [Adjusting Memory Demands](#adjusting-memory-demands)
- for more details.
-
-The training script will only reports the loss. To evaluate the quality of the
-fine-tuned model, you will need to run `flowers_eval`:
-
-```shell
-# Build the model. Note that we need to make sure the TensorFlow is ready to
-# use before this as this command will not build TensorFlow.
-cd tensorflow-models/inception
-bazel build //inception:flowers_eval
-
-# Directory where we saved the fine-tuned checkpoint and events files.
-TRAIN_DIR=/tmp/flowers_train/
-
-# Directory where the flowers data resides.
-FLOWERS_DATA_DIR=/tmp/flowers-data/
-
-# Directory where to save the evaluation events files.
-EVAL_DIR=/tmp/flowers_eval/
-
-# Evaluate the fine-tuned model on a hold-out of the flower data set.
-bazel-bin/inception/flowers_eval \
- --eval_dir="${EVAL_DIR}" \
- --data_dir="${FLOWERS_DATA_DIR}" \
- --subset=validation \
- --num_examples=500 \
- --checkpoint_dir="${TRAIN_DIR}" \
- --input_queue_memory_factor=1 \
- --run_once
-```
-
-We find that the evaluation arrives at roughly 93.4% precision@1 after the model
-has been running for 2000 steps.
-
-```shell
-Successfully loaded model from /tmp/flowers/model.ckpt-1999 at step=1999.
-2016-03-01 16:52:51.761219: starting evaluation on (validation).
-2016-03-01 16:53:05.450419: [20 batches out of 20] (36.5 examples/sec; 0.684sec/batch)
-2016-03-01 16:53:05.450471: precision @ 1 = 0.9340 recall @ 5 = 0.9960 [500 examples]
-```
-
-## How to Construct a New Dataset for Retraining
-
-One can use the existing scripts supplied with this model to build a new dataset
-for training or fine-tuning. The main script to employ is
-[`build_image_data.py`](inception/data/build_image_data.py). Briefly, this script takes a
-structured directory of images and converts it to a sharded `TFRecord` that can
-be read by the Inception model.
-
-In particular, you will need to create a directory of training images that
-reside within `$TRAIN_DIR` and `$VALIDATION_DIR` arranged as such:
-
-```shell
- $TRAIN_DIR/dog/image0.jpeg
- $TRAIN_DIR/dog/image1.jpg
- $TRAIN_DIR/dog/image2.png
- ...
- $TRAIN_DIR/cat/weird-image.jpeg
- $TRAIN_DIR/cat/my-image.jpeg
- $TRAIN_DIR/cat/my-image.JPG
- ...
- $VALIDATION_DIR/dog/imageA.jpeg
- $VALIDATION_DIR/dog/imageB.jpg
- $VALIDATION_DIR/dog/imageC.png
- ...
- $VALIDATION_DIR/cat/weird-image.PNG
- $VALIDATION_DIR/cat/that-image.jpg
- $VALIDATION_DIR/cat/cat.JPG
- ...
-```
-**NOTE**: This script will append an extra background class indexed at 0, so
-your class labels will range from 0 to num_labels. Using the example above, the
-corresponding class labels generated from `build_image_data.py` will be as
-follows:
-```shell
-0
-1 dog
-2 cat
-```
-
-Each sub-directory in `$TRAIN_DIR` and `$VALIDATION_DIR` corresponds to a unique
-label for the images that reside within that sub-directory. The images may be
-JPEG or PNG images. We do not support other images types currently.
-
-Once the data is arranged in this directory structure, we can run
-`build_image_data.py` on the data to generate the sharded `TFRecord` dataset.
-Each entry of the `TFRecord` is a serialized `tf.Example` protocol buffer. A
-complete list of information contained in the `tf.Example` is described in the
-comments of `build_image_data.py`.
-
-To run `build_image_data.py`, you can run the following command line:
-
-```shell
-# location to where to save the TFRecord data.
-OUTPUT_DIRECTORY=$HOME/my-custom-data/
-
-# build the preprocessing script.
-cd tensorflow-models/inception
-bazel build //inception:build_image_data
-
-# convert the data.
-bazel-bin/inception/build_image_data \
- --train_directory="${TRAIN_DIR}" \
- --validation_directory="${VALIDATION_DIR}" \
- --output_directory="${OUTPUT_DIRECTORY}" \
- --labels_file="${LABELS_FILE}" \
- --train_shards=128 \
- --validation_shards=24 \
- --num_threads=8
-```
-
-where the `$OUTPUT_DIRECTORY` is the location of the sharded `TFRecords`. The
-`$LABELS_FILE` will be a text file that is read by the script that provides
-a list of all of the labels. For instance, in the case flowers data set, the
-`$LABELS_FILE` contained the following data:
-
-```shell
-daisy
-dandelion
-roses
-sunflowers
-tulips
-```
-
-Note that each row of each label corresponds with the entry in the final
-classifier in the model. That is, the `daisy` corresponds to the classifier for
-entry `1`; `dandelion` is entry `2`, etc. We skip label `0` as a background
-class.
-
-After running this script produces files that look like the following:
-
-```shell
- $TRAIN_DIR/train-00000-of-00128
- $TRAIN_DIR/train-00001-of-00128
- ...
- $TRAIN_DIR/train-00127-of-00128
-
-and
-
- $VALIDATION_DIR/validation-00000-of-00024
- $VALIDATION_DIR/validation-00001-of-00024
- ...
- $VALIDATION_DIR/validation-00023-of-00024
-```
-
-where 128 and 24 are the number of shards specified for each dataset,
-respectively. Generally speaking, we aim for selecting the number of shards such
-that roughly 1024 images reside in each shard. Once this data set is built, you
-are ready to train or fine-tune an Inception model on this data set.
-
-Note, if you are piggy backing on the flowers retraining scripts, be sure to
-update `num_classes()` and `num_examples_per_epoch()` in `flowers_data.py`
-to correspond with your data.
-
-## Practical Considerations for Training a Model
-
-The model architecture and training procedure is heavily dependent on the
-hardware used to train the model. If you wish to train or fine-tune this model
-on your machine **you will need to adjust and empirically determine a good set
-of training hyper-parameters for your setup**. What follows are some general
-considerations for novices.
-
-### Finding Good Hyperparameters
-
-Roughly 5-10 hyper-parameters govern the speed at which a network is trained. In
-addition to `--batch_size` and `--num_gpus`, there are several constants defined
-in [inception_train.py](inception/inception_train.py) which dictate the learning
-schedule.
-
-```shell
-RMSPROP_DECAY = 0.9 # Decay term for RMSProp.
-MOMENTUM = 0.9 # Momentum in RMSProp.
-RMSPROP_EPSILON = 1.0 # Epsilon term for RMSProp.
-INITIAL_LEARNING_RATE = 0.1 # Initial learning rate.
-NUM_EPOCHS_PER_DECAY = 30.0 # Epochs after which learning rate decays.
-LEARNING_RATE_DECAY_FACTOR = 0.16 # Learning rate decay factor.
-```
-
-There are many papers that discuss the various tricks and trade-offs associated
-with training a model with stochastic gradient descent. For those new to the
-field, some great references are:
-
-* Y Bengio, [Practical recommendations for gradient-based training of deep
- architectures](http://arxiv.org/abs/1206.5533)
-* I Goodfellow, Y Bengio and A Courville, [Deep Learning]
- (http://www.deeplearningbook.org/)
-
-What follows is a summary of some general advice for identifying appropriate
-model hyper-parameters in the context of this particular model training setup.
-Namely, this library provides *synchronous* updates to model parameters based on
-batch-splitting the model across multiple GPUs.
-
-* Higher learning rates leads to faster training. Too high of learning rate
- leads to instability and will cause model parameters to diverge to infinity
- or NaN.
-
-* Larger batch sizes lead to higher quality estimates of the gradient and
- permit training the model with higher learning rates.
-
-* Often the GPU memory is a bottleneck that prevents employing larger batch
- sizes. Employing more GPUs allows one to use larger batch sizes because
- this model splits the batch across the GPUs.
-
-**NOTE** If one wishes to train this model with *asynchronous* gradient updates,
-one will need to substantially alter this model and new considerations need to
-be factored into hyperparameter tuning. See [Large Scale Distributed Deep
-Networks](http://research.google.com/archive/large_deep_networks_nips2012.html)
-for a discussion in this domain.
-
-### Adjusting Memory Demands
-
-Training this model has large memory demands in terms of the CPU and GPU. Let's
-discuss each item in turn.
-
-GPU memory is relatively small compared to CPU memory. Two items dictate the
-amount of GPU memory employed -- model architecture and batch size. Assuming
-that you keep the model architecture fixed, the sole parameter governing the GPU
-demand is the batch size. A good rule of thumb is to try employ as large of
-batch size as will fit on the GPU.
-
-If you run out of GPU memory, either lower the `--batch_size` or employ more
-GPUs on your desktop. The model performs batch-splitting across GPUs, thus N
-GPUs can handle N times the batch size of 1 GPU.
-
-The model requires a large amount of CPU memory as well. We have tuned the model
-to employ about ~20GB of CPU memory. Thus, having access to about 40 GB of CPU
-memory would be ideal.
-
-If that is not possible, you can tune down the memory demands of the model via
-lowering `--input_queue_memory_factor`. Images are preprocessed asynchronously
-with respect to the main training across `--num_preprocess_threads` threads. The
-preprocessed images are stored in shuffling queue in which each GPU performs a
-dequeue operation in order to receive a `batch_size` worth of images.
-
-In order to guarantee good shuffling across the data, we maintain a large
-shuffling queue of 1024 x `input_queue_memory_factor` images. For the current
-model architecture, this corresponds to about 4GB of CPU memory. You may lower
-`input_queue_memory_factor` in order to decrease the memory footprint. Keep in
-mind though that lowering this value drastically may result in a model with
-slightly lower predictive accuracy when training from scratch. Please see
-comments in [`image_processing.py`](inception/image_processing.py) for more details.
-
-## Troubleshooting
-
-#### The model runs out of CPU memory.
-
-In lieu of buying more CPU memory, an easy fix is to decrease
-`--input_queue_memory_factor`. See [Adjusting Memory Demands](#adjusting-memory-demands).
-
-#### The model runs out of GPU memory.
-
-The data is not able to fit on the GPU card. The simplest solution is to
-decrease the batch size of the model. Otherwise, you will need to think about a
-more sophisticated method for specifying the training which cuts up the model
-across multiple `session.run()` calls or partitions the model across multiple
-GPUs. See [Using GPUs](https://www.tensorflow.org/how_tos/using_gpu/index.html)
-and [Adjusting Memory Demands](#adjusting-memory-demands) for more information.
-
-#### The model training results in NaN's.
-
-The learning rate of the model is too high. Turn down your learning rate.
-
-#### I wish to train a model with a different image size.
-
-The simplest solution is to artificially resize your images to `299x299` pixels.
-See [Images](https://www.tensorflow.org/api_docs/python/image.html) section for
-many resizing, cropping and padding methods. Note that the entire model
-architecture is predicated on a `299x299` image, thus if you wish to change the
-input image size, then you may need to redesign the entire model architecture.
-
-#### What hardware specification are these hyper-parameters targeted for?
-
-We targeted a desktop with 128GB of CPU ram connected to 8 NVIDIA Tesla K40 GPU
-cards but we have run this on desktops with 32GB of CPU ram and 1 NVIDIA Tesla
-K40. You can get a sense of the various training configurations we tested by
-reading the comments in [`inception_train.py`](inception/inception_train.py).
-
-#### How do I continue training from a checkpoint in distributed setting?
-
-You only need to make sure that the checkpoint is in a location that can be
-reached by all of the `ps` tasks. By specifying the checkpoint location with
-`--train_dir` , the `ps` servers will load the checkpoint before commencing
-training.
diff --git a/research/inception/WORKSPACE b/research/inception/WORKSPACE
deleted file mode 100644
index 2d7b4fb254a0fcebe695cb3fd3685af29a02e0b0..0000000000000000000000000000000000000000
--- a/research/inception/WORKSPACE
+++ /dev/null
@@ -1 +0,0 @@
-workspace(name = "inception")
diff --git a/research/inception/g3doc/inception_v3_architecture.png b/research/inception/g3doc/inception_v3_architecture.png
deleted file mode 100644
index 91fb734a104b2f63114ade7c8f9b2f95ce6334a6..0000000000000000000000000000000000000000
Binary files a/research/inception/g3doc/inception_v3_architecture.png and /dev/null differ
diff --git a/research/inception/inception/BUILD b/research/inception/inception/BUILD
deleted file mode 100644
index 21fc27aa57c14f6a72359cf15d446787c8ea6c2e..0000000000000000000000000000000000000000
--- a/research/inception/inception/BUILD
+++ /dev/null
@@ -1,198 +0,0 @@
-# Description:
-# Example TensorFlow models for ImageNet.
-
-package(default_visibility = [":internal"])
-
-licenses(["notice"]) # Apache 2.0
-
-exports_files(["LICENSE"])
-
-package_group(
- name = "internal",
- packages = ["//inception/..."],
-)
-
-py_library(
- name = "dataset",
- srcs = [
- "dataset.py",
- ],
-)
-
-py_library(
- name = "imagenet_data",
- srcs = [
- "imagenet_data.py",
- ],
- deps = [
- ":dataset",
- ],
-)
-
-py_library(
- name = "flowers_data",
- srcs = [
- "flowers_data.py",
- ],
- deps = [
- ":dataset",
- ],
-)
-
-py_library(
- name = "image_processing",
- srcs = [
- "image_processing.py",
- ],
-)
-
-py_library(
- name = "inception",
- srcs = [
- "inception_model.py",
- ],
- visibility = ["//visibility:public"],
- deps = [
- ":dataset",
- "//inception/slim",
- ],
-)
-
-py_binary(
- name = "imagenet_eval",
- srcs = [
- "imagenet_eval.py",
- ],
- deps = [
- ":imagenet_data",
- ":inception_eval",
- ],
-)
-
-py_binary(
- name = "flowers_eval",
- srcs = [
- "flowers_eval.py",
- ],
- deps = [
- ":flowers_data",
- ":inception_eval",
- ],
-)
-
-py_library(
- name = "inception_eval",
- srcs = [
- "inception_eval.py",
- ],
- deps = [
- ":image_processing",
- ":inception",
- ],
-)
-
-py_binary(
- name = "imagenet_train",
- srcs = [
- "imagenet_train.py",
- ],
- deps = [
- ":imagenet_data",
- ":inception_train",
- ],
-)
-
-py_binary(
- name = "imagenet_distributed_train",
- srcs = [
- "imagenet_distributed_train.py",
- ],
- deps = [
- ":imagenet_data",
- ":inception_distributed_train",
- ],
-)
-
-py_binary(
- name = "flowers_train",
- srcs = [
- "flowers_train.py",
- ],
- deps = [
- ":flowers_data",
- ":inception_train",
- ],
-)
-
-py_library(
- name = "inception_train",
- srcs = [
- "inception_train.py",
- ],
- deps = [
- ":image_processing",
- ":inception",
- ],
-)
-
-py_library(
- name = "inception_distributed_train",
- srcs = [
- "inception_distributed_train.py",
- ],
- deps = [
- ":image_processing",
- ":inception",
- ],
-)
-
-py_binary(
- name = "build_image_data",
- srcs = ["data/build_image_data.py"],
-)
-
-sh_binary(
- name = "download_and_preprocess_flowers",
- srcs = ["data/download_and_preprocess_flowers.sh"],
- data = [
- ":build_image_data",
- ],
-)
-
-sh_binary(
- name = "download_and_preprocess_imagenet",
- srcs = ["data/download_and_preprocess_imagenet.sh"],
- data = [
- "data/download_imagenet.sh",
- "data/imagenet_2012_validation_synset_labels.txt",
- "data/imagenet_lsvrc_2015_synsets.txt",
- "data/imagenet_metadata.txt",
- "data/preprocess_imagenet_validation_data.py",
- "data/process_bounding_boxes.py",
- ":build_imagenet_data",
- ],
-)
-
-py_binary(
- name = "build_imagenet_data",
- srcs = ["data/build_imagenet_data.py"],
-)
-
-filegroup(
- name = "srcs",
- srcs = glob(
- [
- "**/*.py",
- "BUILD",
- ],
- ),
-)
-
-filegroup(
- name = "imagenet_metadata",
- srcs = [
- "data/imagenet_lsvrc_2015_synsets.txt",
- "data/imagenet_metadata.txt",
- ],
- visibility = ["//visibility:public"],
-)
diff --git a/research/inception/inception/data/build_image_data.py b/research/inception/inception/data/build_image_data.py
deleted file mode 100755
index 894388b7f758a46746870f2f0d55d1df7d3fe29b..0000000000000000000000000000000000000000
--- a/research/inception/inception/data/build_image_data.py
+++ /dev/null
@@ -1,436 +0,0 @@
-#!/usr/bin/python
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Converts image data to TFRecords file format with Example protos.
-
-The image data set is expected to reside in JPEG files located in the
-following directory structure.
-
- data_dir/label_0/image0.jpeg
- data_dir/label_0/image1.jpg
- ...
- data_dir/label_1/weird-image.jpeg
- data_dir/label_1/my-image.jpeg
- ...
-
-where the sub-directory is the unique label associated with these images.
-
-This TensorFlow script converts the training and evaluation data into
-a sharded data set consisting of TFRecord files
-
- train_directory/train-00000-of-01024
- train_directory/train-00001-of-01024
- ...
- train_directory/train-01023-of-01024
-
-and
-
- validation_directory/validation-00000-of-00128
- validation_directory/validation-00001-of-00128
- ...
- validation_directory/validation-00127-of-00128
-
-where we have selected 1024 and 128 shards for each data set. Each record
-within the TFRecord file is a serialized Example proto. The Example proto
-contains the following fields:
-
- image/encoded: string containing JPEG encoded image in RGB colorspace
- image/height: integer, image height in pixels
- image/width: integer, image width in pixels
- image/colorspace: string, specifying the colorspace, always 'RGB'
- image/channels: integer, specifying the number of channels, always 3
- image/format: string, specifying the format, always 'JPEG'
-
- image/filename: string containing the basename of the image file
- e.g. 'n01440764_10026.JPEG' or 'ILSVRC2012_val_00000293.JPEG'
- image/class/label: integer specifying the index in a classification layer.
- The label ranges from [0, num_labels] where 0 is unused and left as
- the background class.
- image/class/text: string specifying the human-readable version of the label
- e.g. 'dog'
-
-If your data set involves bounding boxes, please look at build_imagenet_data.py.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from datetime import datetime
-import os
-import random
-import sys
-import threading
-
-import numpy as np
-import tensorflow as tf
-
-tf.app.flags.DEFINE_string('train_directory', '/tmp/',
- 'Training data directory')
-tf.app.flags.DEFINE_string('validation_directory', '/tmp/',
- 'Validation data directory')
-tf.app.flags.DEFINE_string('output_directory', '/tmp/',
- 'Output data directory')
-
-tf.app.flags.DEFINE_integer('train_shards', 2,
- 'Number of shards in training TFRecord files.')
-tf.app.flags.DEFINE_integer('validation_shards', 2,
- 'Number of shards in validation TFRecord files.')
-
-tf.app.flags.DEFINE_integer('num_threads', 2,
- 'Number of threads to preprocess the images.')
-
-# The labels file contains a list of valid labels are held in this file.
-# Assumes that the file contains entries as such:
-# dog
-# cat
-# flower
-# where each line corresponds to a label. We map each label contained in
-# the file to an integer corresponding to the line number starting from 0.
-tf.app.flags.DEFINE_string('labels_file', '', 'Labels file')
-
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def _int64_feature(value):
- """Wrapper for inserting int64 features into Example proto."""
- if not isinstance(value, list):
- value = [value]
- return tf.train.Feature(int64_list=tf.train.Int64List(value=value))
-
-
-def _bytes_feature(value):
- """Wrapper for inserting bytes features into Example proto."""
- return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
-
-
-def _convert_to_example(filename, image_buffer, label, text, height, width):
- """Build an Example proto for an example.
-
- Args:
- filename: string, path to an image file, e.g., '/path/to/example.JPG'
- image_buffer: string, JPEG encoding of RGB image
- label: integer, identifier for the ground truth for the network
- text: string, unique human-readable, e.g. 'dog'
- height: integer, image height in pixels
- width: integer, image width in pixels
- Returns:
- Example proto
- """
-
- colorspace = 'RGB'
- channels = 3
- image_format = 'JPEG'
-
- example = tf.train.Example(features=tf.train.Features(feature={
- 'image/height': _int64_feature(height),
- 'image/width': _int64_feature(width),
- 'image/colorspace': _bytes_feature(tf.compat.as_bytes(colorspace)),
- 'image/channels': _int64_feature(channels),
- 'image/class/label': _int64_feature(label),
- 'image/class/text': _bytes_feature(tf.compat.as_bytes(text)),
- 'image/format': _bytes_feature(tf.compat.as_bytes(image_format)),
- 'image/filename': _bytes_feature(tf.compat.as_bytes(os.path.basename(filename))),
- 'image/encoded': _bytes_feature(tf.compat.as_bytes(image_buffer))}))
- return example
-
-
-class ImageCoder(object):
- """Helper class that provides TensorFlow image coding utilities."""
-
- def __init__(self):
- # Create a single Session to run all image coding calls.
- self._sess = tf.Session()
-
- # Initializes function that converts PNG to JPEG data.
- self._png_data = tf.placeholder(dtype=tf.string)
- image = tf.image.decode_png(self._png_data, channels=3)
- self._png_to_jpeg = tf.image.encode_jpeg(image, format='rgb', quality=100)
-
- # Initializes function that decodes RGB JPEG data.
- self._decode_jpeg_data = tf.placeholder(dtype=tf.string)
- self._decode_jpeg = tf.image.decode_jpeg(self._decode_jpeg_data, channels=3)
-
- def png_to_jpeg(self, image_data):
- return self._sess.run(self._png_to_jpeg,
- feed_dict={self._png_data: image_data})
-
- def decode_jpeg(self, image_data):
- image = self._sess.run(self._decode_jpeg,
- feed_dict={self._decode_jpeg_data: image_data})
- assert len(image.shape) == 3
- assert image.shape[2] == 3
- return image
-
-
-def _is_png(filename):
- """Determine if a file contains a PNG format image.
-
- Args:
- filename: string, path of the image file.
-
- Returns:
- boolean indicating if the image is a PNG.
- """
- return filename.endswith('.png')
-
-
-def _process_image(filename, coder):
- """Process a single image file.
-
- Args:
- filename: string, path to an image file e.g., '/path/to/example.JPG'.
- coder: instance of ImageCoder to provide TensorFlow image coding utils.
- Returns:
- image_buffer: string, JPEG encoding of RGB image.
- height: integer, image height in pixels.
- width: integer, image width in pixels.
- """
- # Read the image file.
- with tf.gfile.FastGFile(filename, 'rb') as f:
- image_data = f.read()
-
- # Convert any PNG to JPEG's for consistency.
- if _is_png(filename):
- print('Converting PNG to JPEG for %s' % filename)
- image_data = coder.png_to_jpeg(image_data)
-
- # Decode the RGB JPEG.
- image = coder.decode_jpeg(image_data)
-
- # Check that image converted to RGB
- assert len(image.shape) == 3
- height = image.shape[0]
- width = image.shape[1]
- assert image.shape[2] == 3
-
- return image_data, height, width
-
-
-def _process_image_files_batch(coder, thread_index, ranges, name, filenames,
- texts, labels, num_shards):
- """Processes and saves list of images as TFRecord in 1 thread.
-
- Args:
- coder: instance of ImageCoder to provide TensorFlow image coding utils.
- thread_index: integer, unique batch to run index is within [0, len(ranges)).
- ranges: list of pairs of integers specifying ranges of each batches to
- analyze in parallel.
- name: string, unique identifier specifying the data set
- filenames: list of strings; each string is a path to an image file
- texts: list of strings; each string is human readable, e.g. 'dog'
- labels: list of integer; each integer identifies the ground truth
- num_shards: integer number of shards for this data set.
- """
- # Each thread produces N shards where N = int(num_shards / num_threads).
- # For instance, if num_shards = 128, and the num_threads = 2, then the first
- # thread would produce shards [0, 64).
- num_threads = len(ranges)
- assert not num_shards % num_threads
- num_shards_per_batch = int(num_shards / num_threads)
-
- shard_ranges = np.linspace(ranges[thread_index][0],
- ranges[thread_index][1],
- num_shards_per_batch + 1).astype(int)
- num_files_in_thread = ranges[thread_index][1] - ranges[thread_index][0]
-
- counter = 0
- for s in range(num_shards_per_batch):
- # Generate a sharded version of the file name, e.g. 'train-00002-of-00010'
- shard = thread_index * num_shards_per_batch + s
- output_filename = '%s-%.5d-of-%.5d' % (name, shard, num_shards)
- output_file = os.path.join(FLAGS.output_directory, output_filename)
- writer = tf.python_io.TFRecordWriter(output_file)
-
- shard_counter = 0
- files_in_shard = np.arange(shard_ranges[s], shard_ranges[s + 1], dtype=int)
- for i in files_in_shard:
- filename = filenames[i]
- label = labels[i]
- text = texts[i]
-
- try:
- image_buffer, height, width = _process_image(filename, coder)
- except Exception as e:
- print(e)
- print('SKIPPED: Unexpected error while decoding %s.' % filename)
- continue
-
- example = _convert_to_example(filename, image_buffer, label,
- text, height, width)
- writer.write(example.SerializeToString())
- shard_counter += 1
- counter += 1
-
- if not counter % 1000:
- print('%s [thread %d]: Processed %d of %d images in thread batch.' %
- (datetime.now(), thread_index, counter, num_files_in_thread))
- sys.stdout.flush()
-
- writer.close()
- print('%s [thread %d]: Wrote %d images to %s' %
- (datetime.now(), thread_index, shard_counter, output_file))
- sys.stdout.flush()
- shard_counter = 0
- print('%s [thread %d]: Wrote %d images to %d shards.' %
- (datetime.now(), thread_index, counter, num_files_in_thread))
- sys.stdout.flush()
-
-
-def _process_image_files(name, filenames, texts, labels, num_shards):
- """Process and save list of images as TFRecord of Example protos.
-
- Args:
- name: string, unique identifier specifying the data set
- filenames: list of strings; each string is a path to an image file
- texts: list of strings; each string is human readable, e.g. 'dog'
- labels: list of integer; each integer identifies the ground truth
- num_shards: integer number of shards for this data set.
- """
- assert len(filenames) == len(texts)
- assert len(filenames) == len(labels)
-
- # Break all images into batches with a [ranges[i][0], ranges[i][1]].
- spacing = np.linspace(0, len(filenames), FLAGS.num_threads + 1).astype(np.int)
- ranges = []
- for i in range(len(spacing) - 1):
- ranges.append([spacing[i], spacing[i + 1]])
-
- # Launch a thread for each batch.
- print('Launching %d threads for spacings: %s' % (FLAGS.num_threads, ranges))
- sys.stdout.flush()
-
- # Create a mechanism for monitoring when all threads are finished.
- coord = tf.train.Coordinator()
-
- # Create a generic TensorFlow-based utility for converting all image codings.
- coder = ImageCoder()
-
- threads = []
- for thread_index in range(len(ranges)):
- args = (coder, thread_index, ranges, name, filenames,
- texts, labels, num_shards)
- t = threading.Thread(target=_process_image_files_batch, args=args)
- t.start()
- threads.append(t)
-
- # Wait for all the threads to terminate.
- coord.join(threads)
- print('%s: Finished writing all %d images in data set.' %
- (datetime.now(), len(filenames)))
- sys.stdout.flush()
-
-
-def _find_image_files(data_dir, labels_file):
- """Build a list of all images files and labels in the data set.
-
- Args:
- data_dir: string, path to the root directory of images.
-
- Assumes that the image data set resides in JPEG files located in
- the following directory structure.
-
- data_dir/dog/another-image.JPEG
- data_dir/dog/my-image.jpg
-
- where 'dog' is the label associated with these images.
-
- labels_file: string, path to the labels file.
-
- The list of valid labels are held in this file. Assumes that the file
- contains entries as such:
- dog
- cat
- flower
- where each line corresponds to a label. We map each label contained in
- the file to an integer starting with the integer 0 corresponding to the
- label contained in the first line.
-
- Returns:
- filenames: list of strings; each string is a path to an image file.
- texts: list of strings; each string is the class, e.g. 'dog'
- labels: list of integer; each integer identifies the ground truth.
- """
- print('Determining list of input files and labels from %s.' % data_dir)
- unique_labels = [l.strip() for l in tf.gfile.FastGFile(
- labels_file, 'r').readlines()]
-
- labels = []
- filenames = []
- texts = []
-
- # Leave label index 0 empty as a background class.
- label_index = 1
-
- # Construct the list of JPEG files and labels.
- for text in unique_labels:
- jpeg_file_path = '%s/%s/*' % (data_dir, text)
- matching_files = tf.gfile.Glob(jpeg_file_path)
-
- labels.extend([label_index] * len(matching_files))
- texts.extend([text] * len(matching_files))
- filenames.extend(matching_files)
-
- if not label_index % 100:
- print('Finished finding files in %d of %d classes.' % (
- label_index, len(labels)))
- label_index += 1
-
- # Shuffle the ordering of all image files in order to guarantee
- # random ordering of the images with respect to label in the
- # saved TFRecord files. Make the randomization repeatable.
- shuffled_index = list(range(len(filenames)))
- random.seed(12345)
- random.shuffle(shuffled_index)
-
- filenames = [filenames[i] for i in shuffled_index]
- texts = [texts[i] for i in shuffled_index]
- labels = [labels[i] for i in shuffled_index]
-
- print('Found %d JPEG files across %d labels inside %s.' %
- (len(filenames), len(unique_labels), data_dir))
- return filenames, texts, labels
-
-
-def _process_dataset(name, directory, num_shards, labels_file):
- """Process a complete data set and save it as a TFRecord.
-
- Args:
- name: string, unique identifier specifying the data set.
- directory: string, root path to the data set.
- num_shards: integer number of shards for this data set.
- labels_file: string, path to the labels file.
- """
- filenames, texts, labels = _find_image_files(directory, labels_file)
- _process_image_files(name, filenames, texts, labels, num_shards)
-
-
-def main(unused_argv):
- assert not FLAGS.train_shards % FLAGS.num_threads, (
- 'Please make the FLAGS.num_threads commensurate with FLAGS.train_shards')
- assert not FLAGS.validation_shards % FLAGS.num_threads, (
- 'Please make the FLAGS.num_threads commensurate with '
- 'FLAGS.validation_shards')
- print('Saving results to %s' % FLAGS.output_directory)
-
- # Run it!
- _process_dataset('validation', FLAGS.validation_directory,
- FLAGS.validation_shards, FLAGS.labels_file)
- _process_dataset('train', FLAGS.train_directory,
- FLAGS.train_shards, FLAGS.labels_file)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/inception/inception/data/build_imagenet_data.py b/research/inception/inception/data/build_imagenet_data.py
deleted file mode 100644
index c054735e782297f990451e29ff4383af24bbe802..0000000000000000000000000000000000000000
--- a/research/inception/inception/data/build_imagenet_data.py
+++ /dev/null
@@ -1,707 +0,0 @@
-#!/usr/bin/python
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Converts ImageNet data to TFRecords file format with Example protos.
-
-The raw ImageNet data set is expected to reside in JPEG files located in the
-following directory structure.
-
- data_dir/n01440764/ILSVRC2012_val_00000293.JPEG
- data_dir/n01440764/ILSVRC2012_val_00000543.JPEG
- ...
-
-where 'n01440764' is the unique synset label associated with
-these images.
-
-The training data set consists of 1000 sub-directories (i.e. labels)
-each containing 1200 JPEG images for a total of 1.2M JPEG images.
-
-The evaluation data set consists of 1000 sub-directories (i.e. labels)
-each containing 50 JPEG images for a total of 50K JPEG images.
-
-This TensorFlow script converts the training and evaluation data into
-a sharded data set consisting of 1024 and 128 TFRecord files, respectively.
-
- train_directory/train-00000-of-01024
- train_directory/train-00001-of-01024
- ...
- train_directory/train-01023-of-01024
-
-and
-
- validation_directory/validation-00000-of-00128
- validation_directory/validation-00001-of-00128
- ...
- validation_directory/validation-00127-of-00128
-
-Each validation TFRecord file contains ~390 records. Each training TFREcord
-file contains ~1250 records. Each record within the TFRecord file is a
-serialized Example proto. The Example proto contains the following fields:
-
- image/encoded: string containing JPEG encoded image in RGB colorspace
- image/height: integer, image height in pixels
- image/width: integer, image width in pixels
- image/colorspace: string, specifying the colorspace, always 'RGB'
- image/channels: integer, specifying the number of channels, always 3
- image/format: string, specifying the format, always 'JPEG'
-
- image/filename: string containing the basename of the image file
- e.g. 'n01440764_10026.JPEG' or 'ILSVRC2012_val_00000293.JPEG'
- image/class/label: integer specifying the index in a classification layer.
- The label ranges from [1, 1000] where 0 is not used.
- image/class/synset: string specifying the unique ID of the label,
- e.g. 'n01440764'
- image/class/text: string specifying the human-readable version of the label
- e.g. 'red fox, Vulpes vulpes'
-
- image/object/bbox/xmin: list of integers specifying the 0+ human annotated
- bounding boxes
- image/object/bbox/xmax: list of integers specifying the 0+ human annotated
- bounding boxes
- image/object/bbox/ymin: list of integers specifying the 0+ human annotated
- bounding boxes
- image/object/bbox/ymax: list of integers specifying the 0+ human annotated
- bounding boxes
- image/object/bbox/label: integer specifying the index in a classification
- layer. The label ranges from [1, 1000] where 0 is not used. Note this is
- always identical to the image label.
-
-Note that the length of xmin is identical to the length of xmax, ymin and ymax
-for each example.
-
-Running this script using 16 threads may take around ~2.5 hours on an HP Z420.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from datetime import datetime
-import os
-import random
-import sys
-import threading
-
-import numpy as np
-import six
-import tensorflow as tf
-
-tf.app.flags.DEFINE_string('train_directory', '/tmp/',
- 'Training data directory')
-tf.app.flags.DEFINE_string('validation_directory', '/tmp/',
- 'Validation data directory')
-tf.app.flags.DEFINE_string('output_directory', '/tmp/',
- 'Output data directory')
-
-tf.app.flags.DEFINE_integer('train_shards', 1024,
- 'Number of shards in training TFRecord files.')
-tf.app.flags.DEFINE_integer('validation_shards', 128,
- 'Number of shards in validation TFRecord files.')
-
-tf.app.flags.DEFINE_integer('num_threads', 8,
- 'Number of threads to preprocess the images.')
-
-# The labels file contains a list of valid labels are held in this file.
-# Assumes that the file contains entries as such:
-# n01440764
-# n01443537
-# n01484850
-# where each line corresponds to a label expressed as a synset. We map
-# each synset contained in the file to an integer (based on the alphabetical
-# ordering). See below for details.
-tf.app.flags.DEFINE_string('labels_file',
- 'imagenet_lsvrc_2015_synsets.txt',
- 'Labels file')
-
-# This file containing mapping from synset to human-readable label.
-# Assumes each line of the file looks like:
-#
-# n02119247 black fox
-# n02119359 silver fox
-# n02119477 red fox, Vulpes fulva
-#
-# where each line corresponds to a unique mapping. Note that each line is
-# formatted as \t.
-tf.app.flags.DEFINE_string('imagenet_metadata_file',
- 'imagenet_metadata.txt',
- 'ImageNet metadata file')
-
-# This file is the output of process_bounding_box.py
-# Assumes each line of the file looks like:
-#
-# n00007846_64193.JPEG,0.0060,0.2620,0.7545,0.9940
-#
-# where each line corresponds to one bounding box annotation associated
-# with an image. Each line can be parsed as:
-#
-# , , , ,
-#
-# Note that there might exist mulitple bounding box annotations associated
-# with an image file.
-tf.app.flags.DEFINE_string('bounding_box_file',
- './imagenet_2012_bounding_boxes.csv',
- 'Bounding box file')
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def _int64_feature(value):
- """Wrapper for inserting int64 features into Example proto."""
- if not isinstance(value, list):
- value = [value]
- return tf.train.Feature(int64_list=tf.train.Int64List(value=value))
-
-
-def _float_feature(value):
- """Wrapper for inserting float features into Example proto."""
- if not isinstance(value, list):
- value = [value]
- return tf.train.Feature(float_list=tf.train.FloatList(value=value))
-
-
-def _bytes_feature(value):
- """Wrapper for inserting bytes features into Example proto."""
- if six.PY3 and isinstance(value, six.text_type):
- value = six.binary_type(value, encoding='utf-8')
- return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
-
-
-def _convert_to_example(filename, image_buffer, label, synset, human, bbox,
- height, width):
- """Build an Example proto for an example.
-
- Args:
- filename: string, path to an image file, e.g., '/path/to/example.JPG'
- image_buffer: string, JPEG encoding of RGB image
- label: integer, identifier for the ground truth for the network
- synset: string, unique WordNet ID specifying the label, e.g., 'n02323233'
- human: string, human-readable label, e.g., 'red fox, Vulpes vulpes'
- bbox: list of bounding boxes; each box is a list of integers
- specifying [xmin, ymin, xmax, ymax]. All boxes are assumed to belong to
- the same label as the image label.
- height: integer, image height in pixels
- width: integer, image width in pixels
- Returns:
- Example proto
- """
- xmin = []
- ymin = []
- xmax = []
- ymax = []
- for b in bbox:
- assert len(b) == 4
- # pylint: disable=expression-not-assigned
- [l.append(point) for l, point in zip([xmin, ymin, xmax, ymax], b)]
- # pylint: enable=expression-not-assigned
-
- colorspace = 'RGB'
- channels = 3
- image_format = 'JPEG'
-
- example = tf.train.Example(features=tf.train.Features(feature={
- 'image/height': _int64_feature(height),
- 'image/width': _int64_feature(width),
- 'image/colorspace': _bytes_feature(colorspace),
- 'image/channels': _int64_feature(channels),
- 'image/class/label': _int64_feature(label),
- 'image/class/synset': _bytes_feature(synset),
- 'image/class/text': _bytes_feature(human),
- 'image/object/bbox/xmin': _float_feature(xmin),
- 'image/object/bbox/xmax': _float_feature(xmax),
- 'image/object/bbox/ymin': _float_feature(ymin),
- 'image/object/bbox/ymax': _float_feature(ymax),
- 'image/object/bbox/label': _int64_feature([label] * len(xmin)),
- 'image/format': _bytes_feature(image_format),
- 'image/filename': _bytes_feature(os.path.basename(filename)),
- 'image/encoded': _bytes_feature(image_buffer)}))
- return example
-
-
-class ImageCoder(object):
- """Helper class that provides TensorFlow image coding utilities."""
-
- def __init__(self):
- # Create a single Session to run all image coding calls.
- self._sess = tf.Session()
-
- # Initializes function that converts PNG to JPEG data.
- self._png_data = tf.placeholder(dtype=tf.string)
- image = tf.image.decode_png(self._png_data, channels=3)
- self._png_to_jpeg = tf.image.encode_jpeg(image, format='rgb', quality=100)
-
- # Initializes function that converts CMYK JPEG data to RGB JPEG data.
- self._cmyk_data = tf.placeholder(dtype=tf.string)
- image = tf.image.decode_jpeg(self._cmyk_data, channels=0)
- self._cmyk_to_rgb = tf.image.encode_jpeg(image, format='rgb', quality=100)
-
- # Initializes function that decodes RGB JPEG data.
- self._decode_jpeg_data = tf.placeholder(dtype=tf.string)
- self._decode_jpeg = tf.image.decode_jpeg(self._decode_jpeg_data, channels=3)
-
- def png_to_jpeg(self, image_data):
- return self._sess.run(self._png_to_jpeg,
- feed_dict={self._png_data: image_data})
-
- def cmyk_to_rgb(self, image_data):
- return self._sess.run(self._cmyk_to_rgb,
- feed_dict={self._cmyk_data: image_data})
-
- def decode_jpeg(self, image_data):
- image = self._sess.run(self._decode_jpeg,
- feed_dict={self._decode_jpeg_data: image_data})
- assert len(image.shape) == 3
- assert image.shape[2] == 3
- return image
-
-
-def _is_png(filename):
- """Determine if a file contains a PNG format image.
-
- Args:
- filename: string, path of the image file.
-
- Returns:
- boolean indicating if the image is a PNG.
- """
- # File list from:
- # https://groups.google.com/forum/embed/?place=forum/torch7#!topic/torch7/fOSTXHIESSU
- return 'n02105855_2933.JPEG' in filename
-
-
-def _is_cmyk(filename):
- """Determine if file contains a CMYK JPEG format image.
-
- Args:
- filename: string, path of the image file.
-
- Returns:
- boolean indicating if the image is a JPEG encoded with CMYK color space.
- """
- # File list from:
- # https://github.com/cytsai/ilsvrc-cmyk-image-list
- blacklist = ['n01739381_1309.JPEG', 'n02077923_14822.JPEG',
- 'n02447366_23489.JPEG', 'n02492035_15739.JPEG',
- 'n02747177_10752.JPEG', 'n03018349_4028.JPEG',
- 'n03062245_4620.JPEG', 'n03347037_9675.JPEG',
- 'n03467068_12171.JPEG', 'n03529860_11437.JPEG',
- 'n03544143_17228.JPEG', 'n03633091_5218.JPEG',
- 'n03710637_5125.JPEG', 'n03961711_5286.JPEG',
- 'n04033995_2932.JPEG', 'n04258138_17003.JPEG',
- 'n04264628_27969.JPEG', 'n04336792_7448.JPEG',
- 'n04371774_5854.JPEG', 'n04596742_4225.JPEG',
- 'n07583066_647.JPEG', 'n13037406_4650.JPEG']
- return filename.split('/')[-1] in blacklist
-
-
-def _process_image(filename, coder):
- """Process a single image file.
-
- Args:
- filename: string, path to an image file e.g., '/path/to/example.JPG'.
- coder: instance of ImageCoder to provide TensorFlow image coding utils.
- Returns:
- image_buffer: string, JPEG encoding of RGB image.
- height: integer, image height in pixels.
- width: integer, image width in pixels.
- """
- # Read the image file.
- with tf.gfile.FastGFile(filename, 'rb') as f:
- image_data = f.read()
-
- # Clean the dirty data.
- if _is_png(filename):
- # 1 image is a PNG.
- print('Converting PNG to JPEG for %s' % filename)
- image_data = coder.png_to_jpeg(image_data)
- elif _is_cmyk(filename):
- # 22 JPEG images are in CMYK colorspace.
- print('Converting CMYK to RGB for %s' % filename)
- image_data = coder.cmyk_to_rgb(image_data)
-
- # Decode the RGB JPEG.
- image = coder.decode_jpeg(image_data)
-
- # Check that image converted to RGB
- assert len(image.shape) == 3
- height = image.shape[0]
- width = image.shape[1]
- assert image.shape[2] == 3
-
- return image_data, height, width
-
-
-def _process_image_files_batch(coder, thread_index, ranges, name, filenames,
- synsets, labels, humans, bboxes, num_shards):
- """Processes and saves list of images as TFRecord in 1 thread.
-
- Args:
- coder: instance of ImageCoder to provide TensorFlow image coding utils.
- thread_index: integer, unique batch to run index is within [0, len(ranges)).
- ranges: list of pairs of integers specifying ranges of each batches to
- analyze in parallel.
- name: string, unique identifier specifying the data set
- filenames: list of strings; each string is a path to an image file
- synsets: list of strings; each string is a unique WordNet ID
- labels: list of integer; each integer identifies the ground truth
- humans: list of strings; each string is a human-readable label
- bboxes: list of bounding boxes for each image. Note that each entry in this
- list might contain from 0+ entries corresponding to the number of bounding
- box annotations for the image.
- num_shards: integer number of shards for this data set.
- """
- # Each thread produces N shards where N = int(num_shards / num_threads).
- # For instance, if num_shards = 128, and the num_threads = 2, then the first
- # thread would produce shards [0, 64).
- num_threads = len(ranges)
- assert not num_shards % num_threads
- num_shards_per_batch = int(num_shards / num_threads)
-
- shard_ranges = np.linspace(ranges[thread_index][0],
- ranges[thread_index][1],
- num_shards_per_batch + 1).astype(int)
- num_files_in_thread = ranges[thread_index][1] - ranges[thread_index][0]
-
- counter = 0
- for s in range(num_shards_per_batch):
- # Generate a sharded version of the file name, e.g. 'train-00002-of-00010'
- shard = thread_index * num_shards_per_batch + s
- output_filename = '%s-%.5d-of-%.5d' % (name, shard, num_shards)
- output_file = os.path.join(FLAGS.output_directory, output_filename)
- writer = tf.python_io.TFRecordWriter(output_file)
-
- shard_counter = 0
- files_in_shard = np.arange(shard_ranges[s], shard_ranges[s + 1], dtype=int)
- for i in files_in_shard:
- filename = filenames[i]
- label = labels[i]
- synset = synsets[i]
- human = humans[i]
- bbox = bboxes[i]
-
- image_buffer, height, width = _process_image(filename, coder)
-
- example = _convert_to_example(filename, image_buffer, label,
- synset, human, bbox,
- height, width)
- writer.write(example.SerializeToString())
- shard_counter += 1
- counter += 1
-
- if not counter % 1000:
- print('%s [thread %d]: Processed %d of %d images in thread batch.' %
- (datetime.now(), thread_index, counter, num_files_in_thread))
- sys.stdout.flush()
-
- writer.close()
- print('%s [thread %d]: Wrote %d images to %s' %
- (datetime.now(), thread_index, shard_counter, output_file))
- sys.stdout.flush()
- shard_counter = 0
- print('%s [thread %d]: Wrote %d images to %d shards.' %
- (datetime.now(), thread_index, counter, num_files_in_thread))
- sys.stdout.flush()
-
-
-def _process_image_files(name, filenames, synsets, labels, humans,
- bboxes, num_shards):
- """Process and save list of images as TFRecord of Example protos.
-
- Args:
- name: string, unique identifier specifying the data set
- filenames: list of strings; each string is a path to an image file
- synsets: list of strings; each string is a unique WordNet ID
- labels: list of integer; each integer identifies the ground truth
- humans: list of strings; each string is a human-readable label
- bboxes: list of bounding boxes for each image. Note that each entry in this
- list might contain from 0+ entries corresponding to the number of bounding
- box annotations for the image.
- num_shards: integer number of shards for this data set.
- """
- assert len(filenames) == len(synsets)
- assert len(filenames) == len(labels)
- assert len(filenames) == len(humans)
- assert len(filenames) == len(bboxes)
-
- # Break all images into batches with a [ranges[i][0], ranges[i][1]].
- spacing = np.linspace(0, len(filenames), FLAGS.num_threads + 1).astype(np.int)
- ranges = []
- threads = []
- for i in range(len(spacing) - 1):
- ranges.append([spacing[i], spacing[i + 1]])
-
- # Launch a thread for each batch.
- print('Launching %d threads for spacings: %s' % (FLAGS.num_threads, ranges))
- sys.stdout.flush()
-
- # Create a mechanism for monitoring when all threads are finished.
- coord = tf.train.Coordinator()
-
- # Create a generic TensorFlow-based utility for converting all image codings.
- coder = ImageCoder()
-
- threads = []
- for thread_index in range(len(ranges)):
- args = (coder, thread_index, ranges, name, filenames,
- synsets, labels, humans, bboxes, num_shards)
- t = threading.Thread(target=_process_image_files_batch, args=args)
- t.start()
- threads.append(t)
-
- # Wait for all the threads to terminate.
- coord.join(threads)
- print('%s: Finished writing all %d images in data set.' %
- (datetime.now(), len(filenames)))
- sys.stdout.flush()
-
-
-def _find_image_files(data_dir, labels_file):
- """Build a list of all images files and labels in the data set.
-
- Args:
- data_dir: string, path to the root directory of images.
-
- Assumes that the ImageNet data set resides in JPEG files located in
- the following directory structure.
-
- data_dir/n01440764/ILSVRC2012_val_00000293.JPEG
- data_dir/n01440764/ILSVRC2012_val_00000543.JPEG
-
- where 'n01440764' is the unique synset label associated with these images.
-
- labels_file: string, path to the labels file.
-
- The list of valid labels are held in this file. Assumes that the file
- contains entries as such:
- n01440764
- n01443537
- n01484850
- where each line corresponds to a label expressed as a synset. We map
- each synset contained in the file to an integer (based on the alphabetical
- ordering) starting with the integer 1 corresponding to the synset
- contained in the first line.
-
- The reason we start the integer labels at 1 is to reserve label 0 as an
- unused background class.
-
- Returns:
- filenames: list of strings; each string is a path to an image file.
- synsets: list of strings; each string is a unique WordNet ID.
- labels: list of integer; each integer identifies the ground truth.
- """
- print('Determining list of input files and labels from %s.' % data_dir)
- challenge_synsets = [l.strip() for l in
- tf.gfile.FastGFile(labels_file, 'r').readlines()]
-
- labels = []
- filenames = []
- synsets = []
-
- # Leave label index 0 empty as a background class.
- label_index = 1
-
- # Construct the list of JPEG files and labels.
- for synset in challenge_synsets:
- jpeg_file_path = '%s/%s/*.JPEG' % (data_dir, synset)
- matching_files = tf.gfile.Glob(jpeg_file_path)
-
- labels.extend([label_index] * len(matching_files))
- synsets.extend([synset] * len(matching_files))
- filenames.extend(matching_files)
-
- if not label_index % 100:
- print('Finished finding files in %d of %d classes.' % (
- label_index, len(challenge_synsets)))
- label_index += 1
-
- # Shuffle the ordering of all image files in order to guarantee
- # random ordering of the images with respect to label in the
- # saved TFRecord files. Make the randomization repeatable.
- shuffled_index = list(range(len(filenames)))
- random.seed(12345)
- random.shuffle(shuffled_index)
-
- filenames = [filenames[i] for i in shuffled_index]
- synsets = [synsets[i] for i in shuffled_index]
- labels = [labels[i] for i in shuffled_index]
-
- print('Found %d JPEG files across %d labels inside %s.' %
- (len(filenames), len(challenge_synsets), data_dir))
- return filenames, synsets, labels
-
-
-def _find_human_readable_labels(synsets, synset_to_human):
- """Build a list of human-readable labels.
-
- Args:
- synsets: list of strings; each string is a unique WordNet ID.
- synset_to_human: dict of synset to human labels, e.g.,
- 'n02119022' --> 'red fox, Vulpes vulpes'
-
- Returns:
- List of human-readable strings corresponding to each synset.
- """
- humans = []
- for s in synsets:
- assert s in synset_to_human, ('Failed to find: %s' % s)
- humans.append(synset_to_human[s])
- return humans
-
-
-def _find_image_bounding_boxes(filenames, image_to_bboxes):
- """Find the bounding boxes for a given image file.
-
- Args:
- filenames: list of strings; each string is a path to an image file.
- image_to_bboxes: dictionary mapping image file names to a list of
- bounding boxes. This list contains 0+ bounding boxes.
- Returns:
- List of bounding boxes for each image. Note that each entry in this
- list might contain from 0+ entries corresponding to the number of bounding
- box annotations for the image.
- """
- num_image_bbox = 0
- bboxes = []
- for f in filenames:
- basename = os.path.basename(f)
- if basename in image_to_bboxes:
- bboxes.append(image_to_bboxes[basename])
- num_image_bbox += 1
- else:
- bboxes.append([])
- print('Found %d images with bboxes out of %d images' % (
- num_image_bbox, len(filenames)))
- return bboxes
-
-
-def _process_dataset(name, directory, num_shards, synset_to_human,
- image_to_bboxes):
- """Process a complete data set and save it as a TFRecord.
-
- Args:
- name: string, unique identifier specifying the data set.
- directory: string, root path to the data set.
- num_shards: integer number of shards for this data set.
- synset_to_human: dict of synset to human labels, e.g.,
- 'n02119022' --> 'red fox, Vulpes vulpes'
- image_to_bboxes: dictionary mapping image file names to a list of
- bounding boxes. This list contains 0+ bounding boxes.
- """
- filenames, synsets, labels = _find_image_files(directory, FLAGS.labels_file)
- humans = _find_human_readable_labels(synsets, synset_to_human)
- bboxes = _find_image_bounding_boxes(filenames, image_to_bboxes)
- _process_image_files(name, filenames, synsets, labels,
- humans, bboxes, num_shards)
-
-
-def _build_synset_lookup(imagenet_metadata_file):
- """Build lookup for synset to human-readable label.
-
- Args:
- imagenet_metadata_file: string, path to file containing mapping from
- synset to human-readable label.
-
- Assumes each line of the file looks like:
-
- n02119247 black fox
- n02119359 silver fox
- n02119477 red fox, Vulpes fulva
-
- where each line corresponds to a unique mapping. Note that each line is
- formatted as \t.
-
- Returns:
- Dictionary of synset to human labels, such as:
- 'n02119022' --> 'red fox, Vulpes vulpes'
- """
- lines = tf.gfile.FastGFile(imagenet_metadata_file, 'r').readlines()
- synset_to_human = {}
- for l in lines:
- if l:
- parts = l.strip().split('\t')
- assert len(parts) == 2
- synset = parts[0]
- human = parts[1]
- synset_to_human[synset] = human
- return synset_to_human
-
-
-def _build_bounding_box_lookup(bounding_box_file):
- """Build a lookup from image file to bounding boxes.
-
- Args:
- bounding_box_file: string, path to file with bounding boxes annotations.
-
- Assumes each line of the file looks like:
-
- n00007846_64193.JPEG,0.0060,0.2620,0.7545,0.9940
-
- where each line corresponds to one bounding box annotation associated
- with an image. Each line can be parsed as:
-
- , , , ,
-
- Note that there might exist mulitple bounding box annotations associated
- with an image file. This file is the output of process_bounding_boxes.py.
-
- Returns:
- Dictionary mapping image file names to a list of bounding boxes. This list
- contains 0+ bounding boxes.
- """
- lines = tf.gfile.FastGFile(bounding_box_file, 'r').readlines()
- images_to_bboxes = {}
- num_bbox = 0
- num_image = 0
- for l in lines:
- if l:
- parts = l.split(',')
- assert len(parts) == 5, ('Failed to parse: %s' % l)
- filename = parts[0]
- xmin = float(parts[1])
- ymin = float(parts[2])
- xmax = float(parts[3])
- ymax = float(parts[4])
- box = [xmin, ymin, xmax, ymax]
-
- if filename not in images_to_bboxes:
- images_to_bboxes[filename] = []
- num_image += 1
- images_to_bboxes[filename].append(box)
- num_bbox += 1
-
- print('Successfully read %d bounding boxes '
- 'across %d images.' % (num_bbox, num_image))
- return images_to_bboxes
-
-
-def main(unused_argv):
- assert not FLAGS.train_shards % FLAGS.num_threads, (
- 'Please make the FLAGS.num_threads commensurate with FLAGS.train_shards')
- assert not FLAGS.validation_shards % FLAGS.num_threads, (
- 'Please make the FLAGS.num_threads commensurate with '
- 'FLAGS.validation_shards')
- print('Saving results to %s' % FLAGS.output_directory)
-
- # Build a map from synset to human-readable label.
- synset_to_human = _build_synset_lookup(FLAGS.imagenet_metadata_file)
- image_to_bboxes = _build_bounding_box_lookup(FLAGS.bounding_box_file)
-
- # Run it!
- _process_dataset('validation', FLAGS.validation_directory,
- FLAGS.validation_shards, synset_to_human, image_to_bboxes)
- _process_dataset('train', FLAGS.train_directory, FLAGS.train_shards,
- synset_to_human, image_to_bboxes)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/inception/inception/data/download_and_preprocess_flowers.sh b/research/inception/inception/data/download_and_preprocess_flowers.sh
deleted file mode 100755
index ee045c164e803ab38be69fb1933134e7f37f1793..0000000000000000000000000000000000000000
--- a/research/inception/inception/data/download_and_preprocess_flowers.sh
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/bin/bash
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-# Script to download and preprocess the flowers data set. This data set
-# provides a demonstration for how to perform fine-tuning (i.e. tranfer
-# learning) from one model to a new data set.
-#
-# This script provides a demonstration for how to prepare an arbitrary
-# data set for training an Inception v3 model.
-#
-# We demonstrate this with the flowers data set which consists of images
-# of labeled flower images from 5 classes:
-#
-# daisy, dandelion, roses, sunflowers, tulips
-#
-# The final output of this script are sharded TFRecord files containing
-# serialized Example protocol buffers. See build_image_data.py for
-# details of how the Example protocol buffer contains image data.
-#
-# usage:
-# ./download_and_preprocess_flowers.sh [data-dir]
-set -e
-
-if [ -z "$1" ]; then
- echo "Usage: download_and_preprocess_flowers.sh [data dir]"
- exit
-fi
-
-# Create the output and temporary directories.
-DATA_DIR="${1%/}"
-SCRATCH_DIR="${DATA_DIR}/raw-data"
-WORK_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
-mkdir -p "${DATA_DIR}"
-mkdir -p "${SCRATCH_DIR}"
-
-# Download the flowers data.
-DATA_URL="http://download.tensorflow.org/example_images/flower_photos.tgz"
-CURRENT_DIR=$(pwd)
-cd "${DATA_DIR}"
-TARBALL="flower_photos.tgz"
-if [ ! -f ${TARBALL} ]; then
- echo "Downloading flower data set."
- curl -o ${TARBALL} "${DATA_URL}"
-else
- echo "Skipping download of flower data."
-fi
-
-# Note the locations of the train and validation data.
-TRAIN_DIRECTORY="${SCRATCH_DIR}/train"
-VALIDATION_DIRECTORY="${SCRATCH_DIR}/validation"
-
-# Expands the data into the flower_photos/ directory and rename it as the
-# train directory.
-tar xf flower_photos.tgz
-rm -rf "${TRAIN_DIRECTORY}" "${VALIDATION_DIRECTORY}"
-mv flower_photos "${TRAIN_DIRECTORY}"
-
-# Generate a list of 5 labels: daisy, dandelion, roses, sunflowers, tulips
-LABELS_FILE="${SCRATCH_DIR}/labels.txt"
-ls -1 "${TRAIN_DIRECTORY}" | grep -v 'LICENSE' | sed 's/\///' | sort > "${LABELS_FILE}"
-
-# Generate the validation data set.
-while read LABEL; do
- VALIDATION_DIR_FOR_LABEL="${VALIDATION_DIRECTORY}/${LABEL}"
- TRAIN_DIR_FOR_LABEL="${TRAIN_DIRECTORY}/${LABEL}"
-
- # Move the first randomly selected 100 images to the validation set.
- mkdir -p "${VALIDATION_DIR_FOR_LABEL}"
- VALIDATION_IMAGES=$(ls -1 "${TRAIN_DIR_FOR_LABEL}" | shuf | head -100)
- for IMAGE in ${VALIDATION_IMAGES}; do
- mv -f "${TRAIN_DIRECTORY}/${LABEL}/${IMAGE}" "${VALIDATION_DIR_FOR_LABEL}"
- done
-done < "${LABELS_FILE}"
-
-# Build the TFRecords version of the image data.
-cd "${CURRENT_DIR}"
-BUILD_SCRIPT="${WORK_DIR}/build_image_data.py"
-OUTPUT_DIRECTORY="${DATA_DIR}"
-"${BUILD_SCRIPT}" \
- --train_directory="${TRAIN_DIRECTORY}" \
- --validation_directory="${VALIDATION_DIRECTORY}" \
- --output_directory="${OUTPUT_DIRECTORY}" \
- --labels_file="${LABELS_FILE}"
diff --git a/research/inception/inception/data/download_and_preprocess_flowers_mac.sh b/research/inception/inception/data/download_and_preprocess_flowers_mac.sh
deleted file mode 100644
index 154905635b19aeaaea087a8e76afda9b8c624d59..0000000000000000000000000000000000000000
--- a/research/inception/inception/data/download_and_preprocess_flowers_mac.sh
+++ /dev/null
@@ -1,96 +0,0 @@
-#!/bin/bash
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-# Script to download and preprocess the flowers data set. This data set
-# provides a demonstration for how to perform fine-tuning (i.e. tranfer
-# learning) from one model to a new data set.
-#
-# This script provides a demonstration for how to prepare an arbitrary
-# data set for training an Inception v3 model.
-#
-# We demonstrate this with the flowers data set which consists of images
-# of labeled flower images from 5 classes:
-#
-# daisy, dandelion, roses, sunflowers, tulips
-#
-# The final output of this script are sharded TFRecord files containing
-# serialized Example protocol buffers. See build_image_data.py for
-# details of how the Example protocol buffer contains image data.
-#
-# usage:
-# ./download_and_preprocess_flowers.sh [data-dir]
-set -e
-
-if [ -z "$1" ]; then
- echo "Usage: download_and_preprocess_flowers.sh [data dir]"
- exit
-fi
-
-# Create the output and temporary directories.
-DATA_DIR="${1%/}"
-SCRATCH_DIR="${DATA_DIR}/raw-data/"
-mkdir -p "${DATA_DIR}"
-mkdir -p "${SCRATCH_DIR}"
-WORK_DIR="$0.runfiles/inception/inception"
-
-# Download the flowers data.
-DATA_URL="http://download.tensorflow.org/example_images/flower_photos.tgz"
-CURRENT_DIR=$(pwd)
-cd "${DATA_DIR}"
-TARBALL="flower_photos.tgz"
-if [ ! -f ${TARBALL} ]; then
- echo "Downloading flower data set."
- curl -o ${TARBALL} "${DATA_URL}"
-else
- echo "Skipping download of flower data."
-fi
-
-# Note the locations of the train and validation data.
-TRAIN_DIRECTORY="${SCRATCH_DIR}train/"
-VALIDATION_DIRECTORY="${SCRATCH_DIR}validation/"
-
-# Expands the data into the flower_photos/ directory and rename it as the
-# train directory.
-tar xf flower_photos.tgz
-rm -rf "${TRAIN_DIRECTORY}" "${VALIDATION_DIRECTORY}"
-mv flower_photos "${TRAIN_DIRECTORY}"
-
-# Generate a list of 5 labels: daisy, dandelion, roses, sunflowers, tulips
-LABELS_FILE="${SCRATCH_DIR}/labels.txt"
-ls -1 "${TRAIN_DIRECTORY}" | grep -v 'LICENSE' | sed 's/\///' | sort > "${LABELS_FILE}"
-
-# Generate the validation data set.
-while read LABEL; do
- VALIDATION_DIR_FOR_LABEL="${VALIDATION_DIRECTORY}${LABEL}"
- TRAIN_DIR_FOR_LABEL="${TRAIN_DIRECTORY}${LABEL}"
-
- # Move the first randomly selected 100 images to the validation set.
- mkdir -p "${VALIDATION_DIR_FOR_LABEL}"
- VALIDATION_IMAGES=$(ls -1 "${TRAIN_DIR_FOR_LABEL}" | gshuf | head -100)
- for IMAGE in ${VALIDATION_IMAGES}; do
- mv -f "${TRAIN_DIRECTORY}${LABEL}/${IMAGE}" "${VALIDATION_DIR_FOR_LABEL}"
- done
-done < "${LABELS_FILE}"
-
-# Build the TFRecords version of the image data.
-cd "${CURRENT_DIR}"
-BUILD_SCRIPT="${WORK_DIR}/build_image_data"
-OUTPUT_DIRECTORY="${DATA_DIR}"
-"${BUILD_SCRIPT}" \
- --train_directory="${TRAIN_DIRECTORY}" \
- --validation_directory="${VALIDATION_DIRECTORY}" \
- --output_directory="${OUTPUT_DIRECTORY}" \
- --labels_file="${LABELS_FILE}"
diff --git a/research/inception/inception/data/download_and_preprocess_imagenet.sh b/research/inception/inception/data/download_and_preprocess_imagenet.sh
deleted file mode 100755
index 6faae831075d4f6bfdc8bf8797219f7a0e4c1797..0000000000000000000000000000000000000000
--- a/research/inception/inception/data/download_and_preprocess_imagenet.sh
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/bin/bash
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-# Script to download and preprocess ImageNet Challenge 2012
-# training and validation data set.
-#
-# The final output of this script are sharded TFRecord files containing
-# serialized Example protocol buffers. See build_imagenet_data.py for
-# details of how the Example protocol buffers contain the ImageNet data.
-#
-# The final output of this script appears as such:
-#
-# data_dir/train-00000-of-01024
-# data_dir/train-00001-of-01024
-# ...
-# data_dir/train-01023-of-01024
-#
-# and
-#
-# data_dir/validation-00000-of-00128
-# data_dir/validation-00001-of-00128
-# ...
-# data_dir/validation-00127-of-00128
-#
-# Note that this script may take several hours to run to completion. The
-# conversion of the ImageNet data to TFRecords alone takes 2-3 hours depending
-# on the speed of your machine. Please be patient.
-#
-# **IMPORTANT**
-# To download the raw images, the user must create an account with image-net.org
-# and generate a username and access_key. The latter two are required for
-# downloading the raw images.
-#
-# usage:
-# ./download_and_preprocess_imagenet.sh [data-dir]
-set -e
-
-if [ -z "$1" ]; then
- echo "Usage: download_and_preprocess_imagenet.sh [data dir]"
- exit
-fi
-
-# Create the output and temporary directories.
-DATA_DIR="${1%/}"
-SCRATCH_DIR="${DATA_DIR}/raw-data/"
-mkdir -p "${DATA_DIR}"
-mkdir -p "${SCRATCH_DIR}"
-WORK_DIR="$0.runfiles/inception/inception"
-
-# Download the ImageNet data.
-LABELS_FILE="${WORK_DIR}/data/imagenet_lsvrc_2015_synsets.txt"
-DOWNLOAD_SCRIPT="${WORK_DIR}/data/download_imagenet.sh"
-"${DOWNLOAD_SCRIPT}" "${SCRATCH_DIR}" "${LABELS_FILE}"
-
-# Note the locations of the train and validation data.
-TRAIN_DIRECTORY="${SCRATCH_DIR}train/"
-VALIDATION_DIRECTORY="${SCRATCH_DIR}validation/"
-
-# Preprocess the validation data by moving the images into the appropriate
-# sub-directory based on the label (synset) of the image.
-echo "Organizing the validation data into sub-directories."
-PREPROCESS_VAL_SCRIPT="${WORK_DIR}/data/preprocess_imagenet_validation_data.py"
-VAL_LABELS_FILE="${WORK_DIR}/data/imagenet_2012_validation_synset_labels.txt"
-
-"${PREPROCESS_VAL_SCRIPT}" "${VALIDATION_DIRECTORY}" "${VAL_LABELS_FILE}"
-
-# Convert the XML files for bounding box annotations into a single CSV.
-echo "Extracting bounding box information from XML."
-BOUNDING_BOX_SCRIPT="${WORK_DIR}/data/process_bounding_boxes.py"
-BOUNDING_BOX_FILE="${SCRATCH_DIR}/imagenet_2012_bounding_boxes.csv"
-BOUNDING_BOX_DIR="${SCRATCH_DIR}bounding_boxes/"
-
-"${BOUNDING_BOX_SCRIPT}" "${BOUNDING_BOX_DIR}" "${LABELS_FILE}" \
- | sort > "${BOUNDING_BOX_FILE}"
-echo "Finished downloading and preprocessing the ImageNet data."
-
-# Build the TFRecords version of the ImageNet data.
-BUILD_SCRIPT="${WORK_DIR}/build_imagenet_data"
-OUTPUT_DIRECTORY="${DATA_DIR}"
-IMAGENET_METADATA_FILE="${WORK_DIR}/data/imagenet_metadata.txt"
-
-"${BUILD_SCRIPT}" \
- --train_directory="${TRAIN_DIRECTORY}" \
- --validation_directory="${VALIDATION_DIRECTORY}" \
- --output_directory="${OUTPUT_DIRECTORY}" \
- --imagenet_metadata_file="${IMAGENET_METADATA_FILE}" \
- --labels_file="${LABELS_FILE}" \
- --bounding_box_file="${BOUNDING_BOX_FILE}"
diff --git a/research/inception/inception/data/download_imagenet.sh b/research/inception/inception/data/download_imagenet.sh
deleted file mode 100755
index f6c77781c0bcaad642ec7a38a7ba00693ef8ef83..0000000000000000000000000000000000000000
--- a/research/inception/inception/data/download_imagenet.sh
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/bin/bash
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-# Script to download ImageNet Challenge 2012 training and validation data set.
-#
-# Downloads and decompresses raw images and bounding boxes.
-#
-# **IMPORTANT**
-# To download the raw images, the user must create an account with image-net.org
-# and generate a username and access_key. The latter two are required for
-# downloading the raw images.
-#
-# usage:
-# ./download_imagenet.sh [dir name] [synsets file]
-set -e
-
-if [ "x$IMAGENET_ACCESS_KEY" == x -o "x$IMAGENET_USERNAME" == x ]; then
- cat < ')
- sys.exit(-1)
- data_dir = sys.argv[1]
- validation_labels_file = sys.argv[2]
-
- # Read in the 50000 synsets associated with the validation data set.
- labels = [l.strip() for l in open(validation_labels_file).readlines()]
- unique_labels = set(labels)
-
- # Make all sub-directories in the validation data dir.
- for label in unique_labels:
- labeled_data_dir = os.path.join(data_dir, label)
- # Catch error if sub-directory exists
- try:
- os.makedirs(labeled_data_dir)
- except OSError as e:
- # Raise all errors but 'EEXIST'
- if e.errno != errno.EEXIST:
- raise
-
- # Move all of the image to the appropriate sub-directory.
- for i in range(len(labels)):
- basename = 'ILSVRC2012_val_000%.5d.JPEG' % (i + 1)
- original_filename = os.path.join(data_dir, basename)
- if not os.path.exists(original_filename):
- print('Failed to find: %s' % original_filename)
- sys.exit(-1)
- new_filename = os.path.join(data_dir, labels[i], basename)
- os.rename(original_filename, new_filename)
diff --git a/research/inception/inception/data/process_bounding_boxes.py b/research/inception/inception/data/process_bounding_boxes.py
deleted file mode 100755
index 5e9fd786e40b6d95b89fcc9f9774aa7f132c1a6f..0000000000000000000000000000000000000000
--- a/research/inception/inception/data/process_bounding_boxes.py
+++ /dev/null
@@ -1,254 +0,0 @@
-#!/usr/bin/python
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Process the ImageNet Challenge bounding boxes for TensorFlow model training.
-
-This script is called as
-
-process_bounding_boxes.py [synsets-file]
-
-Where is a directory containing the downloaded and unpacked bounding box
-data. If [synsets-file] is supplied, then only the bounding boxes whose
-synstes are contained within this file are returned. Note that the
-[synsets-file] file contains synset ids, one per line.
-
-The script dumps out a CSV text file in which each line contains an entry.
- n00007846_64193.JPEG,0.0060,0.2620,0.7545,0.9940
-
-The entry can be read as:
- , , , ,
-
-The bounding box for contains two points (xmin, ymin) and
-(xmax, ymax) specifying the lower-left corner and upper-right corner of a
-bounding box in *relative* coordinates.
-
-The user supplies a directory where the XML files reside. The directory
-structure in the directory is assumed to look like this:
-
-/nXXXXXXXX/nXXXXXXXX_YYYY.xml
-
-Each XML file contains a bounding box annotation. The script:
-
- (1) Parses the XML file and extracts the filename, label and bounding box info.
-
- (2) The bounding box is specified in the XML files as integer (xmin, ymin) and
- (xmax, ymax) *relative* to image size displayed to the human annotator. The
- size of the image displayed to the human annotator is stored in the XML file
- as integer (height, width).
-
- Note that the displayed size will differ from the actual size of the image
- downloaded from image-net.org. To make the bounding box annotation useable,
- we convert bounding box to floating point numbers relative to displayed
- height and width of the image.
-
- Note that each XML file might contain N bounding box annotations.
-
- Note that the points are all clamped at a range of [0.0, 1.0] because some
- human annotations extend outside the range of the supplied image.
-
- See details here: http://image-net.org/download-bboxes
-
-(3) By default, the script outputs all valid bounding boxes. If a
- [synsets-file] is supplied, only the subset of bounding boxes associated
- with those synsets are outputted. Importantly, one can supply a list of
- synsets in the ImageNet Challenge and output the list of bounding boxes
- associated with the training images of the ILSVRC.
-
- We use these bounding boxes to inform the random distortion of images
- supplied to the network.
-
-If you run this script successfully, you will see the following output
-to stderr:
-> Finished processing 544546 XML files.
-> Skipped 0 XML files not in ImageNet Challenge.
-> Skipped 0 bounding boxes not in ImageNet Challenge.
-> Wrote 615299 bounding boxes from 544546 annotated images.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import glob
-import os.path
-import sys
-import xml.etree.ElementTree as ET
-
-
-class BoundingBox(object):
- pass
-
-
-def GetItem(name, root, index=0):
- count = 0
- for item in root.iter(name):
- if count == index:
- return item.text
- count += 1
- # Failed to find "index" occurrence of item.
- return -1
-
-
-def GetInt(name, root, index=0):
- # In some XML annotation files, the point values are not integers, but floats.
- # So we add a float function to avoid ValueError.
- return int(float(GetItem(name, root, index)))
-
-
-def FindNumberBoundingBoxes(root):
- index = 0
- while True:
- if GetInt('xmin', root, index) == -1:
- break
- index += 1
- return index
-
-
-def ProcessXMLAnnotation(xml_file):
- """Process a single XML file containing a bounding box."""
- # pylint: disable=broad-except
- try:
- tree = ET.parse(xml_file)
- except Exception:
- print('Failed to parse: ' + xml_file, file=sys.stderr)
- return None
- # pylint: enable=broad-except
- root = tree.getroot()
-
- num_boxes = FindNumberBoundingBoxes(root)
- boxes = []
-
- for index in range(num_boxes):
- box = BoundingBox()
- # Grab the 'index' annotation.
- box.xmin = GetInt('xmin', root, index)
- box.ymin = GetInt('ymin', root, index)
- box.xmax = GetInt('xmax', root, index)
- box.ymax = GetInt('ymax', root, index)
-
- box.width = GetInt('width', root)
- box.height = GetInt('height', root)
- box.filename = GetItem('filename', root) + '.JPEG'
- box.label = GetItem('name', root)
-
- xmin = float(box.xmin) / float(box.width)
- xmax = float(box.xmax) / float(box.width)
- ymin = float(box.ymin) / float(box.height)
- ymax = float(box.ymax) / float(box.height)
-
- # Some images contain bounding box annotations that
- # extend outside of the supplied image. See, e.g.
- # n03127925/n03127925_147.xml
- # Additionally, for some bounding boxes, the min > max
- # or the box is entirely outside of the image.
- min_x = min(xmin, xmax)
- max_x = max(xmin, xmax)
- box.xmin_scaled = min(max(min_x, 0.0), 1.0)
- box.xmax_scaled = min(max(max_x, 0.0), 1.0)
-
- min_y = min(ymin, ymax)
- max_y = max(ymin, ymax)
- box.ymin_scaled = min(max(min_y, 0.0), 1.0)
- box.ymax_scaled = min(max(max_y, 0.0), 1.0)
-
- boxes.append(box)
-
- return boxes
-
-if __name__ == '__main__':
- if len(sys.argv) < 2 or len(sys.argv) > 3:
- print('Invalid usage\n'
- 'usage: process_bounding_boxes.py [synsets-file]',
- file=sys.stderr)
- sys.exit(-1)
-
- xml_files = glob.glob(sys.argv[1] + '/*/*.xml')
- print('Identified %d XML files in %s' % (len(xml_files), sys.argv[1]),
- file=sys.stderr)
-
- if len(sys.argv) == 3:
- labels = set([l.strip() for l in open(sys.argv[2]).readlines()])
- print('Identified %d synset IDs in %s' % (len(labels), sys.argv[2]),
- file=sys.stderr)
- else:
- labels = None
-
- skipped_boxes = 0
- skipped_files = 0
- saved_boxes = 0
- saved_files = 0
- for file_index, one_file in enumerate(xml_files):
- # Example: <...>/n06470073/n00141669_6790.xml
- label = os.path.basename(os.path.dirname(one_file))
-
- # Determine if the annotation is from an ImageNet Challenge label.
- if labels is not None and label not in labels:
- skipped_files += 1
- continue
-
- bboxes = ProcessXMLAnnotation(one_file)
- assert bboxes is not None, 'No bounding boxes found in ' + one_file
-
- found_box = False
- for bbox in bboxes:
- if labels is not None:
- if bbox.label != label:
- # Note: There is a slight bug in the bounding box annotation data.
- # Many of the dog labels have the human label 'Scottish_deerhound'
- # instead of the synset ID 'n02092002' in the bbox.label field. As a
- # simple hack to overcome this issue, we only exclude bbox labels
- # *which are synset ID's* that do not match original synset label for
- # the XML file.
- if bbox.label in labels:
- skipped_boxes += 1
- continue
-
- # Guard against improperly specified boxes.
- if (bbox.xmin_scaled >= bbox.xmax_scaled or
- bbox.ymin_scaled >= bbox.ymax_scaled):
- skipped_boxes += 1
- continue
-
- # Note bbox.filename occasionally contains '%s' in the name. This is
- # data set noise that is fixed by just using the basename of the XML file.
- image_filename = os.path.splitext(os.path.basename(one_file))[0]
- print('%s.JPEG,%.4f,%.4f,%.4f,%.4f' %
- (image_filename,
- bbox.xmin_scaled, bbox.ymin_scaled,
- bbox.xmax_scaled, bbox.ymax_scaled))
-
- saved_boxes += 1
- found_box = True
- if found_box:
- saved_files += 1
- else:
- skipped_files += 1
-
- if not file_index % 5000:
- print('--> processed %d of %d XML files.' %
- (file_index + 1, len(xml_files)),
- file=sys.stderr)
- print('--> skipped %d boxes and %d XML files.' %
- (skipped_boxes, skipped_files), file=sys.stderr)
-
- print('Finished processing %d XML files.' % len(xml_files), file=sys.stderr)
- print('Skipped %d XML files not in ImageNet Challenge.' % skipped_files,
- file=sys.stderr)
- print('Skipped %d bounding boxes not in ImageNet Challenge.' % skipped_boxes,
- file=sys.stderr)
- print('Wrote %d bounding boxes from %d annotated images.' %
- (saved_boxes, saved_files),
- file=sys.stderr)
- print('Finished.', file=sys.stderr)
diff --git a/research/inception/inception/dataset.py b/research/inception/inception/dataset.py
deleted file mode 100644
index 752c97e03b0361975d64b72892cc94333e353dfb..0000000000000000000000000000000000000000
--- a/research/inception/inception/dataset.py
+++ /dev/null
@@ -1,103 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Small library that points to a data set.
-
-Methods of Data class:
- data_files: Returns a python list of all (sharded) data set files.
- num_examples_per_epoch: Returns the number of examples in the data set.
- num_classes: Returns the number of classes in the data set.
- reader: Return a reader for a single entry from the data set.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from abc import ABCMeta
-from abc import abstractmethod
-import os
-
-
-import tensorflow as tf
-
-FLAGS = tf.app.flags.FLAGS
-
-# Basic model parameters.
-tf.app.flags.DEFINE_string('data_dir', '/tmp/mydata',
- """Path to the processed data, i.e. """
- """TFRecord of Example protos.""")
-
-
-class Dataset(object):
- """A simple class for handling data sets."""
- __metaclass__ = ABCMeta
-
- def __init__(self, name, subset):
- """Initialize dataset using a subset and the path to the data."""
- assert subset in self.available_subsets(), self.available_subsets()
- self.name = name
- self.subset = subset
-
- @abstractmethod
- def num_classes(self):
- """Returns the number of classes in the data set."""
- pass
- # return 10
-
- @abstractmethod
- def num_examples_per_epoch(self):
- """Returns the number of examples in the data subset."""
- pass
- # if self.subset == 'train':
- # return 10000
- # if self.subset == 'validation':
- # return 1000
-
- @abstractmethod
- def download_message(self):
- """Prints a download message for the Dataset."""
- pass
-
- def available_subsets(self):
- """Returns the list of available subsets."""
- return ['train', 'validation']
-
- def data_files(self):
- """Returns a python list of all (sharded) data subset files.
-
- Returns:
- python list of all (sharded) data set files.
- Raises:
- ValueError: if there are not data_files matching the subset.
- """
- tf_record_pattern = os.path.join(FLAGS.data_dir, '%s-*' % self.subset)
- data_files = tf.gfile.Glob(tf_record_pattern)
- if not data_files:
- print('No files found for dataset %s/%s at %s' % (self.name,
- self.subset,
- FLAGS.data_dir))
-
- self.download_message()
- exit(-1)
- return data_files
-
- def reader(self):
- """Return a reader for a single entry from the data set.
-
- See io_ops.py for details of Reader class.
-
- Returns:
- Reader object that reads the data set.
- """
- return tf.TFRecordReader()
diff --git a/research/inception/inception/flowers_data.py b/research/inception/inception/flowers_data.py
deleted file mode 100644
index 022b5234deef035a6150a54ed74445b510f1b148..0000000000000000000000000000000000000000
--- a/research/inception/inception/flowers_data.py
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Small library that points to the flowers data set.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-
-from inception.dataset import Dataset
-
-
-class FlowersData(Dataset):
- """Flowers data set."""
-
- def __init__(self, subset):
- super(FlowersData, self).__init__('Flowers', subset)
-
- def num_classes(self):
- """Returns the number of classes in the data set."""
- return 5
-
- def num_examples_per_epoch(self):
- """Returns the number of examples in the data subset."""
- if self.subset == 'train':
- return 3170
- if self.subset == 'validation':
- return 500
-
- def download_message(self):
- """Instruction to download and extract the tarball from Flowers website."""
-
- print('Failed to find any Flowers %s files'% self.subset)
- print('')
- print('If you have already downloaded and processed the data, then make '
- 'sure to set --data_dir to point to the directory containing the '
- 'location of the sharded TFRecords.\n')
- print('Please see README.md for instructions on how to build '
- 'the flowers dataset using download_and_preprocess_flowers.\n')
diff --git a/research/inception/inception/flowers_eval.py b/research/inception/inception/flowers_eval.py
deleted file mode 100644
index ae3e9dc14c8dc83368aa83f523ade92e12113554..0000000000000000000000000000000000000000
--- a/research/inception/inception/flowers_eval.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""A binary to evaluate Inception on the flowers data set.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import tensorflow as tf
-
-from inception import inception_eval
-from inception.flowers_data import FlowersData
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def main(unused_argv=None):
- dataset = FlowersData(subset=FLAGS.subset)
- assert dataset.data_files()
- if tf.gfile.Exists(FLAGS.eval_dir):
- tf.gfile.DeleteRecursively(FLAGS.eval_dir)
- tf.gfile.MakeDirs(FLAGS.eval_dir)
- inception_eval.evaluate(dataset)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/inception/inception/flowers_train.py b/research/inception/inception/flowers_train.py
deleted file mode 100644
index 1f044a539d48ef6ce011831210b4bc31eba278f3..0000000000000000000000000000000000000000
--- a/research/inception/inception/flowers_train.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""A binary to train Inception on the flowers data set.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-
-import tensorflow as tf
-
-from inception import inception_train
-from inception.flowers_data import FlowersData
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def main(_):
- dataset = FlowersData(subset=FLAGS.subset)
- assert dataset.data_files()
- if tf.gfile.Exists(FLAGS.train_dir):
- tf.gfile.DeleteRecursively(FLAGS.train_dir)
- tf.gfile.MakeDirs(FLAGS.train_dir)
- inception_train.train(dataset)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/inception/inception/image_processing.py b/research/inception/inception/image_processing.py
deleted file mode 100644
index fe74f1b3c9958060b15f52df80b11606c7ccf343..0000000000000000000000000000000000000000
--- a/research/inception/inception/image_processing.py
+++ /dev/null
@@ -1,513 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Read and preprocess image data.
-
- Image processing occurs on a single image at a time. Image are read and
- preprocessed in parallel across multiple threads. The resulting images
- are concatenated together to form a single batch for training or evaluation.
-
- -- Provide processed image data for a network:
- inputs: Construct batches of evaluation examples of images.
- distorted_inputs: Construct batches of training examples of images.
- batch_inputs: Construct batches of training or evaluation examples of images.
-
- -- Data processing:
- parse_example_proto: Parses an Example proto containing a training example
- of an image.
-
- -- Image decoding:
- decode_jpeg: Decode a JPEG encoded string into a 3-D float32 Tensor.
-
- -- Image preprocessing:
- image_preprocessing: Decode and preprocess one image for evaluation or training
- distort_image: Distort one image for training a network.
- eval_image: Prepare one image for evaluation.
- distort_color: Distort the color in one image for training.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-FLAGS = tf.app.flags.FLAGS
-
-tf.app.flags.DEFINE_integer('batch_size', 32,
- """Number of images to process in a batch.""")
-tf.app.flags.DEFINE_integer('image_size', 299,
- """Provide square images of this size.""")
-tf.app.flags.DEFINE_integer('num_preprocess_threads', 4,
- """Number of preprocessing threads per tower. """
- """Please make this a multiple of 4.""")
-tf.app.flags.DEFINE_integer('num_readers', 4,
- """Number of parallel readers during train.""")
-
-# Images are preprocessed asynchronously using multiple threads specified by
-# --num_preprocss_threads and the resulting processed images are stored in a
-# random shuffling queue. The shuffling queue dequeues --batch_size images
-# for processing on a given Inception tower. A larger shuffling queue guarantees
-# better mixing across examples within a batch and results in slightly higher
-# predictive performance in a trained model. Empirically,
-# --input_queue_memory_factor=16 works well. A value of 16 implies a queue size
-# of 1024*16 images. Assuming RGB 299x299 images, this implies a queue size of
-# 16GB. If the machine is memory limited, then decrease this factor to
-# decrease the CPU memory footprint, accordingly.
-tf.app.flags.DEFINE_integer('input_queue_memory_factor', 16,
- """Size of the queue of preprocessed images. """
- """Default is ideal but try smaller values, e.g. """
- """4, 2 or 1, if host memory is constrained. See """
- """comments in code for more details.""")
-
-
-def inputs(dataset, batch_size=None, num_preprocess_threads=None):
- """Generate batches of ImageNet images for evaluation.
-
- Use this function as the inputs for evaluating a network.
-
- Note that some (minimal) image preprocessing occurs during evaluation
- including central cropping and resizing of the image to fit the network.
-
- Args:
- dataset: instance of Dataset class specifying the dataset.
- batch_size: integer, number of examples in batch
- num_preprocess_threads: integer, total number of preprocessing threads but
- None defaults to FLAGS.num_preprocess_threads.
-
- Returns:
- images: Images. 4D tensor of size [batch_size, FLAGS.image_size,
- image_size, 3].
- labels: 1-D integer Tensor of [FLAGS.batch_size].
- """
- if not batch_size:
- batch_size = FLAGS.batch_size
-
- # Force all input processing onto CPU in order to reserve the GPU for
- # the forward inference and back-propagation.
- with tf.device('/cpu:0'):
- images, labels = batch_inputs(
- dataset, batch_size, train=False,
- num_preprocess_threads=num_preprocess_threads,
- num_readers=1)
-
- return images, labels
-
-
-def distorted_inputs(dataset, batch_size=None, num_preprocess_threads=None):
- """Generate batches of distorted versions of ImageNet images.
-
- Use this function as the inputs for training a network.
-
- Distorting images provides a useful technique for augmenting the data
- set during training in order to make the network invariant to aspects
- of the image that do not effect the label.
-
- Args:
- dataset: instance of Dataset class specifying the dataset.
- batch_size: integer, number of examples in batch
- num_preprocess_threads: integer, total number of preprocessing threads but
- None defaults to FLAGS.num_preprocess_threads.
-
- Returns:
- images: Images. 4D tensor of size [batch_size, FLAGS.image_size,
- FLAGS.image_size, 3].
- labels: 1-D integer Tensor of [batch_size].
- """
- if not batch_size:
- batch_size = FLAGS.batch_size
-
- # Force all input processing onto CPU in order to reserve the GPU for
- # the forward inference and back-propagation.
- with tf.device('/cpu:0'):
- images, labels = batch_inputs(
- dataset, batch_size, train=True,
- num_preprocess_threads=num_preprocess_threads,
- num_readers=FLAGS.num_readers)
- return images, labels
-
-
-def decode_jpeg(image_buffer, scope=None):
- """Decode a JPEG string into one 3-D float image Tensor.
-
- Args:
- image_buffer: scalar string Tensor.
- scope: Optional scope for name_scope.
- Returns:
- 3-D float Tensor with values ranging from [0, 1).
- """
- with tf.name_scope(values=[image_buffer], name=scope,
- default_name='decode_jpeg'):
- # Decode the string as an RGB JPEG.
- # Note that the resulting image contains an unknown height and width
- # that is set dynamically by decode_jpeg. In other words, the height
- # and width of image is unknown at compile-time.
- image = tf.image.decode_jpeg(image_buffer, channels=3)
-
- # After this point, all image pixels reside in [0,1)
- # until the very end, when they're rescaled to (-1, 1). The various
- # adjust_* ops all require this range for dtype float.
- image = tf.image.convert_image_dtype(image, dtype=tf.float32)
- return image
-
-
-def distort_color(image, thread_id=0, scope=None):
- """Distort the color of the image.
-
- Each color distortion is non-commutative and thus ordering of the color ops
- matters. Ideally we would randomly permute the ordering of the color ops.
- Rather than adding that level of complication, we select a distinct ordering
- of color ops for each preprocessing thread.
-
- Args:
- image: Tensor containing single image.
- thread_id: preprocessing thread ID.
- scope: Optional scope for name_scope.
- Returns:
- color-distorted image
- """
- with tf.name_scope(values=[image], name=scope, default_name='distort_color'):
- color_ordering = thread_id % 2
-
- if color_ordering == 0:
- image = tf.image.random_brightness(image, max_delta=32. / 255.)
- image = tf.image.random_saturation(image, lower=0.5, upper=1.5)
- image = tf.image.random_hue(image, max_delta=0.2)
- image = tf.image.random_contrast(image, lower=0.5, upper=1.5)
- elif color_ordering == 1:
- image = tf.image.random_brightness(image, max_delta=32. / 255.)
- image = tf.image.random_contrast(image, lower=0.5, upper=1.5)
- image = tf.image.random_saturation(image, lower=0.5, upper=1.5)
- image = tf.image.random_hue(image, max_delta=0.2)
-
- # The random_* ops do not necessarily clamp.
- image = tf.clip_by_value(image, 0.0, 1.0)
- return image
-
-
-def distort_image(image, height, width, bbox, thread_id=0, scope=None):
- """Distort one image for training a network.
-
- Distorting images provides a useful technique for augmenting the data
- set during training in order to make the network invariant to aspects
- of the image that do not effect the label.
-
- Args:
- image: 3-D float Tensor of image
- height: integer
- width: integer
- bbox: 3-D float Tensor of bounding boxes arranged [1, num_boxes, coords]
- where each coordinate is [0, 1) and the coordinates are arranged
- as [ymin, xmin, ymax, xmax].
- thread_id: integer indicating the preprocessing thread.
- scope: Optional scope for name_scope.
- Returns:
- 3-D float Tensor of distorted image used for training.
- """
- with tf.name_scope(values=[image, height, width, bbox], name=scope,
- default_name='distort_image'):
- # Each bounding box has shape [1, num_boxes, box coords] and
- # the coordinates are ordered [ymin, xmin, ymax, xmax].
-
- # Display the bounding box in the first thread only.
- if not thread_id:
- image_with_box = tf.image.draw_bounding_boxes(tf.expand_dims(image, 0),
- bbox)
- tf.summary.image('image_with_bounding_boxes', image_with_box)
-
- # A large fraction of image datasets contain a human-annotated bounding
- # box delineating the region of the image containing the object of interest.
- # We choose to create a new bounding box for the object which is a randomly
- # distorted version of the human-annotated bounding box that obeys an allowed
- # range of aspect ratios, sizes and overlap with the human-annotated
- # bounding box. If no box is supplied, then we assume the bounding box is
- # the entire image.
- sample_distorted_bounding_box = tf.image.sample_distorted_bounding_box(
- tf.shape(image),
- bounding_boxes=bbox,
- min_object_covered=0.1,
- aspect_ratio_range=[0.75, 1.33],
- area_range=[0.05, 1.0],
- max_attempts=100,
- use_image_if_no_bounding_boxes=True)
- bbox_begin, bbox_size, distort_bbox = sample_distorted_bounding_box
- if not thread_id:
- image_with_distorted_box = tf.image.draw_bounding_boxes(
- tf.expand_dims(image, 0), distort_bbox)
- tf.summary.image('images_with_distorted_bounding_box',
- image_with_distorted_box)
-
- # Crop the image to the specified bounding box.
- distorted_image = tf.slice(image, bbox_begin, bbox_size)
-
- # This resizing operation may distort the images because the aspect
- # ratio is not respected. We select a resize method in a round robin
- # fashion based on the thread number.
- # Note that ResizeMethod contains 4 enumerated resizing methods.
- resize_method = thread_id % 4
- distorted_image = tf.image.resize_images(distorted_image, [height, width],
- method=resize_method)
- # Restore the shape since the dynamic slice based upon the bbox_size loses
- # the third dimension.
- distorted_image.set_shape([height, width, 3])
- if not thread_id:
- tf.summary.image('cropped_resized_image',
- tf.expand_dims(distorted_image, 0))
-
- # Randomly flip the image horizontally.
- distorted_image = tf.image.random_flip_left_right(distorted_image)
-
- # Randomly distort the colors.
- distorted_image = distort_color(distorted_image, thread_id)
-
- if not thread_id:
- tf.summary.image('final_distorted_image',
- tf.expand_dims(distorted_image, 0))
- return distorted_image
-
-
-def eval_image(image, height, width, scope=None):
- """Prepare one image for evaluation.
-
- Args:
- image: 3-D float Tensor
- height: integer
- width: integer
- scope: Optional scope for name_scope.
- Returns:
- 3-D float Tensor of prepared image.
- """
- with tf.name_scope(values=[image, height, width], name=scope,
- default_name='eval_image'):
- # Crop the central region of the image with an area containing 87.5% of
- # the original image.
- image = tf.image.central_crop(image, central_fraction=0.875)
-
- # Resize the image to the original height and width.
- image = tf.expand_dims(image, 0)
- image = tf.image.resize_bilinear(image, [height, width],
- align_corners=False)
- image = tf.squeeze(image, [0])
- return image
-
-
-def image_preprocessing(image_buffer, bbox, train, thread_id=0):
- """Decode and preprocess one image for evaluation or training.
-
- Args:
- image_buffer: JPEG encoded string Tensor
- bbox: 3-D float Tensor of bounding boxes arranged [1, num_boxes, coords]
- where each coordinate is [0, 1) and the coordinates are arranged as
- [ymin, xmin, ymax, xmax].
- train: boolean
- thread_id: integer indicating preprocessing thread
-
- Returns:
- 3-D float Tensor containing an appropriately scaled image
-
- Raises:
- ValueError: if user does not provide bounding box
- """
- if bbox is None:
- raise ValueError('Please supply a bounding box.')
-
- image = decode_jpeg(image_buffer)
- height = FLAGS.image_size
- width = FLAGS.image_size
-
- if train:
- image = distort_image(image, height, width, bbox, thread_id)
- else:
- image = eval_image(image, height, width)
-
- # Finally, rescale to [-1,1] instead of [0, 1)
- image = tf.subtract(image, 0.5)
- image = tf.multiply(image, 2.0)
- return image
-
-
-def parse_example_proto(example_serialized):
- """Parses an Example proto containing a training example of an image.
-
- The output of the build_image_data.py image preprocessing script is a dataset
- containing serialized Example protocol buffers. Each Example proto contains
- the following fields:
-
- image/height: 462
- image/width: 581
- image/colorspace: 'RGB'
- image/channels: 3
- image/class/label: 615
- image/class/synset: 'n03623198'
- image/class/text: 'knee pad'
- image/object/bbox/xmin: 0.1
- image/object/bbox/xmax: 0.9
- image/object/bbox/ymin: 0.2
- image/object/bbox/ymax: 0.6
- image/object/bbox/label: 615
- image/format: 'JPEG'
- image/filename: 'ILSVRC2012_val_00041207.JPEG'
- image/encoded:
-
- Args:
- example_serialized: scalar Tensor tf.string containing a serialized
- Example protocol buffer.
-
- Returns:
- image_buffer: Tensor tf.string containing the contents of a JPEG file.
- label: Tensor tf.int32 containing the label.
- bbox: 3-D float Tensor of bounding boxes arranged [1, num_boxes, coords]
- where each coordinate is [0, 1) and the coordinates are arranged as
- [ymin, xmin, ymax, xmax].
- text: Tensor tf.string containing the human-readable label.
- """
- # Dense features in Example proto.
- feature_map = {
- 'image/encoded': tf.FixedLenFeature([], dtype=tf.string,
- default_value=''),
- 'image/class/label': tf.FixedLenFeature([1], dtype=tf.int64,
- default_value=-1),
- 'image/class/text': tf.FixedLenFeature([], dtype=tf.string,
- default_value=''),
- }
- sparse_float32 = tf.VarLenFeature(dtype=tf.float32)
- # Sparse features in Example proto.
- feature_map.update(
- {k: sparse_float32 for k in ['image/object/bbox/xmin',
- 'image/object/bbox/ymin',
- 'image/object/bbox/xmax',
- 'image/object/bbox/ymax']})
-
- features = tf.parse_single_example(example_serialized, feature_map)
- label = tf.cast(features['image/class/label'], dtype=tf.int32)
-
- xmin = tf.expand_dims(features['image/object/bbox/xmin'].values, 0)
- ymin = tf.expand_dims(features['image/object/bbox/ymin'].values, 0)
- xmax = tf.expand_dims(features['image/object/bbox/xmax'].values, 0)
- ymax = tf.expand_dims(features['image/object/bbox/ymax'].values, 0)
-
- # Note that we impose an ordering of (y, x) just to make life difficult.
- bbox = tf.concat(axis=0, values=[ymin, xmin, ymax, xmax])
-
- # Force the variable number of bounding boxes into the shape
- # [1, num_boxes, coords].
- bbox = tf.expand_dims(bbox, 0)
- bbox = tf.transpose(bbox, [0, 2, 1])
-
- return features['image/encoded'], label, bbox, features['image/class/text']
-
-
-def batch_inputs(dataset, batch_size, train, num_preprocess_threads=None,
- num_readers=1):
- """Contruct batches of training or evaluation examples from the image dataset.
-
- Args:
- dataset: instance of Dataset class specifying the dataset.
- See dataset.py for details.
- batch_size: integer
- train: boolean
- num_preprocess_threads: integer, total number of preprocessing threads
- num_readers: integer, number of parallel readers
-
- Returns:
- images: 4-D float Tensor of a batch of images
- labels: 1-D integer Tensor of [batch_size].
-
- Raises:
- ValueError: if data is not found
- """
- with tf.name_scope('batch_processing'):
- data_files = dataset.data_files()
- if data_files is None:
- raise ValueError('No data files found for this dataset')
-
- # Create filename_queue
- if train:
- filename_queue = tf.train.string_input_producer(data_files,
- shuffle=True,
- capacity=16)
- else:
- filename_queue = tf.train.string_input_producer(data_files,
- shuffle=False,
- capacity=1)
- if num_preprocess_threads is None:
- num_preprocess_threads = FLAGS.num_preprocess_threads
-
- if num_preprocess_threads % 4:
- raise ValueError('Please make num_preprocess_threads a multiple '
- 'of 4 (%d % 4 != 0).', num_preprocess_threads)
-
- if num_readers is None:
- num_readers = FLAGS.num_readers
-
- if num_readers < 1:
- raise ValueError('Please make num_readers at least 1')
-
- # Approximate number of examples per shard.
- examples_per_shard = 1024
- # Size the random shuffle queue to balance between good global
- # mixing (more examples) and memory use (fewer examples).
- # 1 image uses 299*299*3*4 bytes = 1MB
- # The default input_queue_memory_factor is 16 implying a shuffling queue
- # size: examples_per_shard * 16 * 1MB = 17.6GB
- min_queue_examples = examples_per_shard * FLAGS.input_queue_memory_factor
- if train:
- examples_queue = tf.RandomShuffleQueue(
- capacity=min_queue_examples + 3 * batch_size,
- min_after_dequeue=min_queue_examples,
- dtypes=[tf.string])
- else:
- examples_queue = tf.FIFOQueue(
- capacity=examples_per_shard + 3 * batch_size,
- dtypes=[tf.string])
-
- # Create multiple readers to populate the queue of examples.
- if num_readers > 1:
- enqueue_ops = []
- for _ in range(num_readers):
- reader = dataset.reader()
- _, value = reader.read(filename_queue)
- enqueue_ops.append(examples_queue.enqueue([value]))
-
- tf.train.queue_runner.add_queue_runner(
- tf.train.queue_runner.QueueRunner(examples_queue, enqueue_ops))
- example_serialized = examples_queue.dequeue()
- else:
- reader = dataset.reader()
- _, example_serialized = reader.read(filename_queue)
-
- images_and_labels = []
- for thread_id in range(num_preprocess_threads):
- # Parse a serialized Example proto to extract the image and metadata.
- image_buffer, label_index, bbox, _ = parse_example_proto(
- example_serialized)
- image = image_preprocessing(image_buffer, bbox, train, thread_id)
- images_and_labels.append([image, label_index])
-
- images, label_index_batch = tf.train.batch_join(
- images_and_labels,
- batch_size=batch_size,
- capacity=2 * num_preprocess_threads * batch_size)
-
- # Reshape images into these desired dimensions.
- height = FLAGS.image_size
- width = FLAGS.image_size
- depth = 3
-
- images = tf.cast(images, tf.float32)
- images = tf.reshape(images, shape=[batch_size, height, width, depth])
-
- # Display the training images in the visualizer.
- tf.summary.image('images', images)
-
- return images, tf.reshape(label_index_batch, [batch_size])
diff --git a/research/inception/inception/imagenet_data.py b/research/inception/inception/imagenet_data.py
deleted file mode 100644
index 0a6d22e1292632f0899355d5aa7183c3f5f33b2c..0000000000000000000000000000000000000000
--- a/research/inception/inception/imagenet_data.py
+++ /dev/null
@@ -1,59 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Small library that points to the ImageNet data set.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-
-from inception.dataset import Dataset
-
-
-class ImagenetData(Dataset):
- """ImageNet data set."""
-
- def __init__(self, subset):
- super(ImagenetData, self).__init__('ImageNet', subset)
-
- def num_classes(self):
- """Returns the number of classes in the data set."""
- return 1000
-
- def num_examples_per_epoch(self):
- """Returns the number of examples in the data set."""
- # Bounding box data consists of 615299 bounding boxes for 544546 images.
- if self.subset == 'train':
- return 1281167
- if self.subset == 'validation':
- return 50000
-
- def download_message(self):
- """Instruction to download and extract the tarball from Flowers website."""
-
- print('Failed to find any ImageNet %s files'% self.subset)
- print('')
- print('If you have already downloaded and processed the data, then make '
- 'sure to set --data_dir to point to the directory containing the '
- 'location of the sharded TFRecords.\n')
- print('If you have not downloaded and prepared the ImageNet data in the '
- 'TFRecord format, you will need to do this at least once. This '
- 'process could take several hours depending on the speed of your '
- 'computer and network connection\n')
- print('Please see README.md for instructions on how to build '
- 'the ImageNet dataset using download_and_preprocess_imagenet.\n')
- print('Note that the raw data size is 300 GB and the processed data size '
- 'is 150 GB. Please ensure you have at least 500GB disk space.')
diff --git a/research/inception/inception/imagenet_distributed_train.py b/research/inception/inception/imagenet_distributed_train.py
deleted file mode 100644
index f3615e012f042649b52e37aeaeeb2c3efc07f92c..0000000000000000000000000000000000000000
--- a/research/inception/inception/imagenet_distributed_train.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-# pylint: disable=line-too-long
-"""A binary to train Inception in a distributed manner using multiple systems.
-
-Please see accompanying README.md for details and instructions.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-from inception import inception_distributed_train
-from inception.imagenet_data import ImagenetData
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def main(unused_args):
- assert FLAGS.job_name in ['ps', 'worker'], 'job_name must be ps or worker'
-
- # Extract all the hostnames for the ps and worker jobs to construct the
- # cluster spec.
- ps_hosts = FLAGS.ps_hosts.split(',')
- worker_hosts = FLAGS.worker_hosts.split(',')
- tf.logging.info('PS hosts are: %s' % ps_hosts)
- tf.logging.info('Worker hosts are: %s' % worker_hosts)
-
- cluster_spec = tf.train.ClusterSpec({'ps': ps_hosts,
- 'worker': worker_hosts})
- server = tf.train.Server(
- {'ps': ps_hosts,
- 'worker': worker_hosts},
- job_name=FLAGS.job_name,
- task_index=FLAGS.task_id,
- protocol=FLAGS.protocol)
-
- if FLAGS.job_name == 'ps':
- # `ps` jobs wait for incoming connections from the workers.
- server.join()
- else:
- # `worker` jobs will actually do the work.
- dataset = ImagenetData(subset=FLAGS.subset)
- assert dataset.data_files()
- # Only the chief checks for or creates train_dir.
- if FLAGS.task_id == 0:
- if not tf.gfile.Exists(FLAGS.train_dir):
- tf.gfile.MakeDirs(FLAGS.train_dir)
- inception_distributed_train.train(server.target, dataset, cluster_spec)
-
-if __name__ == '__main__':
- tf.logging.set_verbosity(tf.logging.INFO)
- tf.app.run()
diff --git a/research/inception/inception/imagenet_eval.py b/research/inception/inception/imagenet_eval.py
deleted file mode 100644
index e6f8bac2ee71021914715172296d63dd56b5a6f9..0000000000000000000000000000000000000000
--- a/research/inception/inception/imagenet_eval.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""A binary to evaluate Inception on the ImageNet data set.
-
-Note that using the supplied pre-trained inception checkpoint, the eval should
-achieve:
- precision @ 1 = 0.7874 recall @ 5 = 0.9436 [50000 examples]
-
-See the README.md for more details.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import tensorflow as tf
-
-from inception import inception_eval
-from inception.imagenet_data import ImagenetData
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def main(unused_argv=None):
- dataset = ImagenetData(subset=FLAGS.subset)
- assert dataset.data_files()
- if tf.gfile.Exists(FLAGS.eval_dir):
- tf.gfile.DeleteRecursively(FLAGS.eval_dir)
- tf.gfile.MakeDirs(FLAGS.eval_dir)
- inception_eval.evaluate(dataset)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/inception/inception/imagenet_train.py b/research/inception/inception/imagenet_train.py
deleted file mode 100644
index 3ffb55ee963e5b9f8e31915a78eef518324642aa..0000000000000000000000000000000000000000
--- a/research/inception/inception/imagenet_train.py
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""A binary to train Inception on the ImageNet data set.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-
-import tensorflow as tf
-
-from inception import inception_train
-from inception.imagenet_data import ImagenetData
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def main(_):
- dataset = ImagenetData(subset=FLAGS.subset)
- assert dataset.data_files()
- if tf.gfile.Exists(FLAGS.train_dir):
- tf.gfile.DeleteRecursively(FLAGS.train_dir)
- tf.gfile.MakeDirs(FLAGS.train_dir)
- inception_train.train(dataset)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/inception/inception/inception_distributed_train.py b/research/inception/inception/inception_distributed_train.py
deleted file mode 100644
index c1a589acb5fe386fd648ae3fae926ee927c0ca79..0000000000000000000000000000000000000000
--- a/research/inception/inception/inception_distributed_train.py
+++ /dev/null
@@ -1,314 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""A library to train Inception using multiple replicas with synchronous update.
-
-Please see accompanying README.md for details and instructions.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from datetime import datetime
-import os.path
-import time
-
-import numpy as np
-import tensorflow as tf
-
-from inception import image_processing
-from inception import inception_model as inception
-from inception.slim import slim
-
-FLAGS = tf.app.flags.FLAGS
-
-tf.app.flags.DEFINE_string('job_name', '', 'One of "ps", "worker"')
-tf.app.flags.DEFINE_string('ps_hosts', '',
- """Comma-separated list of hostname:port for the """
- """parameter server jobs. e.g. """
- """'machine1:2222,machine2:1111,machine2:2222'""")
-tf.app.flags.DEFINE_string('worker_hosts', '',
- """Comma-separated list of hostname:port for the """
- """worker jobs. e.g. """
- """'machine1:2222,machine2:1111,machine2:2222'""")
-tf.app.flags.DEFINE_string('protocol', 'grpc',
- """Communication protocol to use in distributed """
- """execution (default grpc) """)
-
-tf.app.flags.DEFINE_string('train_dir', '/tmp/imagenet_train',
- """Directory where to write event logs """
- """and checkpoint.""")
-tf.app.flags.DEFINE_integer('max_steps', 1000000, 'Number of batches to run.')
-tf.app.flags.DEFINE_string('subset', 'train', 'Either "train" or "validation".')
-tf.app.flags.DEFINE_boolean('log_device_placement', False,
- 'Whether to log device placement.')
-
-# Task ID is used to select the chief and also to access the local_step for
-# each replica to check staleness of the gradients in SyncReplicasOptimizer.
-tf.app.flags.DEFINE_integer(
- 'task_id', 0, 'Task ID of the worker/replica running the training.')
-
-# More details can be found in the SyncReplicasOptimizer class:
-# tensorflow/python/training/sync_replicas_optimizer.py
-tf.app.flags.DEFINE_integer('num_replicas_to_aggregate', -1,
- """Number of gradients to collect before """
- """updating the parameters.""")
-tf.app.flags.DEFINE_integer('save_interval_secs', 10 * 60,
- 'Save interval seconds.')
-tf.app.flags.DEFINE_integer('save_summaries_secs', 180,
- 'Save summaries interval seconds.')
-
-# **IMPORTANT**
-# Please note that this learning rate schedule is heavily dependent on the
-# hardware architecture, batch size and any changes to the model architecture
-# specification. Selecting a finely tuned learning rate schedule is an
-# empirical process that requires some experimentation. Please see README.md
-# more guidance and discussion.
-#
-# Learning rate decay factor selected from https://arxiv.org/abs/1604.00981
-tf.app.flags.DEFINE_float('initial_learning_rate', 0.045,
- 'Initial learning rate.')
-tf.app.flags.DEFINE_float('num_epochs_per_decay', 2.0,
- 'Epochs after which learning rate decays.')
-tf.app.flags.DEFINE_float('learning_rate_decay_factor', 0.94,
- 'Learning rate decay factor.')
-
-# Constants dictating the learning rate schedule.
-RMSPROP_DECAY = 0.9 # Decay term for RMSProp.
-RMSPROP_MOMENTUM = 0.9 # Momentum in RMSProp.
-RMSPROP_EPSILON = 1.0 # Epsilon term for RMSProp.
-
-
-def train(target, dataset, cluster_spec):
- """Train Inception on a dataset for a number of steps."""
- # Number of workers and parameter servers are inferred from the workers and ps
- # hosts string.
- num_workers = len(cluster_spec.as_dict()['worker'])
- num_parameter_servers = len(cluster_spec.as_dict()['ps'])
- # If no value is given, num_replicas_to_aggregate defaults to be the number of
- # workers.
- if FLAGS.num_replicas_to_aggregate == -1:
- num_replicas_to_aggregate = num_workers
- else:
- num_replicas_to_aggregate = FLAGS.num_replicas_to_aggregate
-
- # Both should be greater than 0 in a distributed training.
- assert num_workers > 0 and num_parameter_servers > 0, (' num_workers and '
- 'num_parameter_servers'
- ' must be > 0.')
-
- # Choose worker 0 as the chief. Note that any worker could be the chief
- # but there should be only one chief.
- is_chief = (FLAGS.task_id == 0)
-
- # Ops are assigned to worker by default.
- with tf.device('/job:worker/task:%d' % FLAGS.task_id):
- # Variables and its related init/assign ops are assigned to ps.
- with slim.scopes.arg_scope(
- [slim.variables.variable, slim.variables.global_step],
- device=slim.variables.VariableDeviceChooser(num_parameter_servers)):
- # Create a variable to count the number of train() calls. This equals the
- # number of updates applied to the variables.
- global_step = slim.variables.global_step()
-
- # Calculate the learning rate schedule.
- num_batches_per_epoch = (dataset.num_examples_per_epoch() /
- FLAGS.batch_size)
- # Decay steps need to be divided by the number of replicas to aggregate.
- decay_steps = int(num_batches_per_epoch * FLAGS.num_epochs_per_decay /
- num_replicas_to_aggregate)
-
- # Decay the learning rate exponentially based on the number of steps.
- lr = tf.train.exponential_decay(FLAGS.initial_learning_rate,
- global_step,
- decay_steps,
- FLAGS.learning_rate_decay_factor,
- staircase=True)
- # Add a summary to track the learning rate.
- tf.summary.scalar('learning_rate', lr)
-
- # Create an optimizer that performs gradient descent.
- opt = tf.train.RMSPropOptimizer(lr,
- RMSPROP_DECAY,
- momentum=RMSPROP_MOMENTUM,
- epsilon=RMSPROP_EPSILON)
-
- images, labels = image_processing.distorted_inputs(
- dataset,
- batch_size=FLAGS.batch_size,
- num_preprocess_threads=FLAGS.num_preprocess_threads)
-
- # Number of classes in the Dataset label set plus 1.
- # Label 0 is reserved for an (unused) background class.
- num_classes = dataset.num_classes() + 1
- logits = inception.inference(images, num_classes, for_training=True)
- # Add classification loss.
- inception.loss(logits, labels)
-
- # Gather all of the losses including regularization losses.
- losses = tf.get_collection(slim.losses.LOSSES_COLLECTION)
- losses += tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
-
- total_loss = tf.add_n(losses, name='total_loss')
-
- if is_chief:
- # Compute the moving average of all individual losses and the
- # total loss.
- loss_averages = tf.train.ExponentialMovingAverage(0.9, name='avg')
- loss_averages_op = loss_averages.apply(losses + [total_loss])
-
- # Attach a scalar summmary to all individual losses and the total loss;
- # do the same for the averaged version of the losses.
- for l in losses + [total_loss]:
- loss_name = l.op.name
- # Name each loss as '(raw)' and name the moving average version of the
- # loss as the original loss name.
- tf.summary.scalar(loss_name + ' (raw)', l)
- tf.summary.scalar(loss_name, loss_averages.average(l))
-
- # Add dependency to compute loss_averages.
- with tf.control_dependencies([loss_averages_op]):
- total_loss = tf.identity(total_loss)
-
- # Track the moving averages of all trainable variables.
- # Note that we maintain a 'double-average' of the BatchNormalization
- # global statistics.
- # This is not needed when the number of replicas are small but important
- # for synchronous distributed training with tens of workers/replicas.
- exp_moving_averager = tf.train.ExponentialMovingAverage(
- inception.MOVING_AVERAGE_DECAY, global_step)
-
- variables_to_average = (
- tf.trainable_variables() + tf.moving_average_variables())
-
- # Add histograms for model variables.
- for var in variables_to_average:
- tf.summary.histogram(var.op.name, var)
-
- # Create synchronous replica optimizer.
- opt = tf.train.SyncReplicasOptimizer(
- opt,
- replicas_to_aggregate=num_replicas_to_aggregate,
- total_num_replicas=num_workers,
- variable_averages=exp_moving_averager,
- variables_to_average=variables_to_average)
-
- batchnorm_updates = tf.get_collection(slim.ops.UPDATE_OPS_COLLECTION)
- assert batchnorm_updates, 'Batchnorm updates are missing'
- batchnorm_updates_op = tf.group(*batchnorm_updates)
- # Add dependency to compute batchnorm_updates.
- with tf.control_dependencies([batchnorm_updates_op]):
- total_loss = tf.identity(total_loss)
-
- # Compute gradients with respect to the loss.
- grads = opt.compute_gradients(total_loss)
-
- # Add histograms for gradients.
- for grad, var in grads:
- if grad is not None:
- tf.summary.histogram(var.op.name + '/gradients', grad)
-
- apply_gradients_op = opt.apply_gradients(grads, global_step=global_step)
-
- with tf.control_dependencies([apply_gradients_op]):
- train_op = tf.identity(total_loss, name='train_op')
-
- # Get chief queue_runners and init_tokens, which is used to synchronize
- # replicas. More details can be found in SyncReplicasOptimizer.
- chief_queue_runners = [opt.get_chief_queue_runner()]
- init_tokens_op = opt.get_init_tokens_op()
-
- # Create a saver.
- saver = tf.train.Saver()
-
- # Build the summary operation based on the TF collection of Summaries.
- summary_op = tf.summary.merge_all()
-
- # Build an initialization operation to run below.
- init_op = tf.global_variables_initializer()
-
- # We run the summaries in the same thread as the training operations by
- # passing in None for summary_op to avoid a summary_thread being started.
- # Running summaries and training operations in parallel could run out of
- # GPU memory.
- sv = tf.train.Supervisor(is_chief=is_chief,
- logdir=FLAGS.train_dir,
- init_op=init_op,
- summary_op=None,
- global_step=global_step,
- saver=saver,
- save_model_secs=FLAGS.save_interval_secs)
-
- tf.logging.info('%s Supervisor' % datetime.now())
-
- sess_config = tf.ConfigProto(
- allow_soft_placement=True,
- log_device_placement=FLAGS.log_device_placement)
-
- # Get a session.
- sess = sv.prepare_or_wait_for_session(target, config=sess_config)
-
- # Start the queue runners.
- queue_runners = tf.get_collection(tf.GraphKeys.QUEUE_RUNNERS)
- sv.start_queue_runners(sess, queue_runners)
- tf.logging.info('Started %d queues for processing input data.',
- len(queue_runners))
-
- if is_chief:
- sv.start_queue_runners(sess, chief_queue_runners)
- sess.run(init_tokens_op)
-
- # Train, checking for Nans. Concurrently run the summary operation at a
- # specified interval. Note that the summary_op and train_op never run
- # simultaneously in order to prevent running out of GPU memory.
- next_summary_time = time.time() + FLAGS.save_summaries_secs
- while not sv.should_stop():
- try:
- start_time = time.time()
- loss_value, step = sess.run([train_op, global_step])
- assert not np.isnan(loss_value), 'Model diverged with loss = NaN'
- if step > FLAGS.max_steps:
- break
- duration = time.time() - start_time
-
- if step % 30 == 0:
- examples_per_sec = FLAGS.batch_size / float(duration)
- format_str = ('Worker %d: %s: step %d, loss = %.2f'
- '(%.1f examples/sec; %.3f sec/batch)')
- tf.logging.info(format_str %
- (FLAGS.task_id, datetime.now(), step, loss_value,
- examples_per_sec, duration))
-
- # Determine if the summary_op should be run on the chief worker.
- if is_chief and next_summary_time < time.time():
- tf.logging.info('Running Summary operation on the chief.')
- summary_str = sess.run(summary_op)
- sv.summary_computed(sess, summary_str)
- tf.logging.info('Finished running Summary operation.')
-
- # Determine the next time for running the summary.
- next_summary_time += FLAGS.save_summaries_secs
- except:
- if is_chief:
- tf.logging.info('Chief got exception while running!')
- raise
-
- # Stop the supervisor. This also waits for service threads to finish.
- sv.stop()
-
- # Save after the training ends.
- if is_chief:
- saver.save(sess,
- os.path.join(FLAGS.train_dir, 'model.ckpt'),
- global_step=global_step)
diff --git a/research/inception/inception/inception_eval.py b/research/inception/inception/inception_eval.py
deleted file mode 100644
index e7cfc3c399dd82a915b3a49c7ddd4a8565292f69..0000000000000000000000000000000000000000
--- a/research/inception/inception/inception_eval.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""A library to evaluate Inception on a single GPU.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from datetime import datetime
-import math
-import os.path
-import time
-
-
-import numpy as np
-import tensorflow as tf
-
-from inception import image_processing
-from inception import inception_model as inception
-
-
-FLAGS = tf.app.flags.FLAGS
-
-tf.app.flags.DEFINE_string('eval_dir', '/tmp/imagenet_eval',
- """Directory where to write event logs.""")
-tf.app.flags.DEFINE_string('checkpoint_dir', '/tmp/imagenet_train',
- """Directory where to read model checkpoints.""")
-
-# Flags governing the frequency of the eval.
-tf.app.flags.DEFINE_integer('eval_interval_secs', 60 * 5,
- """How often to run the eval.""")
-tf.app.flags.DEFINE_boolean('run_once', False,
- """Whether to run eval only once.""")
-
-# Flags governing the data used for the eval.
-tf.app.flags.DEFINE_integer('num_examples', 50000,
- """Number of examples to run. Note that the eval """
- """ImageNet dataset contains 50000 examples.""")
-tf.app.flags.DEFINE_string('subset', 'validation',
- """Either 'validation' or 'train'.""")
-
-
-def _eval_once(saver, summary_writer, top_1_op, top_5_op, summary_op):
- """Runs Eval once.
-
- Args:
- saver: Saver.
- summary_writer: Summary writer.
- top_1_op: Top 1 op.
- top_5_op: Top 5 op.
- summary_op: Summary op.
- """
- with tf.Session() as sess:
- ckpt = tf.train.get_checkpoint_state(FLAGS.checkpoint_dir)
- if ckpt and ckpt.model_checkpoint_path:
- if os.path.isabs(ckpt.model_checkpoint_path):
- # Restores from checkpoint with absolute path.
- saver.restore(sess, ckpt.model_checkpoint_path)
- else:
- # Restores from checkpoint with relative path.
- saver.restore(sess, os.path.join(FLAGS.checkpoint_dir,
- ckpt.model_checkpoint_path))
-
- # Assuming model_checkpoint_path looks something like:
- # /my-favorite-path/imagenet_train/model.ckpt-0,
- # extract global_step from it.
- global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]
- print('Successfully loaded model from %s at step=%s.' %
- (ckpt.model_checkpoint_path, global_step))
- else:
- print('No checkpoint file found')
- return
-
- # Start the queue runners.
- coord = tf.train.Coordinator()
- try:
- threads = []
- for qr in tf.get_collection(tf.GraphKeys.QUEUE_RUNNERS):
- threads.extend(qr.create_threads(sess, coord=coord, daemon=True,
- start=True))
-
- num_iter = int(math.ceil(FLAGS.num_examples / FLAGS.batch_size))
- # Counts the number of correct predictions.
- count_top_1 = 0.0
- count_top_5 = 0.0
- total_sample_count = num_iter * FLAGS.batch_size
- step = 0
-
- print('%s: starting evaluation on (%s).' % (datetime.now(), FLAGS.subset))
- start_time = time.time()
- while step < num_iter and not coord.should_stop():
- top_1, top_5 = sess.run([top_1_op, top_5_op])
- count_top_1 += np.sum(top_1)
- count_top_5 += np.sum(top_5)
- step += 1
- if step % 20 == 0:
- duration = time.time() - start_time
- sec_per_batch = duration / 20.0
- examples_per_sec = FLAGS.batch_size / sec_per_batch
- print('%s: [%d batches out of %d] (%.1f examples/sec; %.3f'
- 'sec/batch)' % (datetime.now(), step, num_iter,
- examples_per_sec, sec_per_batch))
- start_time = time.time()
-
- # Compute precision @ 1.
- precision_at_1 = count_top_1 / total_sample_count
- recall_at_5 = count_top_5 / total_sample_count
- print('%s: precision @ 1 = %.4f recall @ 5 = %.4f [%d examples]' %
- (datetime.now(), precision_at_1, recall_at_5, total_sample_count))
-
- summary = tf.Summary()
- summary.ParseFromString(sess.run(summary_op))
- summary.value.add(tag='Precision @ 1', simple_value=precision_at_1)
- summary.value.add(tag='Recall @ 5', simple_value=recall_at_5)
- summary_writer.add_summary(summary, global_step)
-
- except Exception as e: # pylint: disable=broad-except
- coord.request_stop(e)
-
- coord.request_stop()
- coord.join(threads, stop_grace_period_secs=10)
-
-
-def evaluate(dataset):
- """Evaluate model on Dataset for a number of steps."""
- with tf.Graph().as_default():
- # Get images and labels from the dataset.
- images, labels = image_processing.inputs(dataset)
-
- # Number of classes in the Dataset label set plus 1.
- # Label 0 is reserved for an (unused) background class.
- num_classes = dataset.num_classes() + 1
-
- # Build a Graph that computes the logits predictions from the
- # inference model.
- logits, _ = inception.inference(images, num_classes)
-
- # Calculate predictions.
- top_1_op = tf.nn.in_top_k(logits, labels, 1)
- top_5_op = tf.nn.in_top_k(logits, labels, 5)
-
- # Restore the moving average version of the learned variables for eval.
- variable_averages = tf.train.ExponentialMovingAverage(
- inception.MOVING_AVERAGE_DECAY)
- variables_to_restore = variable_averages.variables_to_restore()
- saver = tf.train.Saver(variables_to_restore)
-
- # Build the summary operation based on the TF collection of Summaries.
- summary_op = tf.summary.merge_all()
-
- graph_def = tf.get_default_graph().as_graph_def()
- summary_writer = tf.summary.FileWriter(FLAGS.eval_dir,
- graph_def=graph_def)
-
- while True:
- _eval_once(saver, summary_writer, top_1_op, top_5_op, summary_op)
- if FLAGS.run_once:
- break
- time.sleep(FLAGS.eval_interval_secs)
diff --git a/research/inception/inception/inception_model.py b/research/inception/inception/inception_model.py
deleted file mode 100644
index fedae13ae712f09d23ff020b161d86e87ee46e95..0000000000000000000000000000000000000000
--- a/research/inception/inception/inception_model.py
+++ /dev/null
@@ -1,157 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Build the Inception v3 network on ImageNet data set.
-
-The Inception v3 architecture is described in http://arxiv.org/abs/1512.00567
-
-Summary of available functions:
- inference: Compute inference on the model inputs to make a prediction
- loss: Compute the loss of the prediction with respect to the labels
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import re
-
-import tensorflow as tf
-
-from inception.slim import slim
-
-FLAGS = tf.app.flags.FLAGS
-
-# If a model is trained using multiple GPUs, prefix all Op names with tower_name
-# to differentiate the operations. Note that this prefix is removed from the
-# names of the summaries when visualizing a model.
-TOWER_NAME = 'tower'
-
-# Batch normalization. Constant governing the exponential moving average of
-# the 'global' mean and variance for all activations.
-BATCHNORM_MOVING_AVERAGE_DECAY = 0.9997
-
-# The decay to use for the moving average.
-MOVING_AVERAGE_DECAY = 0.9999
-
-
-def inference(images, num_classes, for_training=False, restore_logits=True,
- scope=None):
- """Build Inception v3 model architecture.
-
- See here for reference: http://arxiv.org/abs/1512.00567
-
- Args:
- images: Images returned from inputs() or distorted_inputs().
- num_classes: number of classes
- for_training: If set to `True`, build the inference model for training.
- Kernels that operate differently for inference during training
- e.g. dropout, are appropriately configured.
- restore_logits: whether or not the logits layers should be restored.
- Useful for fine-tuning a model with different num_classes.
- scope: optional prefix string identifying the ImageNet tower.
-
- Returns:
- Logits. 2-D float Tensor.
- Auxiliary Logits. 2-D float Tensor of side-head. Used for training only.
- """
- # Parameters for BatchNorm.
- batch_norm_params = {
- # Decay for the moving averages.
- 'decay': BATCHNORM_MOVING_AVERAGE_DECAY,
- # epsilon to prevent 0s in variance.
- 'epsilon': 0.001,
- }
- # Set weight_decay for weights in Conv and FC layers.
- with slim.arg_scope([slim.ops.conv2d, slim.ops.fc], weight_decay=0.00004):
- with slim.arg_scope([slim.ops.conv2d],
- stddev=0.1,
- activation=tf.nn.relu,
- batch_norm_params=batch_norm_params):
- logits, endpoints = slim.inception.inception_v3(
- images,
- dropout_keep_prob=0.8,
- num_classes=num_classes,
- is_training=for_training,
- restore_logits=restore_logits,
- scope=scope)
-
- # Add summaries for viewing model statistics on TensorBoard.
- _activation_summaries(endpoints)
-
- # Grab the logits associated with the side head. Employed during training.
- auxiliary_logits = endpoints['aux_logits']
-
- return logits, auxiliary_logits
-
-
-def loss(logits, labels, batch_size=None):
- """Adds all losses for the model.
-
- Note the final loss is not returned. Instead, the list of losses are collected
- by slim.losses. The losses are accumulated in tower_loss() and summed to
- calculate the total loss.
-
- Args:
- logits: List of logits from inference(). Each entry is a 2-D float Tensor.
- labels: Labels from distorted_inputs or inputs(). 1-D tensor
- of shape [batch_size]
- batch_size: integer
- """
- if not batch_size:
- batch_size = FLAGS.batch_size
-
- # Reshape the labels into a dense Tensor of
- # shape [FLAGS.batch_size, num_classes].
- sparse_labels = tf.reshape(labels, [batch_size, 1])
- indices = tf.reshape(tf.range(batch_size), [batch_size, 1])
- concated = tf.concat(axis=1, values=[indices, sparse_labels])
- num_classes = logits[0].get_shape()[-1].value
- dense_labels = tf.sparse_to_dense(concated,
- [batch_size, num_classes],
- 1.0, 0.0)
-
- # Cross entropy loss for the main softmax prediction.
- slim.losses.cross_entropy_loss(logits[0],
- dense_labels,
- label_smoothing=0.1,
- weight=1.0)
-
- # Cross entropy loss for the auxiliary softmax head.
- slim.losses.cross_entropy_loss(logits[1],
- dense_labels,
- label_smoothing=0.1,
- weight=0.4,
- scope='aux_loss')
-
-
-def _activation_summary(x):
- """Helper to create summaries for activations.
-
- Creates a summary that provides a histogram of activations.
- Creates a summary that measure the sparsity of activations.
-
- Args:
- x: Tensor
- """
- # Remove 'tower_[0-9]/' from the name in case this is a multi-GPU training
- # session. This helps the clarity of presentation on tensorboard.
- tensor_name = re.sub('%s_[0-9]*/' % TOWER_NAME, '', x.op.name)
- tf.summary.histogram(tensor_name + '/activations', x)
- tf.summary.scalar(tensor_name + '/sparsity', tf.nn.zero_fraction(x))
-
-
-def _activation_summaries(endpoints):
- with tf.name_scope('summaries'):
- for act in endpoints.values():
- _activation_summary(act)
diff --git a/research/inception/inception/inception_train.py b/research/inception/inception/inception_train.py
deleted file mode 100644
index e1c32713b2012aec8a18637ec5dd79a1cc84d90f..0000000000000000000000000000000000000000
--- a/research/inception/inception/inception_train.py
+++ /dev/null
@@ -1,357 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""A library to train Inception using multiple GPUs with synchronous updates.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import copy
-from datetime import datetime
-import os.path
-import re
-import time
-
-import numpy as np
-import tensorflow as tf
-
-from inception import image_processing
-from inception import inception_model as inception
-from inception.slim import slim
-
-FLAGS = tf.app.flags.FLAGS
-
-tf.app.flags.DEFINE_string('train_dir', '/tmp/imagenet_train',
- """Directory where to write event logs """
- """and checkpoint.""")
-tf.app.flags.DEFINE_integer('max_steps', 10000000,
- """Number of batches to run.""")
-tf.app.flags.DEFINE_string('subset', 'train',
- """Either 'train' or 'validation'.""")
-
-# Flags governing the hardware employed for running TensorFlow.
-tf.app.flags.DEFINE_integer('num_gpus', 1,
- """How many GPUs to use.""")
-tf.app.flags.DEFINE_boolean('log_device_placement', False,
- """Whether to log device placement.""")
-
-# Flags governing the type of training.
-tf.app.flags.DEFINE_boolean('fine_tune', False,
- """If set, randomly initialize the final layer """
- """of weights in order to train the network on a """
- """new task.""")
-tf.app.flags.DEFINE_string('pretrained_model_checkpoint_path', '',
- """If specified, restore this pretrained model """
- """before beginning any training.""")
-
-# **IMPORTANT**
-# Please note that this learning rate schedule is heavily dependent on the
-# hardware architecture, batch size and any changes to the model architecture
-# specification. Selecting a finely tuned learning rate schedule is an
-# empirical process that requires some experimentation. Please see README.md
-# more guidance and discussion.
-#
-# With 8 Tesla K40's and a batch size = 256, the following setup achieves
-# precision@1 = 73.5% after 100 hours and 100K steps (20 epochs).
-# Learning rate decay factor selected from http://arxiv.org/abs/1404.5997.
-tf.app.flags.DEFINE_float('initial_learning_rate', 0.1,
- """Initial learning rate.""")
-tf.app.flags.DEFINE_float('num_epochs_per_decay', 30.0,
- """Epochs after which learning rate decays.""")
-tf.app.flags.DEFINE_float('learning_rate_decay_factor', 0.16,
- """Learning rate decay factor.""")
-
-# Constants dictating the learning rate schedule.
-RMSPROP_DECAY = 0.9 # Decay term for RMSProp.
-RMSPROP_MOMENTUM = 0.9 # Momentum in RMSProp.
-RMSPROP_EPSILON = 1.0 # Epsilon term for RMSProp.
-
-
-def _tower_loss(images, labels, num_classes, scope, reuse_variables=None):
- """Calculate the total loss on a single tower running the ImageNet model.
-
- We perform 'batch splitting'. This means that we cut up a batch across
- multiple GPUs. For instance, if the batch size = 32 and num_gpus = 2,
- then each tower will operate on an batch of 16 images.
-
- Args:
- images: Images. 4D tensor of size [batch_size, FLAGS.image_size,
- FLAGS.image_size, 3].
- labels: 1-D integer Tensor of [batch_size].
- num_classes: number of classes
- scope: unique prefix string identifying the ImageNet tower, e.g.
- 'tower_0'.
-
- Returns:
- Tensor of shape [] containing the total loss for a batch of data
- """
- # When fine-tuning a model, we do not restore the logits but instead we
- # randomly initialize the logits. The number of classes in the output of the
- # logit is the number of classes in specified Dataset.
- restore_logits = not FLAGS.fine_tune
-
- # Build inference Graph.
- with tf.variable_scope(tf.get_variable_scope(), reuse=reuse_variables):
- logits = inception.inference(images, num_classes, for_training=True,
- restore_logits=restore_logits,
- scope=scope)
-
- # Build the portion of the Graph calculating the losses. Note that we will
- # assemble the total_loss using a custom function below.
- split_batch_size = images.get_shape().as_list()[0]
- inception.loss(logits, labels, batch_size=split_batch_size)
-
- # Assemble all of the losses for the current tower only.
- losses = tf.get_collection(slim.losses.LOSSES_COLLECTION, scope)
-
- # Calculate the total loss for the current tower.
- regularization_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
- total_loss = tf.add_n(losses + regularization_losses, name='total_loss')
-
- # Compute the moving average of all individual losses and the total loss.
- loss_averages = tf.train.ExponentialMovingAverage(0.9, name='avg')
- loss_averages_op = loss_averages.apply(losses + [total_loss])
-
- # Attach a scalar summmary to all individual losses and the total loss; do the
- # same for the averaged version of the losses.
- for l in losses + [total_loss]:
- # Remove 'tower_[0-9]/' from the name in case this is a multi-GPU training
- # session. This helps the clarity of presentation on TensorBoard.
- loss_name = re.sub('%s_[0-9]*/' % inception.TOWER_NAME, '', l.op.name)
- # Name each loss as '(raw)' and name the moving average version of the loss
- # as the original loss name.
- tf.summary.scalar(loss_name +' (raw)', l)
- tf.summary.scalar(loss_name, loss_averages.average(l))
-
- with tf.control_dependencies([loss_averages_op]):
- total_loss = tf.identity(total_loss)
- return total_loss
-
-
-def _average_gradients(tower_grads):
- """Calculate the average gradient for each shared variable across all towers.
-
- Note that this function provides a synchronization point across all towers.
-
- Args:
- tower_grads: List of lists of (gradient, variable) tuples. The outer list
- is over individual gradients. The inner list is over the gradient
- calculation for each tower.
- Returns:
- List of pairs of (gradient, variable) where the gradient has been averaged
- across all towers.
- """
- average_grads = []
- for grad_and_vars in zip(*tower_grads):
- # Note that each grad_and_vars looks like the following:
- # ((grad0_gpu0, var0_gpu0), ... , (grad0_gpuN, var0_gpuN))
- grads = []
- for g, _ in grad_and_vars:
- # Add 0 dimension to the gradients to represent the tower.
- expanded_g = tf.expand_dims(g, 0)
-
- # Append on a 'tower' dimension which we will average over below.
- grads.append(expanded_g)
-
- # Average over the 'tower' dimension.
- grad = tf.concat(axis=0, values=grads)
- grad = tf.reduce_mean(grad, 0)
-
- # Keep in mind that the Variables are redundant because they are shared
- # across towers. So .. we will just return the first tower's pointer to
- # the Variable.
- v = grad_and_vars[0][1]
- grad_and_var = (grad, v)
- average_grads.append(grad_and_var)
- return average_grads
-
-
-def train(dataset):
- """Train on dataset for a number of steps."""
- with tf.Graph().as_default(), tf.device('/cpu:0'):
- # Create a variable to count the number of train() calls. This equals the
- # number of batches processed * FLAGS.num_gpus.
- global_step = tf.get_variable(
- 'global_step', [],
- initializer=tf.constant_initializer(0), trainable=False)
-
- # Calculate the learning rate schedule.
- num_batches_per_epoch = (dataset.num_examples_per_epoch() /
- FLAGS.batch_size)
- decay_steps = int(num_batches_per_epoch * FLAGS.num_epochs_per_decay)
-
- # Decay the learning rate exponentially based on the number of steps.
- lr = tf.train.exponential_decay(FLAGS.initial_learning_rate,
- global_step,
- decay_steps,
- FLAGS.learning_rate_decay_factor,
- staircase=True)
-
- # Create an optimizer that performs gradient descent.
- opt = tf.train.RMSPropOptimizer(lr, RMSPROP_DECAY,
- momentum=RMSPROP_MOMENTUM,
- epsilon=RMSPROP_EPSILON)
-
- # Get images and labels for ImageNet and split the batch across GPUs.
- assert FLAGS.batch_size % FLAGS.num_gpus == 0, (
- 'Batch size must be divisible by number of GPUs')
- split_batch_size = int(FLAGS.batch_size / FLAGS.num_gpus)
-
- # Override the number of preprocessing threads to account for the increased
- # number of GPU towers.
- num_preprocess_threads = FLAGS.num_preprocess_threads * FLAGS.num_gpus
- images, labels = image_processing.distorted_inputs(
- dataset,
- num_preprocess_threads=num_preprocess_threads)
-
- input_summaries = copy.copy(tf.get_collection(tf.GraphKeys.SUMMARIES))
-
- # Number of classes in the Dataset label set plus 1.
- # Label 0 is reserved for an (unused) background class.
- num_classes = dataset.num_classes() + 1
-
- # Split the batch of images and labels for towers.
- images_splits = tf.split(axis=0, num_or_size_splits=FLAGS.num_gpus, value=images)
- labels_splits = tf.split(axis=0, num_or_size_splits=FLAGS.num_gpus, value=labels)
-
- # Calculate the gradients for each model tower.
- tower_grads = []
- reuse_variables = None
- for i in range(FLAGS.num_gpus):
- with tf.device('/gpu:%d' % i):
- with tf.name_scope('%s_%d' % (inception.TOWER_NAME, i)) as scope:
- # Force all Variables to reside on the CPU.
- with slim.arg_scope([slim.variables.variable], device='/cpu:0'):
- # Calculate the loss for one tower of the ImageNet model. This
- # function constructs the entire ImageNet model but shares the
- # variables across all towers.
- loss = _tower_loss(images_splits[i], labels_splits[i], num_classes,
- scope, reuse_variables)
-
- # Reuse variables for the next tower.
- reuse_variables = True
-
- # Retain the summaries from the final tower.
- summaries = tf.get_collection(tf.GraphKeys.SUMMARIES, scope)
-
- # Retain the Batch Normalization updates operations only from the
- # final tower. Ideally, we should grab the updates from all towers
- # but these stats accumulate extremely fast so we can ignore the
- # other stats from the other towers without significant detriment.
- batchnorm_updates = tf.get_collection(slim.ops.UPDATE_OPS_COLLECTION,
- scope)
-
- # Calculate the gradients for the batch of data on this ImageNet
- # tower.
- grads = opt.compute_gradients(loss)
-
- # Keep track of the gradients across all towers.
- tower_grads.append(grads)
-
- # We must calculate the mean of each gradient. Note that this is the
- # synchronization point across all towers.
- grads = _average_gradients(tower_grads)
-
- # Add a summaries for the input processing and global_step.
- summaries.extend(input_summaries)
-
- # Add a summary to track the learning rate.
- summaries.append(tf.summary.scalar('learning_rate', lr))
-
- # Add histograms for gradients.
- for grad, var in grads:
- if grad is not None:
- summaries.append(
- tf.summary.histogram(var.op.name + '/gradients', grad))
-
- # Apply the gradients to adjust the shared variables.
- apply_gradient_op = opt.apply_gradients(grads, global_step=global_step)
-
- # Add histograms for trainable variables.
- for var in tf.trainable_variables():
- summaries.append(tf.summary.histogram(var.op.name, var))
-
- # Track the moving averages of all trainable variables.
- # Note that we maintain a "double-average" of the BatchNormalization
- # global statistics. This is more complicated then need be but we employ
- # this for backward-compatibility with our previous models.
- variable_averages = tf.train.ExponentialMovingAverage(
- inception.MOVING_AVERAGE_DECAY, global_step)
-
- # Another possibility is to use tf.slim.get_variables().
- variables_to_average = (tf.trainable_variables() +
- tf.moving_average_variables())
- variables_averages_op = variable_averages.apply(variables_to_average)
-
- # Group all updates to into a single train op.
- batchnorm_updates_op = tf.group(*batchnorm_updates)
- train_op = tf.group(apply_gradient_op, variables_averages_op,
- batchnorm_updates_op)
-
- # Create a saver.
- saver = tf.train.Saver(tf.global_variables())
-
- # Build the summary operation from the last tower summaries.
- summary_op = tf.summary.merge(summaries)
-
- # Build an initialization operation to run below.
- init = tf.global_variables_initializer()
-
- # Start running operations on the Graph. allow_soft_placement must be set to
- # True to build towers on GPU, as some of the ops do not have GPU
- # implementations.
- sess = tf.Session(config=tf.ConfigProto(
- allow_soft_placement=True,
- log_device_placement=FLAGS.log_device_placement))
- sess.run(init)
-
- if FLAGS.pretrained_model_checkpoint_path:
- assert tf.gfile.Exists(FLAGS.pretrained_model_checkpoint_path)
- variables_to_restore = tf.get_collection(
- slim.variables.VARIABLES_TO_RESTORE)
- restorer = tf.train.Saver(variables_to_restore)
- restorer.restore(sess, FLAGS.pretrained_model_checkpoint_path)
- print('%s: Pre-trained model restored from %s' %
- (datetime.now(), FLAGS.pretrained_model_checkpoint_path))
-
- # Start the queue runners.
- tf.train.start_queue_runners(sess=sess)
-
- summary_writer = tf.summary.FileWriter(
- FLAGS.train_dir,
- graph=sess.graph)
-
- for step in range(FLAGS.max_steps):
- start_time = time.time()
- _, loss_value = sess.run([train_op, loss])
- duration = time.time() - start_time
-
- assert not np.isnan(loss_value), 'Model diverged with loss = NaN'
-
- if step % 10 == 0:
- examples_per_sec = FLAGS.batch_size / float(duration)
- format_str = ('%s: step %d, loss = %.2f (%.1f examples/sec; %.3f '
- 'sec/batch)')
- print(format_str % (datetime.now(), step, loss_value,
- examples_per_sec, duration))
-
- if step % 100 == 0:
- summary_str = sess.run(summary_op)
- summary_writer.add_summary(summary_str, step)
-
- # Save the model checkpoint periodically.
- if step % 5000 == 0 or (step + 1) == FLAGS.max_steps:
- checkpoint_path = os.path.join(FLAGS.train_dir, 'model.ckpt')
- saver.save(sess, checkpoint_path, global_step=step)
diff --git a/research/inception/inception/slim/BUILD b/research/inception/inception/slim/BUILD
deleted file mode 100644
index 174e77d5c2654380232174a2bb8b29c6b9affc5d..0000000000000000000000000000000000000000
--- a/research/inception/inception/slim/BUILD
+++ /dev/null
@@ -1,112 +0,0 @@
-# Description:
-# Contains the operations and nets for building TensorFlow-Slim models.
-
-package(default_visibility = ["//inception:internal"])
-
-licenses(["notice"]) # Apache 2.0
-
-exports_files(["LICENSE"])
-
-py_library(
- name = "scopes",
- srcs = ["scopes.py"],
-)
-
-py_test(
- name = "scopes_test",
- size = "small",
- srcs = ["scopes_test.py"],
- deps = [
- ":scopes",
- ],
-)
-
-py_library(
- name = "variables",
- srcs = ["variables.py"],
- deps = [
- ":scopes",
- ],
-)
-
-py_test(
- name = "variables_test",
- size = "small",
- srcs = ["variables_test.py"],
- deps = [
- ":variables",
- ],
-)
-
-py_library(
- name = "losses",
- srcs = ["losses.py"],
-)
-
-py_test(
- name = "losses_test",
- size = "small",
- srcs = ["losses_test.py"],
- deps = [
- ":losses",
- ],
-)
-
-py_library(
- name = "ops",
- srcs = ["ops.py"],
- deps = [
- ":losses",
- ":scopes",
- ":variables",
- ],
-)
-
-py_test(
- name = "ops_test",
- size = "small",
- srcs = ["ops_test.py"],
- deps = [
- ":ops",
- ":variables",
- ],
-)
-
-py_library(
- name = "inception",
- srcs = ["inception_model.py"],
- deps = [
- ":ops",
- ":scopes",
- ],
-)
-
-py_test(
- name = "inception_test",
- size = "medium",
- srcs = ["inception_test.py"],
- deps = [
- ":inception",
- ],
-)
-
-py_library(
- name = "slim",
- srcs = ["slim.py"],
- deps = [
- ":inception",
- ":losses",
- ":ops",
- ":scopes",
- ":variables",
- ],
-)
-
-py_test(
- name = "collections_test",
- size = "small",
- srcs = ["collections_test.py"],
- deps = [
- ":slim",
- ],
-)
diff --git a/research/inception/inception/slim/README.md b/research/inception/inception/slim/README.md
deleted file mode 100644
index 36d8b7eb19ae47d8810ed97abe203aa34be50a75..0000000000000000000000000000000000000000
--- a/research/inception/inception/slim/README.md
+++ /dev/null
@@ -1,621 +0,0 @@
-# TensorFlow-Slim
-
-TF-Slim is a lightweight library for defining, training and evaluating models in
-TensorFlow. It enables defining complex networks quickly and concisely while
-keeping a model's architecture transparent and its hyperparameters explicit.
-
-[TOC]
-
-## Teaser
-
-As a demonstration of the simplicity of using TF-Slim, compare the simplicity of
-the code necessary for defining the entire [VGG](http://www.robots.ox.ac.uk/~vgg/research/very_deep/) network using TF-Slim to
-the lengthy and verbose nature of defining just the first three layers (out of
-16) using native tensorflow:
-
-```python{.good}
-# VGG16 in TF-Slim.
-def vgg16(inputs):
- with slim.arg_scope([slim.ops.conv2d, slim.ops.fc], stddev=0.01, weight_decay=0.0005):
- net = slim.ops.repeat_op(2, inputs, slim.ops.conv2d, 64, [3, 3], scope='conv1')
- net = slim.ops.max_pool(net, [2, 2], scope='pool1')
- net = slim.ops.repeat_op(2, net, slim.ops.conv2d, 128, [3, 3], scope='conv2')
- net = slim.ops.max_pool(net, [2, 2], scope='pool2')
- net = slim.ops.repeat_op(3, net, slim.ops.conv2d, 256, [3, 3], scope='conv3')
- net = slim.ops.max_pool(net, [2, 2], scope='pool3')
- net = slim.ops.repeat_op(3, net, slim.ops.conv2d, 512, [3, 3], scope='conv4')
- net = slim.ops.max_pool(net, [2, 2], scope='pool4')
- net = slim.ops.repeat_op(3, net, slim.ops.conv2d, 512, [3, 3], scope='conv5')
- net = slim.ops.max_pool(net, [2, 2], scope='pool5')
- net = slim.ops.flatten(net, scope='flatten5')
- net = slim.ops.fc(net, 4096, scope='fc6')
- net = slim.ops.dropout(net, 0.5, scope='dropout6')
- net = slim.ops.fc(net, 4096, scope='fc7')
- net = slim.ops.dropout(net, 0.5, scope='dropout7')
- net = slim.ops.fc(net, 1000, activation=None, scope='fc8')
- return net
-```
-
-```python{.bad}
-# Layers 1-3 (out of 16) of VGG16 in native tensorflow.
-def vgg16(inputs):
- with tf.name_scope('conv1_1') as scope:
- kernel = tf.Variable(tf.truncated_normal([3, 3, 3, 64], dtype=tf.float32, stddev=1e-1), name='weights')
- conv = tf.nn.conv2d(inputs, kernel, [1, 1, 1, 1], padding='SAME')
- biases = tf.Variable(tf.constant(0.0, shape=[64], dtype=tf.float32), trainable=True, name='biases')
- bias = tf.nn.bias_add(conv, biases)
- conv1 = tf.nn.relu(bias, name=scope)
- with tf.name_scope('conv1_2') as scope:
- kernel = tf.Variable(tf.truncated_normal([3, 3, 64, 64], dtype=tf.float32, stddev=1e-1), name='weights')
- conv = tf.nn.conv2d(images, kernel, [1, 1, 1, 1], padding='SAME')
- biases = tf.Variable(tf.constant(0.0, shape=[64], dtype=tf.float32), trainable=True, name='biases')
- bias = tf.nn.bias_add(conv, biases)
- conv1 = tf.nn.relu(bias, name=scope)
- with tf.name_scope('pool1')
- pool1 = tf.nn.max_pool(conv1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='VALID', name='pool1')
-```
-
-## Why TF-Slim?
-
-TF-Slim offers several advantages over just the built-in tensorflow libraries:
-
-* Allows one to define models much more compactly by eliminating boilerplate
- code. This is accomplished through the use of [argument scoping](./scopes.py)
- and numerous high level [operations](./ops.py). These tools increase
- readability and maintainability, reduce the likelihood of an error from
- copy-and-pasting hyperparameter values and simplifies hyperparameter tuning.
-* Makes developing models simple by providing commonly used [loss functions](./losses.py)
-* Provides a concise [definition](./inception_model.py) of [Inception v3](http://arxiv.org/abs/1512.00567) network architecture ready to be used
- out-of-the-box or subsumed into new models.
-
-Additionally TF-Slim was designed with several principles in mind:
-
-* The various modules of TF-Slim (scopes, variables, ops, losses) are
- independent. This flexibility allows users to pick and choose components of
- TF-Slim completely à la carte.
-* TF-Slim is written using a Functional Programming style. That means it's
- super-lightweight and can be used right alongside any of TensorFlow's native
- operations.
-* Makes re-using network architectures easy. This allows users to build new
- networks on top of existing ones as well as fine-tuning pre-trained models
- on new tasks.
-
-## What are the various components of TF-Slim?
-
-TF-Slim is composed of several parts which were designed to exist independently.
-These include:
-
-* [scopes.py](./scopes.py): provides a new scope named `arg_scope` that allows
- a user to define default arguments for specific operations within that
- scope.
-* [variables.py](./variables.py): provides convenience wrappers for variable
- creation and manipulation.
-* [ops.py](./ops.py): provides high level operations for building models using
- tensorflow.
-* [losses.py](./losses.py): contains commonly used loss functions.
-
-## Defining Models
-
-Models can be succinctly defined using TF-Slim by combining its variables,
-operations and scopes. Each of these elements are defined below.
-
-### Variables
-
-Creating [`Variables`](https://www.tensorflow.org/how_tos/variables/index.html)
-in native tensorflow requires either a predefined value or an initialization
-mechanism (random, normally distributed). Furthermore, if a variable needs to be
-created on a specific device, such as a GPU, the specification must be [made
-explicit](https://www.tensorflow.org/how_tos/using_gpu/index.html). To alleviate
-the code required for variable creation, TF-Slim provides a set of thin wrapper
-functions in [variables.py](./variables.py) which allow callers to easily define
-variables.
-
-For example, to create a `weight` variable, initialize it using a truncated
-normal distribution, regularize it with an `l2_loss` and place it on the `CPU`,
-one need only declare the following:
-
-```python
-weights = variables.variable('weights',
- shape=[10, 10, 3 , 3],
- initializer=tf.truncated_normal_initializer(stddev=0.1),
- regularizer=lambda t: losses.l2_loss(t, weight=0.05),
- device='/cpu:0')
-```
-
-In addition to the functionality provided by `tf.Variable`, `slim.variables`
-keeps track of the variables created by `slim.ops` to define a model, which
-allows one to distinguish variables that belong to the model versus other
-variables.
-
-```python
-# Get all the variables defined by the model.
-model_variables = slim.variables.get_variables()
-
-# Get all the variables with the same given name, i.e. 'weights', 'biases'.
-weights = slim.variables.get_variables_by_name('weights')
-biases = slim.variables.get_variables_by_name('biases')
-
-# Get all the variables in VARIABLES_TO_RESTORE collection.
-variables_to_restore = tf.get_collection(slim.variables.VARIABLES_TO_RESTORE)
-
-
-weights = variables.variable('weights',
- shape=[10, 10, 3 , 3],
- initializer=tf.truncated_normal_initializer(stddev=0.1),
- regularizer=lambda t: losses.l2_loss(t, weight=0.05),
- device='/cpu:0')
-```
-
-### Operations (Layers)
-
-While the set of TensorFlow operations is quite extensive, builders of neural
-networks typically think of models in terms of "layers". A layer, such as a
-Convolutional Layer, a Fully Connected Layer or a BatchNorm Layer are more
-abstract than a single TensorFlow operation and typically involve many such
-operations. For example, a Convolutional Layer in a neural network is built
-using several steps:
-
-1. Creating the weight variables
-2. Creating the bias variables
-3. Convolving the weights with the input from the previous layer
-4. Adding the biases to the result of the convolution.
-
-In python code this can be rather laborious:
-
-```python
-input = ...
-with tf.name_scope('conv1_1') as scope:
- kernel = tf.Variable(tf.truncated_normal([3, 3, 64, 128], dtype=tf.float32,
- stddev=1e-1), name='weights')
- conv = tf.nn.conv2d(input, kernel, [1, 1, 1, 1], padding='SAME')
- biases = tf.Variable(tf.constant(0.0, shape=[128], dtype=tf.float32),
- trainable=True, name='biases')
- bias = tf.nn.bias_add(conv, biases)
- conv1 = tf.nn.relu(bias, name=scope)
-```
-
-To alleviate the need to duplicate this code repeatedly, TF-Slim provides a
-number of convenient operations defined at the (more abstract) level of neural
-network layers. For example, compare the code above to an invocation of the
-TF-Slim code:
-
-```python
-input = ...
-net = slim.ops.conv2d(input, [3, 3], 128, scope='conv1_1')
-```
-
-TF-Slim provides numerous operations used in building neural networks which
-roughly correspond to such layers. These include:
-
-Layer | TF-Slim Op
---------------------- | ------------------------
-Convolutional Layer | [ops.conv2d](./ops.py)
-Fully Connected Layer | [ops.fc](./ops.py)
-BatchNorm layer | [ops.batch_norm](./ops.py)
-Max Pooling Layer | [ops.max_pool](./ops.py)
-Avg Pooling Layer | [ops.avg_pool](./ops.py)
-Dropout Layer | [ops.dropout](./ops.py)
-
-[ops.py](./ops.py) also includes operations that are not really "layers" per se,
-but are often used to manipulate hidden unit representations during inference:
-
-Operation | TF-Slim Op
---------- | ---------------------
-Flatten | [ops.flatten](./ops.py)
-
-TF-Slim also provides a meta-operation called `repeat_op` that allows one to
-repeatedly perform the same operation. Consider the following snippet from the
-[VGG](https://www.robots.ox.ac.uk/~vgg/research/very_deep/) network whose layers
-perform several convolutions in a row between pooling layers:
-
-```python
-net = ...
-net = slim.ops.conv2d(net, 256, [3, 3], scope='conv3_1')
-net = slim.ops.conv2d(net, 256, [3, 3], scope='conv3_2')
-net = slim.ops.conv2d(net, 256, [3, 3], scope='conv3_3')
-net = slim.ops.max_pool(net, [2, 2], scope='pool3')
-```
-
-This clear duplication of code can be removed via a standard loop:
-
-```python
-net = ...
-for i in range(3):
- net = slim.ops.conv2d(net, 256, [3, 3], scope='conv3_' % (i+1))
-net = slim.ops.max_pool(net, [2, 2], scope='pool3')
-```
-
-While this does reduce the amount of duplication, it can be made even cleaner by
-using the `RepeatOp`:
-
-```python
-net = slim.ops.repeat_op(3, net, slim.ops.conv2d, 256, [3, 3], scope='conv3')
-net = slim.ops.max_pool(net, [2, 2], scope='pool2')
-```
-
-Notice that the RepeatOp not only applies the same argument in-line, it also is
-smart enough to unroll the scopes such that the scopes assigned to each
-subsequent call of `ops.conv2d` is appended with an underscore and iteration
-number. More concretely, the scopes in the example above would be 'conv3_1',
-'conv3_2' and 'conv3_3'.
-
-### Scopes
-
-In addition to the types of scope mechanisms in TensorFlow ([name_scope](https://www.tensorflow.org/api_docs/python/framework.html#name_scope),
-[variable_scope](https://www.tensorflow.org/api_docs/python/state_ops.html#variable_scope),
-TF-Slim adds a new scoping mechanism called "argument scope" or [arg_scope](./scopes.py). This new scope allows a user to specify one or more operations and
-a set of arguments which will be passed to each of the operations defined in the
-`arg_scope`. This functionality is best illustrated by example. Consider the
-following code snippet:
-
-```python
-net = slim.ops.conv2d(inputs, 64, [11, 11], 4, padding='SAME', stddev=0.01, weight_decay=0.0005, scope='conv1')
-net = slim.ops.conv2d(net, 128, [11, 11], padding='VALID', stddev=0.01, weight_decay=0.0005, scope='conv2')
-net = slim.ops.conv2d(net, 256, [11, 11], padding='SAME', stddev=0.01, weight_decay=0.0005, scope='conv3')
-```
-
-It should be clear that these three Convolution layers share many of the same
-hyperparameters. Two have the same padding, all three have the same weight_decay
-and standard deviation of its weights. Not only do the duplicated values make
-the code more difficult to read, it also adds the addition burder to the writer
-of needing to doublecheck that all of the values are identical in each step. One
-solution would be to specify default values using variables:
-
-```python
-padding='SAME'
-stddev=0.01
-weight_decay=0.0005
-net = slim.ops.conv2d(inputs, 64, [11, 11], 4, padding=padding, stddev=stddev, weight_decay=weight_decay, scope='conv1')
-net = slim.ops.conv2d(net, 128, [11, 11], padding='VALID', stddev=stddev, weight_decay=weight_decay, scope='conv2')
-net = slim.ops.conv2d(net, 256, [11, 11], padding=padding, stddev=stddev, weight_decay=weight_decay, scope='conv3')
-
-```
-
-This solution ensures that all three convolutions share the exact same variable
-values but doesn't reduce the code clutter. By using an `arg_scope`, we can both
-ensure that each layer uses the same values and simplify the code:
-
-```python
- with slim.arg_scope([slim.ops.conv2d], padding='SAME', stddev=0.01, weight_decay=0.0005):
- net = slim.ops.conv2d(inputs, 64, [11, 11], scope='conv1')
- net = slim.ops.conv2d(net, 128, [11, 11], padding='VALID', scope='conv2')
- net = slim.ops.conv2d(net, 256, [11, 11], scope='conv3')
-```
-
-As the example illustrates, the use of arg_scope makes the code cleaner, simpler
-and easier to maintain. Notice that while argument values are specifed in the
-arg_scope, they can be overwritten locally. In particular, while the padding
-argument has been set to 'SAME', the second convolution overrides it with the
-value of 'VALID'.
-
-One can also nest `arg_scope`s and use multiple operations in the same scope.
-For example:
-
-```python
-with arg_scope([slim.ops.conv2d, slim.ops.fc], stddev=0.01, weight_decay=0.0005):
- with arg_scope([slim.ops.conv2d], padding='SAME'), slim.arg_scope([slim.ops.fc], bias=1.0):
- net = slim.ops.conv2d(inputs, 64, [11, 11], 4, padding='VALID', scope='conv1')
- net = slim.ops.conv2d(net, 256, [5, 5], stddev=0.03, scope='conv2')
- net = slim.ops.flatten(net)
- net = slim.ops.fc(net, 1000, activation=None, scope='fc')
-```
-
-In this example, the first `arg_scope` applies the same `stddev` and
-`weight_decay` arguments to the `conv2d` and `fc` ops in its scope. In the
-second `arg_scope`, additional default arguments to `conv2d` only are specified.
-
-In addition to `arg_scope`, TF-Slim provides several decorators that wrap the
-use of tensorflow arg scopes. These include `@AddArgScope`, `@AddNameScope`,
-`@AddVariableScope`, `@AddOpScope` and `@AddVariableOpScope`. To illustrate
-their use, consider the following example.
-
-```python
-def MyNewOp(inputs):
- varA = ...
- varB = ...
- outputs = tf.multiply(varA, inputs) + varB
- return outputs
-
-```
-
-In this example, the user has created a new op which creates two variables. To
-ensure that these variables exist within a certain variable scope (to avoid
-collisions with variables with the same name), in standard TF, the op must be
-called within a variable scope:
-
-```python
-inputs = ...
-with tf.variable_scope('layer1'):
- outputs = MyNewOp(inputs)
-```
-
-As an alternative, one can use TF-Slim's decorators to decorate the function and
-simplify the call:
-
-```python
-@AddVariableScope
-def MyNewOp(inputs):
- ...
- return outputs
-
-
-inputs = ...
-outputs = MyNewOp('layer1')
-```
-
-The `@AddVariableScope` decorater simply applies the `tf.variable_scope` scoping
-to the called function taking "layer1" as its argument. This allows the code to
-be written more concisely.
-
-### Losses
-
-The loss function defines a quantity that we want to minimize. For
-classification problems, this is typically the cross entropy between the true
-(one-hot) distribution and the predicted probability distribution across
-classes. For regression problems, this is often the sum-of-squares differences
-between the predicted and true values.
-
-Certain models, such as multi-task learning models, require the use of multiple
-loss functions simultaneously. In other words, the loss function ultimatey being
-minimized is the sum of various other loss functions. For example, consider a
-model that predicts both the type of scene in an image as well as the depth from
-the camera of each pixel. This model's loss function would be the sum of the
-classification loss and depth prediction loss.
-
-TF-Slim provides an easy-to-use mechanism for defining and keeping track of loss
-functions via the [losses.py](./losses.py) module. Consider the simple case
-where we want to train the VGG network:
-
-```python
-# Load the images and labels.
-images, labels = ...
-
-# Create the model.
-predictions = ...
-
-# Define the loss functions and get the total loss.
-loss = losses.cross_entropy_loss(predictions, labels)
-```
-
-In this example, we start by creating the model (using TF-Slim's VGG
-implementation), and add the standard classification loss. Now, lets turn to the
-case where we have a multi-task model that produces multiple outputs:
-
-```python
-# Load the images and labels.
-images, scene_labels, depth_labels = ...
-
-# Create the model.
-scene_predictions, depth_predictions = CreateMultiTaskModel(images)
-
-# Define the loss functions and get the total loss.
-classification_loss = slim.losses.cross_entropy_loss(scene_predictions, scene_labels)
-sum_of_squares_loss = slim.losses.l2loss(depth_predictions - depth_labels)
-
-# The following two lines have the same effect:
-total_loss1 = classification_loss + sum_of_squares_loss
-total_loss2 = tf.get_collection(slim.losses.LOSSES_COLLECTION)
-```
-
-In this example, we have two losses which we add by calling
-`losses.cross_entropy_loss` and `losses.l2loss`. We can obtain the
-total loss by adding them together (`total_loss1`) or by calling
-`losses.GetTotalLoss()`. How did this work? When you create a loss function via
-TF-Slim, TF-Slim adds the loss to a special TensorFlow collection of loss
-functions. This enables you to either manage the total loss manually, or allow
-TF-Slim to manage them for you.
-
-What if you want to let TF-Slim manage the losses for you but have a custom loss
-function? [losses.py](./losses.py) also has a function that adds this loss to
-TF-Slims collection. For example:
-
-```python
-# Load the images and labels.
-images, scene_labels, depth_labels, pose_labels = ...
-
-# Create the model.
-scene_predictions, depth_predictions, pose_predictions = CreateMultiTaskModel(images)
-
-# Define the loss functions and get the total loss.
-classification_loss = slim.losses.cross_entropy_loss(scene_predictions, scene_labels)
-sum_of_squares_loss = slim.losses.l2loss(depth_predictions - depth_labels)
-pose_loss = MyCustomLossFunction(pose_predictions, pose_labels)
-tf.add_to_collection(slim.losses.LOSSES_COLLECTION, pose_loss) # Letting TF-Slim know about the additional loss.
-
-# The following two lines have the same effect:
-total_loss1 = classification_loss + sum_of_squares_loss + pose_loss
-total_loss2 = losses.GetTotalLoss()
-```
-
-In this example, we can again either produce the total loss function manually or
-let TF-Slim know about the additional loss and let TF-Slim handle the losses.
-
-## Putting the Pieces Together
-
-By combining TF-Slim Variables, Operations and scopes, we can write a normally
-very complex network with very few lines of code. For example, the entire [VGG](https://www.robots.ox.ac.uk/~vgg/research/very_deep/) architecture can be
-defined with just the following snippet:
-
-```python
-with arg_scope([slim.ops.conv2d, slim.ops.fc], stddev=0.01, weight_decay=0.0005):
- net = slim.ops.repeat_op(2, inputs, slim.ops.conv2d, 64, [3, 3], scope='conv1')
- net = slim.ops.max_pool(net, [2, 2], scope='pool1')
- net = slim.ops.repeat_op(2, net, slim.ops.conv2d, 128, [3, 3], scope='conv2')
- net = slim.ops.max_pool(net, [2, 2], scope='pool2')
- net = slim.ops.repeat_op(3, net, slim.ops.conv2d, 256, [3, 3], scope='conv3')
- net = slim.ops.max_pool(net, [2, 2], scope='pool3')
- net = slim.ops.repeat_op(3, net, slim.ops.conv2d, 512, [3, 3], scope='conv4')
- net = slim.ops.max_pool(net, [2, 2], scope='pool4')
- net = slim.ops.repeat_op(3, net, slim.ops.conv2d, 512, [3, 3], scope='conv5')
- net = slim.ops.max_pool(net, [2, 2], scope='pool5')
- net = slim.ops.flatten(net, scope='flatten5')
- net = slim.ops.fc(net, 4096, scope='fc6')
- net = slim.ops.dropout(net, 0.5, scope='dropout6')
- net = slim.ops.fc(net, 4096, scope='fc7')
- net = slim.ops.dropout(net, 0.5, scope='dropout7')
- net = slim.ops.fc(net, 1000, activation=None, scope='fc8')
-return net
-```
-
-## Re-using previously defined network architectures and pre-trained models.
-
-### Brief Recap on Restoring Variables from a Checkpoint
-
-After a model has been trained, it can be restored using `tf.train.Saver()`
-which restores `Variables` from a given checkpoint. For many cases,
-`tf.train.Saver()` provides a simple mechanism to restore all or just a few
-variables.
-
-```python
-# Create some variables.
-v1 = tf.Variable(..., name="v1")
-v2 = tf.Variable(..., name="v2")
-...
-# Add ops to restore all the variables.
-restorer = tf.train.Saver()
-
-# Add ops to restore some variables.
-restorer = tf.train.Saver([v1, v2])
-
-# Later, launch the model, use the saver to restore variables from disk, and
-# do some work with the model.
-with tf.Session() as sess:
- # Restore variables from disk.
- restorer.restore(sess, "/tmp/model.ckpt")
- print("Model restored.")
- # Do some work with the model
- ...
-```
-
-See [Restoring Variables](https://www.tensorflow.org/versions/r0.7/how_tos/variables/index.html#restoring-variables)
-and [Choosing which Variables to Save and Restore](https://www.tensorflow.org/versions/r0.7/how_tos/variables/index.html#choosing-which-variables-to-save-and-restore)
-sections of the [Variables](https://www.tensorflow.org/versions/r0.7/how_tos/variables/index.html) page for
-more details.
-
-### Using slim.variables to Track which Variables need to be Restored
-
-It is often desirable to fine-tune a pre-trained model on an entirely new
-dataset or even a new task. In these situations, one must specify which layers
-of the model should be reused (and consequently loaded from a checkpoint) and
-which layers are new. Indicating which variables or layers should be restored is
-a process that quickly becomes cumbersome when done manually.
-
-To help keep track of which variables to restore, `slim.variables` provides a
-`restore` argument when creating each Variable. By default, all variables are
-marked as `restore=True`, which results in all variables defined by the model
-being restored.
-
-```python
-# Create some variables.
-v1 = slim.variables.variable(name="v1", ..., restore=False)
-v2 = slim.variables.variable(name="v2", ...) # By default restore=True
-...
-# Get list of variables to restore (which contains only 'v2')
-variables_to_restore = tf.get_collection(slim.variables.VARIABLES_TO_RESTORE)
-restorer = tf.train.Saver(variables_to_restore)
-with tf.Session() as sess:
- # Restore variables from disk.
- restorer.restore(sess, "/tmp/model.ckpt")
- print("Model restored.")
- # Do some work with the model
- ...
-```
-
-Additionally, every layer in `slim.ops` that creates slim.variables (such as
-`slim.ops.conv2d`, `slim.ops.fc`, `slim.ops.batch_norm`) also has a `restore`
-argument which controls whether the variables created by that layer should be
-restored or not.
-
-```python
-# Create a small network.
-net = slim.ops.conv2d(images, 32, [7, 7], stride=2, scope='conv1')
-net = slim.ops.conv2d(net, 64, [3, 3], scope='conv2')
-net = slim.ops.conv2d(net, 128, [3, 3], scope='conv3')
-net = slim.ops.max_pool(net, [3, 3], stride=2, scope='pool3')
-net = slim.ops.flatten(net)
-net = slim.ops.fc(net, 10, scope='logits', restore=False)
-...
-
-# VARIABLES_TO_RESTORE would contain the 'weights' and 'bias' defined by 'conv1'
-# 'conv2' and 'conv3' but not the ones defined by 'logits'
-variables_to_restore = tf.get_collection(slim.variables.VARIABLES_TO_RESTORE)
-
-# Create a restorer that would restore only the needed variables.
-restorer = tf.train.Saver(variables_to_restore)
-
-# Create a saver that would save all the variables (including 'logits').
-saver = tf.train.Saver()
-with tf.Session() as sess:
- # Restore variables from disk.
- restorer.restore(sess, "/tmp/model.ckpt")
- print("Model restored.")
-
- # Do some work with the model
- ...
- saver.save(sess, "/tmp/new_model.ckpt")
-```
-
-Note: When restoring variables from a checkpoint, the `Saver` locates the
-variable names in a checkpoint file and maps them to variables in the current
-graph. Above, we created a saver by passing to it a list of variables. In this
-case, the names of the variables to locate in the checkpoint file were
-implicitly obtained from each provided variable's `var.op.name`.
-
-This works well when the variable names in the checkpoint file match those in
-the graph. However, sometimes, we want to restore a model from a checkpoint
-whose variables have different names those in the current graph. In this case,
-we must provide the `Saver` a dictionary that maps from each checkpoint variable
-name to each graph variable. Consider the following example where the checkpoint
-variables names are obtained via a simple function:
-
-```python
-# Assuming that 'conv1/weights' should be restored from 'vgg16/conv1/weights'
-def name_in_checkpoint(var):
- return 'vgg16/' + var.op.name
-
-# Assuming that 'conv1/weights' and 'conv1/bias' should be restored from 'conv1/params1' and 'conv1/params2'
-def name_in_checkpoint(var):
- if "weights" in var.op.name:
- return var.op.name.replace("weights", "params1")
- if "bias" in var.op.name:
- return var.op.name.replace("bias", "params2")
-
-variables_to_restore = tf.get_collection(slim.variables.VARIABLES_TO_RESTORE)
-variables_to_restore = {name_in_checkpoint(var):var for var in variables_to_restore}
-restorer = tf.train.Saver(variables_to_restore)
-with tf.Session() as sess:
- # Restore variables from disk.
- restorer.restore(sess, "/tmp/model.ckpt")
-```
-
-### Reusing the VGG16 network defined in TF-Slim on a different task, i.e. PASCAL-VOC.
-
-Assuming one have already a pre-trained VGG16 model, one just need to replace
-the last layer `fc8` with a new layer `fc8_pascal` and use `restore=False`.
-
-```python
-def vgg16_pascal(inputs):
- with slim.arg_scope([slim.ops.conv2d, slim.ops.fc], stddev=0.01, weight_decay=0.0005):
- net = slim.ops.repeat_op(2, inputs, slim.ops.conv2d, 64, [3, 3], scope='conv1')
- net = slim.ops.max_pool(net, [2, 2], scope='pool1')
- net = slim.ops.repeat_op(2, net, slim.ops.conv2d, 128, [3, 3], scope='conv2')
- net = slim.ops.max_pool(net, [2, 2], scope='pool2')
- net = slim.ops.repeat_op(3, net, slim.ops.conv2d, 256, [3, 3], scope='conv3')
- net = slim.ops.max_pool(net, [2, 2], scope='pool3')
- net = slim.ops.repeat_op(3, net, slim.ops.conv2d, 512, [3, 3], scope='conv4')
- net = slim.ops.max_pool(net, [2, 2], scope='pool4')
- net = slim.ops.repeat_op(3, net, slim.ops.conv2d, 512, [3, 3], scope='conv5')
- net = slim.ops.max_pool(net, [2, 2], scope='pool5')
- net = slim.ops.flatten(net, scope='flatten5')
- net = slim.ops.fc(net, 4096, scope='fc6')
- net = slim.ops.dropout(net, 0.5, scope='dropout6')
- net = slim.ops.fc(net, 4096, scope='fc7')
- net = slim.ops.dropout(net, 0.5, scope='dropout7')
- # To reuse vgg16 on PASCAL-VOC, just change the last layer.
- net = slim.ops.fc(net, 21, activation=None, scope='fc8_pascal', restore=False)
- return net
-```
-
-## Authors
-
-Sergio Guadarrama and Nathan Silberman
diff --git a/research/inception/inception/slim/collections_test.py b/research/inception/inception/slim/collections_test.py
deleted file mode 100644
index 2a1f170edaaedae337df8e0b552a03dd82b263d4..0000000000000000000000000000000000000000
--- a/research/inception/inception/slim/collections_test.py
+++ /dev/null
@@ -1,181 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tests for inception."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-from inception.slim import slim
-
-
-def get_variables(scope=None):
- return slim.variables.get_variables(scope)
-
-
-def get_variables_by_name(name):
- return slim.variables.get_variables_by_name(name)
-
-
-class CollectionsTest(tf.test.TestCase):
-
- def testVariables(self):
- batch_size = 5
- height, width = 299, 299
- with self.test_session():
- inputs = tf.random_uniform((batch_size, height, width, 3))
- with slim.arg_scope([slim.ops.conv2d],
- batch_norm_params={'decay': 0.9997}):
- slim.inception.inception_v3(inputs)
- self.assertEqual(len(get_variables()), 388)
- self.assertEqual(len(get_variables_by_name('weights')), 98)
- self.assertEqual(len(get_variables_by_name('biases')), 2)
- self.assertEqual(len(get_variables_by_name('beta')), 96)
- self.assertEqual(len(get_variables_by_name('gamma')), 0)
- self.assertEqual(len(get_variables_by_name('moving_mean')), 96)
- self.assertEqual(len(get_variables_by_name('moving_variance')), 96)
-
- def testVariablesWithoutBatchNorm(self):
- batch_size = 5
- height, width = 299, 299
- with self.test_session():
- inputs = tf.random_uniform((batch_size, height, width, 3))
- with slim.arg_scope([slim.ops.conv2d],
- batch_norm_params=None):
- slim.inception.inception_v3(inputs)
- self.assertEqual(len(get_variables()), 196)
- self.assertEqual(len(get_variables_by_name('weights')), 98)
- self.assertEqual(len(get_variables_by_name('biases')), 98)
- self.assertEqual(len(get_variables_by_name('beta')), 0)
- self.assertEqual(len(get_variables_by_name('gamma')), 0)
- self.assertEqual(len(get_variables_by_name('moving_mean')), 0)
- self.assertEqual(len(get_variables_by_name('moving_variance')), 0)
-
- def testVariablesByLayer(self):
- batch_size = 5
- height, width = 299, 299
- with self.test_session():
- inputs = tf.random_uniform((batch_size, height, width, 3))
- with slim.arg_scope([slim.ops.conv2d],
- batch_norm_params={'decay': 0.9997}):
- slim.inception.inception_v3(inputs)
- self.assertEqual(len(get_variables()), 388)
- self.assertEqual(len(get_variables('conv0')), 4)
- self.assertEqual(len(get_variables('conv1')), 4)
- self.assertEqual(len(get_variables('conv2')), 4)
- self.assertEqual(len(get_variables('conv3')), 4)
- self.assertEqual(len(get_variables('conv4')), 4)
- self.assertEqual(len(get_variables('mixed_35x35x256a')), 28)
- self.assertEqual(len(get_variables('mixed_35x35x288a')), 28)
- self.assertEqual(len(get_variables('mixed_35x35x288b')), 28)
- self.assertEqual(len(get_variables('mixed_17x17x768a')), 16)
- self.assertEqual(len(get_variables('mixed_17x17x768b')), 40)
- self.assertEqual(len(get_variables('mixed_17x17x768c')), 40)
- self.assertEqual(len(get_variables('mixed_17x17x768d')), 40)
- self.assertEqual(len(get_variables('mixed_17x17x768e')), 40)
- self.assertEqual(len(get_variables('mixed_8x8x2048a')), 36)
- self.assertEqual(len(get_variables('mixed_8x8x2048b')), 36)
- self.assertEqual(len(get_variables('logits')), 2)
- self.assertEqual(len(get_variables('aux_logits')), 10)
-
- def testVariablesToRestore(self):
- batch_size = 5
- height, width = 299, 299
- with self.test_session():
- inputs = tf.random_uniform((batch_size, height, width, 3))
- with slim.arg_scope([slim.ops.conv2d],
- batch_norm_params={'decay': 0.9997}):
- slim.inception.inception_v3(inputs)
- variables_to_restore = tf.get_collection(
- slim.variables.VARIABLES_TO_RESTORE)
- self.assertEqual(len(variables_to_restore), 388)
- self.assertListEqual(variables_to_restore, get_variables())
-
- def testVariablesToRestoreWithoutLogits(self):
- batch_size = 5
- height, width = 299, 299
- with self.test_session():
- inputs = tf.random_uniform((batch_size, height, width, 3))
- with slim.arg_scope([slim.ops.conv2d],
- batch_norm_params={'decay': 0.9997}):
- slim.inception.inception_v3(inputs, restore_logits=False)
- variables_to_restore = tf.get_collection(
- slim.variables.VARIABLES_TO_RESTORE)
- self.assertEqual(len(variables_to_restore), 384)
-
- def testRegularizationLosses(self):
- batch_size = 5
- height, width = 299, 299
- with self.test_session():
- inputs = tf.random_uniform((batch_size, height, width, 3))
- with slim.arg_scope([slim.ops.conv2d, slim.ops.fc], weight_decay=0.00004):
- slim.inception.inception_v3(inputs)
- losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
- self.assertEqual(len(losses), len(get_variables_by_name('weights')))
-
- def testTotalLossWithoutRegularization(self):
- batch_size = 5
- height, width = 299, 299
- num_classes = 1001
- with self.test_session():
- inputs = tf.random_uniform((batch_size, height, width, 3))
- dense_labels = tf.random_uniform((batch_size, num_classes))
- with slim.arg_scope([slim.ops.conv2d, slim.ops.fc], weight_decay=0):
- logits, end_points = slim.inception.inception_v3(
- inputs,
- num_classes=num_classes)
- # Cross entropy loss for the main softmax prediction.
- slim.losses.cross_entropy_loss(logits,
- dense_labels,
- label_smoothing=0.1,
- weight=1.0)
- # Cross entropy loss for the auxiliary softmax head.
- slim.losses.cross_entropy_loss(end_points['aux_logits'],
- dense_labels,
- label_smoothing=0.1,
- weight=0.4,
- scope='aux_loss')
- losses = tf.get_collection(slim.losses.LOSSES_COLLECTION)
- self.assertEqual(len(losses), 2)
-
- def testTotalLossWithRegularization(self):
- batch_size = 5
- height, width = 299, 299
- num_classes = 1000
- with self.test_session():
- inputs = tf.random_uniform((batch_size, height, width, 3))
- dense_labels = tf.random_uniform((batch_size, num_classes))
- with slim.arg_scope([slim.ops.conv2d, slim.ops.fc], weight_decay=0.00004):
- logits, end_points = slim.inception.inception_v3(inputs, num_classes)
- # Cross entropy loss for the main softmax prediction.
- slim.losses.cross_entropy_loss(logits,
- dense_labels,
- label_smoothing=0.1,
- weight=1.0)
- # Cross entropy loss for the auxiliary softmax head.
- slim.losses.cross_entropy_loss(end_points['aux_logits'],
- dense_labels,
- label_smoothing=0.1,
- weight=0.4,
- scope='aux_loss')
- losses = tf.get_collection(slim.losses.LOSSES_COLLECTION)
- self.assertEqual(len(losses), 2)
- reg_losses = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)
- self.assertEqual(len(reg_losses), 98)
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/inception/inception/slim/inception_model.py b/research/inception/inception/slim/inception_model.py
deleted file mode 100644
index 6136ab1ba68716f4f135110a4d5c518b732b23df..0000000000000000000000000000000000000000
--- a/research/inception/inception/slim/inception_model.py
+++ /dev/null
@@ -1,356 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Inception-v3 expressed in TensorFlow-Slim.
-
- Usage:
-
- # Parameters for BatchNorm.
- batch_norm_params = {
- # Decay for the batch_norm moving averages.
- 'decay': BATCHNORM_MOVING_AVERAGE_DECAY,
- # epsilon to prevent 0s in variance.
- 'epsilon': 0.001,
- }
- # Set weight_decay for weights in Conv and FC layers.
- with slim.arg_scope([slim.ops.conv2d, slim.ops.fc], weight_decay=0.00004):
- with slim.arg_scope([slim.ops.conv2d],
- stddev=0.1,
- activation=tf.nn.relu,
- batch_norm_params=batch_norm_params):
- # Force all Variables to reside on the CPU.
- with slim.arg_scope([slim.variables.variable], device='/cpu:0'):
- logits, endpoints = slim.inception.inception_v3(
- images,
- dropout_keep_prob=0.8,
- num_classes=num_classes,
- is_training=for_training,
- restore_logits=restore_logits,
- scope=scope)
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-from inception.slim import ops
-from inception.slim import scopes
-
-
-def inception_v3(inputs,
- dropout_keep_prob=0.8,
- num_classes=1000,
- is_training=True,
- restore_logits=True,
- scope=''):
- """Latest Inception from http://arxiv.org/abs/1512.00567.
-
- "Rethinking the Inception Architecture for Computer Vision"
-
- Christian Szegedy, Vincent Vanhoucke, Sergey Ioffe, Jonathon Shlens,
- Zbigniew Wojna
-
- Args:
- inputs: a tensor of size [batch_size, height, width, channels].
- dropout_keep_prob: dropout keep_prob.
- num_classes: number of predicted classes.
- is_training: whether is training or not.
- restore_logits: whether or not the logits layers should be restored.
- Useful for fine-tuning a model with different num_classes.
- scope: Optional scope for name_scope.
-
- Returns:
- a list containing 'logits', 'aux_logits' Tensors.
- """
- # end_points will collect relevant activations for external use, for example
- # summaries or losses.
- end_points = {}
- with tf.name_scope(scope, 'inception_v3', [inputs]):
- with scopes.arg_scope([ops.conv2d, ops.fc, ops.batch_norm, ops.dropout],
- is_training=is_training):
- with scopes.arg_scope([ops.conv2d, ops.max_pool, ops.avg_pool],
- stride=1, padding='VALID'):
- # 299 x 299 x 3
- end_points['conv0'] = ops.conv2d(inputs, 32, [3, 3], stride=2,
- scope='conv0')
- # 149 x 149 x 32
- end_points['conv1'] = ops.conv2d(end_points['conv0'], 32, [3, 3],
- scope='conv1')
- # 147 x 147 x 32
- end_points['conv2'] = ops.conv2d(end_points['conv1'], 64, [3, 3],
- padding='SAME', scope='conv2')
- # 147 x 147 x 64
- end_points['pool1'] = ops.max_pool(end_points['conv2'], [3, 3],
- stride=2, scope='pool1')
- # 73 x 73 x 64
- end_points['conv3'] = ops.conv2d(end_points['pool1'], 80, [1, 1],
- scope='conv3')
- # 73 x 73 x 80.
- end_points['conv4'] = ops.conv2d(end_points['conv3'], 192, [3, 3],
- scope='conv4')
- # 71 x 71 x 192.
- end_points['pool2'] = ops.max_pool(end_points['conv4'], [3, 3],
- stride=2, scope='pool2')
- # 35 x 35 x 192.
- net = end_points['pool2']
- # Inception blocks
- with scopes.arg_scope([ops.conv2d, ops.max_pool, ops.avg_pool],
- stride=1, padding='SAME'):
- # mixed: 35 x 35 x 256.
- with tf.variable_scope('mixed_35x35x256a'):
- with tf.variable_scope('branch1x1'):
- branch1x1 = ops.conv2d(net, 64, [1, 1])
- with tf.variable_scope('branch5x5'):
- branch5x5 = ops.conv2d(net, 48, [1, 1])
- branch5x5 = ops.conv2d(branch5x5, 64, [5, 5])
- with tf.variable_scope('branch3x3dbl'):
- branch3x3dbl = ops.conv2d(net, 64, [1, 1])
- branch3x3dbl = ops.conv2d(branch3x3dbl, 96, [3, 3])
- branch3x3dbl = ops.conv2d(branch3x3dbl, 96, [3, 3])
- with tf.variable_scope('branch_pool'):
- branch_pool = ops.avg_pool(net, [3, 3])
- branch_pool = ops.conv2d(branch_pool, 32, [1, 1])
- net = tf.concat(axis=3, values=[branch1x1, branch5x5, branch3x3dbl, branch_pool])
- end_points['mixed_35x35x256a'] = net
- # mixed_1: 35 x 35 x 288.
- with tf.variable_scope('mixed_35x35x288a'):
- with tf.variable_scope('branch1x1'):
- branch1x1 = ops.conv2d(net, 64, [1, 1])
- with tf.variable_scope('branch5x5'):
- branch5x5 = ops.conv2d(net, 48, [1, 1])
- branch5x5 = ops.conv2d(branch5x5, 64, [5, 5])
- with tf.variable_scope('branch3x3dbl'):
- branch3x3dbl = ops.conv2d(net, 64, [1, 1])
- branch3x3dbl = ops.conv2d(branch3x3dbl, 96, [3, 3])
- branch3x3dbl = ops.conv2d(branch3x3dbl, 96, [3, 3])
- with tf.variable_scope('branch_pool'):
- branch_pool = ops.avg_pool(net, [3, 3])
- branch_pool = ops.conv2d(branch_pool, 64, [1, 1])
- net = tf.concat(axis=3, values=[branch1x1, branch5x5, branch3x3dbl, branch_pool])
- end_points['mixed_35x35x288a'] = net
- # mixed_2: 35 x 35 x 288.
- with tf.variable_scope('mixed_35x35x288b'):
- with tf.variable_scope('branch1x1'):
- branch1x1 = ops.conv2d(net, 64, [1, 1])
- with tf.variable_scope('branch5x5'):
- branch5x5 = ops.conv2d(net, 48, [1, 1])
- branch5x5 = ops.conv2d(branch5x5, 64, [5, 5])
- with tf.variable_scope('branch3x3dbl'):
- branch3x3dbl = ops.conv2d(net, 64, [1, 1])
- branch3x3dbl = ops.conv2d(branch3x3dbl, 96, [3, 3])
- branch3x3dbl = ops.conv2d(branch3x3dbl, 96, [3, 3])
- with tf.variable_scope('branch_pool'):
- branch_pool = ops.avg_pool(net, [3, 3])
- branch_pool = ops.conv2d(branch_pool, 64, [1, 1])
- net = tf.concat(axis=3, values=[branch1x1, branch5x5, branch3x3dbl, branch_pool])
- end_points['mixed_35x35x288b'] = net
- # mixed_3: 17 x 17 x 768.
- with tf.variable_scope('mixed_17x17x768a'):
- with tf.variable_scope('branch3x3'):
- branch3x3 = ops.conv2d(net, 384, [3, 3], stride=2, padding='VALID')
- with tf.variable_scope('branch3x3dbl'):
- branch3x3dbl = ops.conv2d(net, 64, [1, 1])
- branch3x3dbl = ops.conv2d(branch3x3dbl, 96, [3, 3])
- branch3x3dbl = ops.conv2d(branch3x3dbl, 96, [3, 3],
- stride=2, padding='VALID')
- with tf.variable_scope('branch_pool'):
- branch_pool = ops.max_pool(net, [3, 3], stride=2, padding='VALID')
- net = tf.concat(axis=3, values=[branch3x3, branch3x3dbl, branch_pool])
- end_points['mixed_17x17x768a'] = net
- # mixed4: 17 x 17 x 768.
- with tf.variable_scope('mixed_17x17x768b'):
- with tf.variable_scope('branch1x1'):
- branch1x1 = ops.conv2d(net, 192, [1, 1])
- with tf.variable_scope('branch7x7'):
- branch7x7 = ops.conv2d(net, 128, [1, 1])
- branch7x7 = ops.conv2d(branch7x7, 128, [1, 7])
- branch7x7 = ops.conv2d(branch7x7, 192, [7, 1])
- with tf.variable_scope('branch7x7dbl'):
- branch7x7dbl = ops.conv2d(net, 128, [1, 1])
- branch7x7dbl = ops.conv2d(branch7x7dbl, 128, [7, 1])
- branch7x7dbl = ops.conv2d(branch7x7dbl, 128, [1, 7])
- branch7x7dbl = ops.conv2d(branch7x7dbl, 128, [7, 1])
- branch7x7dbl = ops.conv2d(branch7x7dbl, 192, [1, 7])
- with tf.variable_scope('branch_pool'):
- branch_pool = ops.avg_pool(net, [3, 3])
- branch_pool = ops.conv2d(branch_pool, 192, [1, 1])
- net = tf.concat(axis=3, values=[branch1x1, branch7x7, branch7x7dbl, branch_pool])
- end_points['mixed_17x17x768b'] = net
- # mixed_5: 17 x 17 x 768.
- with tf.variable_scope('mixed_17x17x768c'):
- with tf.variable_scope('branch1x1'):
- branch1x1 = ops.conv2d(net, 192, [1, 1])
- with tf.variable_scope('branch7x7'):
- branch7x7 = ops.conv2d(net, 160, [1, 1])
- branch7x7 = ops.conv2d(branch7x7, 160, [1, 7])
- branch7x7 = ops.conv2d(branch7x7, 192, [7, 1])
- with tf.variable_scope('branch7x7dbl'):
- branch7x7dbl = ops.conv2d(net, 160, [1, 1])
- branch7x7dbl = ops.conv2d(branch7x7dbl, 160, [7, 1])
- branch7x7dbl = ops.conv2d(branch7x7dbl, 160, [1, 7])
- branch7x7dbl = ops.conv2d(branch7x7dbl, 160, [7, 1])
- branch7x7dbl = ops.conv2d(branch7x7dbl, 192, [1, 7])
- with tf.variable_scope('branch_pool'):
- branch_pool = ops.avg_pool(net, [3, 3])
- branch_pool = ops.conv2d(branch_pool, 192, [1, 1])
- net = tf.concat(axis=3, values=[branch1x1, branch7x7, branch7x7dbl, branch_pool])
- end_points['mixed_17x17x768c'] = net
- # mixed_6: 17 x 17 x 768.
- with tf.variable_scope('mixed_17x17x768d'):
- with tf.variable_scope('branch1x1'):
- branch1x1 = ops.conv2d(net, 192, [1, 1])
- with tf.variable_scope('branch7x7'):
- branch7x7 = ops.conv2d(net, 160, [1, 1])
- branch7x7 = ops.conv2d(branch7x7, 160, [1, 7])
- branch7x7 = ops.conv2d(branch7x7, 192, [7, 1])
- with tf.variable_scope('branch7x7dbl'):
- branch7x7dbl = ops.conv2d(net, 160, [1, 1])
- branch7x7dbl = ops.conv2d(branch7x7dbl, 160, [7, 1])
- branch7x7dbl = ops.conv2d(branch7x7dbl, 160, [1, 7])
- branch7x7dbl = ops.conv2d(branch7x7dbl, 160, [7, 1])
- branch7x7dbl = ops.conv2d(branch7x7dbl, 192, [1, 7])
- with tf.variable_scope('branch_pool'):
- branch_pool = ops.avg_pool(net, [3, 3])
- branch_pool = ops.conv2d(branch_pool, 192, [1, 1])
- net = tf.concat(axis=3, values=[branch1x1, branch7x7, branch7x7dbl, branch_pool])
- end_points['mixed_17x17x768d'] = net
- # mixed_7: 17 x 17 x 768.
- with tf.variable_scope('mixed_17x17x768e'):
- with tf.variable_scope('branch1x1'):
- branch1x1 = ops.conv2d(net, 192, [1, 1])
- with tf.variable_scope('branch7x7'):
- branch7x7 = ops.conv2d(net, 192, [1, 1])
- branch7x7 = ops.conv2d(branch7x7, 192, [1, 7])
- branch7x7 = ops.conv2d(branch7x7, 192, [7, 1])
- with tf.variable_scope('branch7x7dbl'):
- branch7x7dbl = ops.conv2d(net, 192, [1, 1])
- branch7x7dbl = ops.conv2d(branch7x7dbl, 192, [7, 1])
- branch7x7dbl = ops.conv2d(branch7x7dbl, 192, [1, 7])
- branch7x7dbl = ops.conv2d(branch7x7dbl, 192, [7, 1])
- branch7x7dbl = ops.conv2d(branch7x7dbl, 192, [1, 7])
- with tf.variable_scope('branch_pool'):
- branch_pool = ops.avg_pool(net, [3, 3])
- branch_pool = ops.conv2d(branch_pool, 192, [1, 1])
- net = tf.concat(axis=3, values=[branch1x1, branch7x7, branch7x7dbl, branch_pool])
- end_points['mixed_17x17x768e'] = net
- # Auxiliary Head logits
- aux_logits = tf.identity(end_points['mixed_17x17x768e'])
- with tf.variable_scope('aux_logits'):
- aux_logits = ops.avg_pool(aux_logits, [5, 5], stride=3,
- padding='VALID')
- aux_logits = ops.conv2d(aux_logits, 128, [1, 1], scope='proj')
- # Shape of feature map before the final layer.
- shape = aux_logits.get_shape()
- aux_logits = ops.conv2d(aux_logits, 768, shape[1:3], stddev=0.01,
- padding='VALID')
- aux_logits = ops.flatten(aux_logits)
- aux_logits = ops.fc(aux_logits, num_classes, activation=None,
- stddev=0.001, restore=restore_logits)
- end_points['aux_logits'] = aux_logits
- # mixed_8: 8 x 8 x 1280.
- # Note that the scope below is not changed to not void previous
- # checkpoints.
- # (TODO) Fix the scope when appropriate.
- with tf.variable_scope('mixed_17x17x1280a'):
- with tf.variable_scope('branch3x3'):
- branch3x3 = ops.conv2d(net, 192, [1, 1])
- branch3x3 = ops.conv2d(branch3x3, 320, [3, 3], stride=2,
- padding='VALID')
- with tf.variable_scope('branch7x7x3'):
- branch7x7x3 = ops.conv2d(net, 192, [1, 1])
- branch7x7x3 = ops.conv2d(branch7x7x3, 192, [1, 7])
- branch7x7x3 = ops.conv2d(branch7x7x3, 192, [7, 1])
- branch7x7x3 = ops.conv2d(branch7x7x3, 192, [3, 3],
- stride=2, padding='VALID')
- with tf.variable_scope('branch_pool'):
- branch_pool = ops.max_pool(net, [3, 3], stride=2, padding='VALID')
- net = tf.concat(axis=3, values=[branch3x3, branch7x7x3, branch_pool])
- end_points['mixed_17x17x1280a'] = net
- # mixed_9: 8 x 8 x 2048.
- with tf.variable_scope('mixed_8x8x2048a'):
- with tf.variable_scope('branch1x1'):
- branch1x1 = ops.conv2d(net, 320, [1, 1])
- with tf.variable_scope('branch3x3'):
- branch3x3 = ops.conv2d(net, 384, [1, 1])
- branch3x3 = tf.concat(axis=3, values=[ops.conv2d(branch3x3, 384, [1, 3]),
- ops.conv2d(branch3x3, 384, [3, 1])])
- with tf.variable_scope('branch3x3dbl'):
- branch3x3dbl = ops.conv2d(net, 448, [1, 1])
- branch3x3dbl = ops.conv2d(branch3x3dbl, 384, [3, 3])
- branch3x3dbl = tf.concat(axis=3, values=[ops.conv2d(branch3x3dbl, 384, [1, 3]),
- ops.conv2d(branch3x3dbl, 384, [3, 1])])
- with tf.variable_scope('branch_pool'):
- branch_pool = ops.avg_pool(net, [3, 3])
- branch_pool = ops.conv2d(branch_pool, 192, [1, 1])
- net = tf.concat(axis=3, values=[branch1x1, branch3x3, branch3x3dbl, branch_pool])
- end_points['mixed_8x8x2048a'] = net
- # mixed_10: 8 x 8 x 2048.
- with tf.variable_scope('mixed_8x8x2048b'):
- with tf.variable_scope('branch1x1'):
- branch1x1 = ops.conv2d(net, 320, [1, 1])
- with tf.variable_scope('branch3x3'):
- branch3x3 = ops.conv2d(net, 384, [1, 1])
- branch3x3 = tf.concat(axis=3, values=[ops.conv2d(branch3x3, 384, [1, 3]),
- ops.conv2d(branch3x3, 384, [3, 1])])
- with tf.variable_scope('branch3x3dbl'):
- branch3x3dbl = ops.conv2d(net, 448, [1, 1])
- branch3x3dbl = ops.conv2d(branch3x3dbl, 384, [3, 3])
- branch3x3dbl = tf.concat(axis=3, values=[ops.conv2d(branch3x3dbl, 384, [1, 3]),
- ops.conv2d(branch3x3dbl, 384, [3, 1])])
- with tf.variable_scope('branch_pool'):
- branch_pool = ops.avg_pool(net, [3, 3])
- branch_pool = ops.conv2d(branch_pool, 192, [1, 1])
- net = tf.concat(axis=3, values=[branch1x1, branch3x3, branch3x3dbl, branch_pool])
- end_points['mixed_8x8x2048b'] = net
- # Final pooling and prediction
- with tf.variable_scope('logits'):
- shape = net.get_shape()
- net = ops.avg_pool(net, shape[1:3], padding='VALID', scope='pool')
- # 1 x 1 x 2048
- net = ops.dropout(net, dropout_keep_prob, scope='dropout')
- net = ops.flatten(net, scope='flatten')
- # 2048
- logits = ops.fc(net, num_classes, activation=None, scope='logits',
- restore=restore_logits)
- # 1000
- end_points['logits'] = logits
- end_points['predictions'] = tf.nn.softmax(logits, name='predictions')
- return logits, end_points
-
-
-def inception_v3_parameters(weight_decay=0.00004, stddev=0.1,
- batch_norm_decay=0.9997, batch_norm_epsilon=0.001):
- """Yields the scope with the default parameters for inception_v3.
-
- Args:
- weight_decay: the weight decay for weights variables.
- stddev: standard deviation of the truncated guassian weight distribution.
- batch_norm_decay: decay for the moving average of batch_norm momentums.
- batch_norm_epsilon: small float added to variance to avoid dividing by zero.
-
- Yields:
- a arg_scope with the parameters needed for inception_v3.
- """
- # Set weight_decay for weights in Conv and FC layers.
- with scopes.arg_scope([ops.conv2d, ops.fc],
- weight_decay=weight_decay):
- # Set stddev, activation and parameters for batch_norm.
- with scopes.arg_scope([ops.conv2d],
- stddev=stddev,
- activation=tf.nn.relu,
- batch_norm_params={
- 'decay': batch_norm_decay,
- 'epsilon': batch_norm_epsilon}) as arg_scope:
- yield arg_scope
diff --git a/research/inception/inception/slim/inception_test.py b/research/inception/inception/slim/inception_test.py
deleted file mode 100644
index 231dea298f4b761aa90224df1c263873bc890ac5..0000000000000000000000000000000000000000
--- a/research/inception/inception/slim/inception_test.py
+++ /dev/null
@@ -1,134 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tests for slim.inception."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-from inception.slim import inception_model as inception
-
-
-class InceptionTest(tf.test.TestCase):
-
- def testBuildLogits(self):
- batch_size = 5
- height, width = 299, 299
- num_classes = 1000
- with self.test_session():
- inputs = tf.random_uniform((batch_size, height, width, 3))
- logits, _ = inception.inception_v3(inputs, num_classes)
- self.assertTrue(logits.op.name.startswith('logits'))
- self.assertListEqual(logits.get_shape().as_list(),
- [batch_size, num_classes])
-
- def testBuildEndPoints(self):
- batch_size = 5
- height, width = 299, 299
- num_classes = 1000
- with self.test_session():
- inputs = tf.random_uniform((batch_size, height, width, 3))
- _, end_points = inception.inception_v3(inputs, num_classes)
- self.assertTrue('logits' in end_points)
- logits = end_points['logits']
- self.assertListEqual(logits.get_shape().as_list(),
- [batch_size, num_classes])
- self.assertTrue('aux_logits' in end_points)
- aux_logits = end_points['aux_logits']
- self.assertListEqual(aux_logits.get_shape().as_list(),
- [batch_size, num_classes])
- pre_pool = end_points['mixed_8x8x2048b']
- self.assertListEqual(pre_pool.get_shape().as_list(),
- [batch_size, 8, 8, 2048])
-
- def testVariablesSetDevice(self):
- batch_size = 5
- height, width = 299, 299
- num_classes = 1000
- with self.test_session():
- inputs = tf.random_uniform((batch_size, height, width, 3))
- # Force all Variables to reside on the device.
- with tf.variable_scope('on_cpu'), tf.device('/cpu:0'):
- inception.inception_v3(inputs, num_classes)
- with tf.variable_scope('on_gpu'), tf.device('/gpu:0'):
- inception.inception_v3(inputs, num_classes)
- for v in tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='on_cpu'):
- self.assertDeviceEqual(v.device, '/cpu:0')
- for v in tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope='on_gpu'):
- self.assertDeviceEqual(v.device, '/gpu:0')
-
- def testHalfSizeImages(self):
- batch_size = 5
- height, width = 150, 150
- num_classes = 1000
- with self.test_session():
- inputs = tf.random_uniform((batch_size, height, width, 3))
- logits, end_points = inception.inception_v3(inputs, num_classes)
- self.assertTrue(logits.op.name.startswith('logits'))
- self.assertListEqual(logits.get_shape().as_list(),
- [batch_size, num_classes])
- pre_pool = end_points['mixed_8x8x2048b']
- self.assertListEqual(pre_pool.get_shape().as_list(),
- [batch_size, 3, 3, 2048])
-
- def testUnknowBatchSize(self):
- batch_size = 1
- height, width = 299, 299
- num_classes = 1000
- with self.test_session() as sess:
- inputs = tf.placeholder(tf.float32, (None, height, width, 3))
- logits, _ = inception.inception_v3(inputs, num_classes)
- self.assertTrue(logits.op.name.startswith('logits'))
- self.assertListEqual(logits.get_shape().as_list(),
- [None, num_classes])
- images = tf.random_uniform((batch_size, height, width, 3))
- sess.run(tf.global_variables_initializer())
- output = sess.run(logits, {inputs: images.eval()})
- self.assertEquals(output.shape, (batch_size, num_classes))
-
- def testEvaluation(self):
- batch_size = 2
- height, width = 299, 299
- num_classes = 1000
- with self.test_session() as sess:
- eval_inputs = tf.random_uniform((batch_size, height, width, 3))
- logits, _ = inception.inception_v3(eval_inputs, num_classes,
- is_training=False)
- predictions = tf.argmax(logits, 1)
- sess.run(tf.global_variables_initializer())
- output = sess.run(predictions)
- self.assertEquals(output.shape, (batch_size,))
-
- def testTrainEvalWithReuse(self):
- train_batch_size = 5
- eval_batch_size = 2
- height, width = 150, 150
- num_classes = 1000
- with self.test_session() as sess:
- train_inputs = tf.random_uniform((train_batch_size, height, width, 3))
- inception.inception_v3(train_inputs, num_classes)
- tf.get_variable_scope().reuse_variables()
- eval_inputs = tf.random_uniform((eval_batch_size, height, width, 3))
- logits, _ = inception.inception_v3(eval_inputs, num_classes,
- is_training=False)
- predictions = tf.argmax(logits, 1)
- sess.run(tf.global_variables_initializer())
- output = sess.run(predictions)
- self.assertEquals(output.shape, (eval_batch_size,))
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/inception/inception/slim/losses.py b/research/inception/inception/slim/losses.py
deleted file mode 100644
index 78298d092fab3afc264e427fb060602c27ea97b0..0000000000000000000000000000000000000000
--- a/research/inception/inception/slim/losses.py
+++ /dev/null
@@ -1,174 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Contains convenience wrappers for various Neural Network TensorFlow losses.
-
- All the losses defined here add themselves to the LOSSES_COLLECTION
- collection.
-
- l1_loss: Define a L1 Loss, useful for regularization, i.e. lasso.
- l2_loss: Define a L2 Loss, useful for regularization, i.e. weight decay.
- cross_entropy_loss: Define a cross entropy loss using
- softmax_cross_entropy_with_logits. Useful for classification.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-# In order to gather all losses in a network, the user should use this
-# key for get_collection, i.e:
-# losses = tf.get_collection(slim.losses.LOSSES_COLLECTION)
-LOSSES_COLLECTION = '_losses'
-
-
-def l1_regularizer(weight=1.0, scope=None):
- """Define a L1 regularizer.
-
- Args:
- weight: scale the loss by this factor.
- scope: Optional scope for name_scope.
-
- Returns:
- a regularizer function.
- """
- def regularizer(tensor):
- with tf.name_scope(scope, 'L1Regularizer', [tensor]):
- l1_weight = tf.convert_to_tensor(weight,
- dtype=tensor.dtype.base_dtype,
- name='weight')
- return tf.multiply(l1_weight, tf.reduce_sum(tf.abs(tensor)), name='value')
- return regularizer
-
-
-def l2_regularizer(weight=1.0, scope=None):
- """Define a L2 regularizer.
-
- Args:
- weight: scale the loss by this factor.
- scope: Optional scope for name_scope.
-
- Returns:
- a regularizer function.
- """
- def regularizer(tensor):
- with tf.name_scope(scope, 'L2Regularizer', [tensor]):
- l2_weight = tf.convert_to_tensor(weight,
- dtype=tensor.dtype.base_dtype,
- name='weight')
- return tf.multiply(l2_weight, tf.nn.l2_loss(tensor), name='value')
- return regularizer
-
-
-def l1_l2_regularizer(weight_l1=1.0, weight_l2=1.0, scope=None):
- """Define a L1L2 regularizer.
-
- Args:
- weight_l1: scale the L1 loss by this factor.
- weight_l2: scale the L2 loss by this factor.
- scope: Optional scope for name_scope.
-
- Returns:
- a regularizer function.
- """
- def regularizer(tensor):
- with tf.name_scope(scope, 'L1L2Regularizer', [tensor]):
- weight_l1_t = tf.convert_to_tensor(weight_l1,
- dtype=tensor.dtype.base_dtype,
- name='weight_l1')
- weight_l2_t = tf.convert_to_tensor(weight_l2,
- dtype=tensor.dtype.base_dtype,
- name='weight_l2')
- reg_l1 = tf.multiply(weight_l1_t, tf.reduce_sum(tf.abs(tensor)),
- name='value_l1')
- reg_l2 = tf.multiply(weight_l2_t, tf.nn.l2_loss(tensor),
- name='value_l2')
- return tf.add(reg_l1, reg_l2, name='value')
- return regularizer
-
-
-def l1_loss(tensor, weight=1.0, scope=None):
- """Define a L1Loss, useful for regularize, i.e. lasso.
-
- Args:
- tensor: tensor to regularize.
- weight: scale the loss by this factor.
- scope: Optional scope for name_scope.
-
- Returns:
- the L1 loss op.
- """
- with tf.name_scope(scope, 'L1Loss', [tensor]):
- weight = tf.convert_to_tensor(weight,
- dtype=tensor.dtype.base_dtype,
- name='loss_weight')
- loss = tf.multiply(weight, tf.reduce_sum(tf.abs(tensor)), name='value')
- tf.add_to_collection(LOSSES_COLLECTION, loss)
- return loss
-
-
-def l2_loss(tensor, weight=1.0, scope=None):
- """Define a L2Loss, useful for regularize, i.e. weight decay.
-
- Args:
- tensor: tensor to regularize.
- weight: an optional weight to modulate the loss.
- scope: Optional scope for name_scope.
-
- Returns:
- the L2 loss op.
- """
- with tf.name_scope(scope, 'L2Loss', [tensor]):
- weight = tf.convert_to_tensor(weight,
- dtype=tensor.dtype.base_dtype,
- name='loss_weight')
- loss = tf.multiply(weight, tf.nn.l2_loss(tensor), name='value')
- tf.add_to_collection(LOSSES_COLLECTION, loss)
- return loss
-
-
-def cross_entropy_loss(logits, one_hot_labels, label_smoothing=0,
- weight=1.0, scope=None):
- """Define a Cross Entropy loss using softmax_cross_entropy_with_logits.
-
- It can scale the loss by weight factor, and smooth the labels.
-
- Args:
- logits: [batch_size, num_classes] logits outputs of the network .
- one_hot_labels: [batch_size, num_classes] target one_hot_encoded labels.
- label_smoothing: if greater than 0 then smooth the labels.
- weight: scale the loss by this factor.
- scope: Optional scope for name_scope.
-
- Returns:
- A tensor with the softmax_cross_entropy loss.
- """
- logits.get_shape().assert_is_compatible_with(one_hot_labels.get_shape())
- with tf.name_scope(scope, 'CrossEntropyLoss', [logits, one_hot_labels]):
- num_classes = one_hot_labels.get_shape()[-1].value
- one_hot_labels = tf.cast(one_hot_labels, logits.dtype)
- if label_smoothing > 0:
- smooth_positives = 1.0 - label_smoothing
- smooth_negatives = label_smoothing / num_classes
- one_hot_labels = one_hot_labels * smooth_positives + smooth_negatives
- cross_entropy = tf.contrib.nn.deprecated_flipped_softmax_cross_entropy_with_logits(
- logits, one_hot_labels, name='xentropy')
-
- weight = tf.convert_to_tensor(weight,
- dtype=logits.dtype.base_dtype,
- name='loss_weight')
- loss = tf.multiply(weight, tf.reduce_mean(cross_entropy), name='value')
- tf.add_to_collection(LOSSES_COLLECTION, loss)
- return loss
diff --git a/research/inception/inception/slim/losses_test.py b/research/inception/inception/slim/losses_test.py
deleted file mode 100644
index e267f6520779f63be0becf41ceccc7de494e14f7..0000000000000000000000000000000000000000
--- a/research/inception/inception/slim/losses_test.py
+++ /dev/null
@@ -1,177 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tests for slim.losses."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import tensorflow as tf
-
-from inception.slim import losses
-
-
-class LossesTest(tf.test.TestCase):
-
- def testL1Loss(self):
- with self.test_session():
- shape = [5, 5, 5]
- num_elem = 5 * 5 * 5
- weights = tf.constant(1.0, shape=shape)
- wd = 0.01
- loss = losses.l1_loss(weights, wd)
- self.assertEquals(loss.op.name, 'L1Loss/value')
- self.assertAlmostEqual(loss.eval(), num_elem * wd, 5)
-
- def testL2Loss(self):
- with self.test_session():
- shape = [5, 5, 5]
- num_elem = 5 * 5 * 5
- weights = tf.constant(1.0, shape=shape)
- wd = 0.01
- loss = losses.l2_loss(weights, wd)
- self.assertEquals(loss.op.name, 'L2Loss/value')
- self.assertAlmostEqual(loss.eval(), num_elem * wd / 2, 5)
-
-
-class RegularizersTest(tf.test.TestCase):
-
- def testL1Regularizer(self):
- with self.test_session():
- shape = [5, 5, 5]
- num_elem = 5 * 5 * 5
- tensor = tf.constant(1.0, shape=shape)
- loss = losses.l1_regularizer()(tensor)
- self.assertEquals(loss.op.name, 'L1Regularizer/value')
- self.assertAlmostEqual(loss.eval(), num_elem, 5)
-
- def testL1RegularizerWithScope(self):
- with self.test_session():
- shape = [5, 5, 5]
- num_elem = 5 * 5 * 5
- tensor = tf.constant(1.0, shape=shape)
- loss = losses.l1_regularizer(scope='L1')(tensor)
- self.assertEquals(loss.op.name, 'L1/value')
- self.assertAlmostEqual(loss.eval(), num_elem, 5)
-
- def testL1RegularizerWithWeight(self):
- with self.test_session():
- shape = [5, 5, 5]
- num_elem = 5 * 5 * 5
- tensor = tf.constant(1.0, shape=shape)
- weight = 0.01
- loss = losses.l1_regularizer(weight)(tensor)
- self.assertEquals(loss.op.name, 'L1Regularizer/value')
- self.assertAlmostEqual(loss.eval(), num_elem * weight, 5)
-
- def testL2Regularizer(self):
- with self.test_session():
- shape = [5, 5, 5]
- num_elem = 5 * 5 * 5
- tensor = tf.constant(1.0, shape=shape)
- loss = losses.l2_regularizer()(tensor)
- self.assertEquals(loss.op.name, 'L2Regularizer/value')
- self.assertAlmostEqual(loss.eval(), num_elem / 2, 5)
-
- def testL2RegularizerWithScope(self):
- with self.test_session():
- shape = [5, 5, 5]
- num_elem = 5 * 5 * 5
- tensor = tf.constant(1.0, shape=shape)
- loss = losses.l2_regularizer(scope='L2')(tensor)
- self.assertEquals(loss.op.name, 'L2/value')
- self.assertAlmostEqual(loss.eval(), num_elem / 2, 5)
-
- def testL2RegularizerWithWeight(self):
- with self.test_session():
- shape = [5, 5, 5]
- num_elem = 5 * 5 * 5
- tensor = tf.constant(1.0, shape=shape)
- weight = 0.01
- loss = losses.l2_regularizer(weight)(tensor)
- self.assertEquals(loss.op.name, 'L2Regularizer/value')
- self.assertAlmostEqual(loss.eval(), num_elem * weight / 2, 5)
-
- def testL1L2Regularizer(self):
- with self.test_session():
- shape = [5, 5, 5]
- num_elem = 5 * 5 * 5
- tensor = tf.constant(1.0, shape=shape)
- loss = losses.l1_l2_regularizer()(tensor)
- self.assertEquals(loss.op.name, 'L1L2Regularizer/value')
- self.assertAlmostEqual(loss.eval(), num_elem + num_elem / 2, 5)
-
- def testL1L2RegularizerWithScope(self):
- with self.test_session():
- shape = [5, 5, 5]
- num_elem = 5 * 5 * 5
- tensor = tf.constant(1.0, shape=shape)
- loss = losses.l1_l2_regularizer(scope='L1L2')(tensor)
- self.assertEquals(loss.op.name, 'L1L2/value')
- self.assertAlmostEqual(loss.eval(), num_elem + num_elem / 2, 5)
-
- def testL1L2RegularizerWithWeights(self):
- with self.test_session():
- shape = [5, 5, 5]
- num_elem = 5 * 5 * 5
- tensor = tf.constant(1.0, shape=shape)
- weight_l1 = 0.01
- weight_l2 = 0.05
- loss = losses.l1_l2_regularizer(weight_l1, weight_l2)(tensor)
- self.assertEquals(loss.op.name, 'L1L2Regularizer/value')
- self.assertAlmostEqual(loss.eval(),
- num_elem * weight_l1 + num_elem * weight_l2 / 2, 5)
-
-
-class CrossEntropyLossTest(tf.test.TestCase):
-
- def testCrossEntropyLossAllCorrect(self):
- with self.test_session():
- logits = tf.constant([[10.0, 0.0, 0.0],
- [0.0, 10.0, 0.0],
- [0.0, 0.0, 10.0]])
- labels = tf.constant([[1, 0, 0],
- [0, 1, 0],
- [0, 0, 1]])
- loss = losses.cross_entropy_loss(logits, labels)
- self.assertEquals(loss.op.name, 'CrossEntropyLoss/value')
- self.assertAlmostEqual(loss.eval(), 0.0, 3)
-
- def testCrossEntropyLossAllWrong(self):
- with self.test_session():
- logits = tf.constant([[10.0, 0.0, 0.0],
- [0.0, 10.0, 0.0],
- [0.0, 0.0, 10.0]])
- labels = tf.constant([[0, 0, 1],
- [1, 0, 0],
- [0, 1, 0]])
- loss = losses.cross_entropy_loss(logits, labels)
- self.assertEquals(loss.op.name, 'CrossEntropyLoss/value')
- self.assertAlmostEqual(loss.eval(), 10.0, 3)
-
- def testCrossEntropyLossAllWrongWithWeight(self):
- with self.test_session():
- logits = tf.constant([[10.0, 0.0, 0.0],
- [0.0, 10.0, 0.0],
- [0.0, 0.0, 10.0]])
- labels = tf.constant([[0, 0, 1],
- [1, 0, 0],
- [0, 1, 0]])
- loss = losses.cross_entropy_loss(logits, labels, weight=0.5)
- self.assertEquals(loss.op.name, 'CrossEntropyLoss/value')
- self.assertAlmostEqual(loss.eval(), 5.0, 3)
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/inception/inception/slim/ops.py b/research/inception/inception/slim/ops.py
deleted file mode 100644
index 54fda4eb81f3a138d9bb2748c21164b88570ede9..0000000000000000000000000000000000000000
--- a/research/inception/inception/slim/ops.py
+++ /dev/null
@@ -1,473 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Contains convenience wrappers for typical Neural Network TensorFlow layers.
-
- Additionally it maintains a collection with update_ops that need to be
- updated after the ops have been computed, for example to update moving means
- and moving variances of batch_norm.
-
- Ops that have different behavior during training or eval have an is_training
- parameter. Additionally Ops that contain variables.variable have a trainable
- parameter, which control if the ops variables are trainable or not.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import tensorflow as tf
-
-from tensorflow.python.training import moving_averages
-
-from inception.slim import losses
-from inception.slim import scopes
-from inception.slim import variables
-
-# Used to keep the update ops done by batch_norm.
-UPDATE_OPS_COLLECTION = '_update_ops_'
-
-
-@scopes.add_arg_scope
-def batch_norm(inputs,
- decay=0.999,
- center=True,
- scale=False,
- epsilon=0.001,
- moving_vars='moving_vars',
- activation=None,
- is_training=True,
- trainable=True,
- restore=True,
- scope=None,
- reuse=None):
- """Adds a Batch Normalization layer.
-
- Args:
- inputs: a tensor of size [batch_size, height, width, channels]
- or [batch_size, channels].
- decay: decay for the moving average.
- center: If True, subtract beta. If False, beta is not created and ignored.
- scale: If True, multiply by gamma. If False, gamma is
- not used. When the next layer is linear (also e.g. ReLU), this can be
- disabled since the scaling can be done by the next layer.
- epsilon: small float added to variance to avoid dividing by zero.
- moving_vars: collection to store the moving_mean and moving_variance.
- activation: activation function.
- is_training: whether or not the model is in training mode.
- trainable: whether or not the variables should be trainable or not.
- restore: whether or not the variables should be marked for restore.
- scope: Optional scope for variable_scope.
- reuse: whether or not the layer and its variables should be reused. To be
- able to reuse the layer scope must be given.
-
- Returns:
- a tensor representing the output of the operation.
-
- """
- inputs_shape = inputs.get_shape()
- with tf.variable_scope(scope, 'BatchNorm', [inputs], reuse=reuse):
- axis = list(range(len(inputs_shape) - 1))
- params_shape = inputs_shape[-1:]
- # Allocate parameters for the beta and gamma of the normalization.
- beta, gamma = None, None
- if center:
- beta = variables.variable('beta',
- params_shape,
- initializer=tf.zeros_initializer(),
- trainable=trainable,
- restore=restore)
- if scale:
- gamma = variables.variable('gamma',
- params_shape,
- initializer=tf.ones_initializer(),
- trainable=trainable,
- restore=restore)
- # Create moving_mean and moving_variance add them to
- # GraphKeys.MOVING_AVERAGE_VARIABLES collections.
- moving_collections = [moving_vars, tf.GraphKeys.MOVING_AVERAGE_VARIABLES]
- moving_mean = variables.variable('moving_mean',
- params_shape,
- initializer=tf.zeros_initializer(),
- trainable=False,
- restore=restore,
- collections=moving_collections)
- moving_variance = variables.variable('moving_variance',
- params_shape,
- initializer=tf.ones_initializer(),
- trainable=False,
- restore=restore,
- collections=moving_collections)
- if is_training:
- # Calculate the moments based on the individual batch.
- mean, variance = tf.nn.moments(inputs, axis)
-
- update_moving_mean = moving_averages.assign_moving_average(
- moving_mean, mean, decay)
- tf.add_to_collection(UPDATE_OPS_COLLECTION, update_moving_mean)
- update_moving_variance = moving_averages.assign_moving_average(
- moving_variance, variance, decay)
- tf.add_to_collection(UPDATE_OPS_COLLECTION, update_moving_variance)
- else:
- # Just use the moving_mean and moving_variance.
- mean = moving_mean
- variance = moving_variance
- # Normalize the activations.
- outputs = tf.nn.batch_normalization(
- inputs, mean, variance, beta, gamma, epsilon)
- outputs.set_shape(inputs.get_shape())
- if activation:
- outputs = activation(outputs)
- return outputs
-
-
-def _two_element_tuple(int_or_tuple):
- """Converts `int_or_tuple` to height, width.
-
- Several of the functions that follow accept arguments as either
- a tuple of 2 integers or a single integer. A single integer
- indicates that the 2 values of the tuple are the same.
-
- This functions normalizes the input value by always returning a tuple.
-
- Args:
- int_or_tuple: A list of 2 ints, a single int or a tf.TensorShape.
-
- Returns:
- A tuple with 2 values.
-
- Raises:
- ValueError: If `int_or_tuple` it not well formed.
- """
- if isinstance(int_or_tuple, (list, tuple)):
- if len(int_or_tuple) != 2:
- raise ValueError('Must be a list with 2 elements: %s' % int_or_tuple)
- return int(int_or_tuple[0]), int(int_or_tuple[1])
- if isinstance(int_or_tuple, int):
- return int(int_or_tuple), int(int_or_tuple)
- if isinstance(int_or_tuple, tf.TensorShape):
- if len(int_or_tuple) == 2:
- return int_or_tuple[0], int_or_tuple[1]
- raise ValueError('Must be an int, a list with 2 elements or a TensorShape of '
- 'length 2')
-
-
-@scopes.add_arg_scope
-def conv2d(inputs,
- num_filters_out,
- kernel_size,
- stride=1,
- padding='SAME',
- activation=tf.nn.relu,
- stddev=0.01,
- bias=0.0,
- weight_decay=0,
- batch_norm_params=None,
- is_training=True,
- trainable=True,
- restore=True,
- scope=None,
- reuse=None):
- """Adds a 2D convolution followed by an optional batch_norm layer.
-
- conv2d creates a variable called 'weights', representing the convolutional
- kernel, that is convolved with the input. If `batch_norm_params` is None, a
- second variable called 'biases' is added to the result of the convolution
- operation.
-
- Args:
- inputs: a tensor of size [batch_size, height, width, channels].
- num_filters_out: the number of output filters.
- kernel_size: a list of length 2: [kernel_height, kernel_width] of
- of the filters. Can be an int if both values are the same.
- stride: a list of length 2: [stride_height, stride_width].
- Can be an int if both strides are the same. Note that presently
- both strides must have the same value.
- padding: one of 'VALID' or 'SAME'.
- activation: activation function.
- stddev: standard deviation of the truncated guassian weight distribution.
- bias: the initial value of the biases.
- weight_decay: the weight decay.
- batch_norm_params: parameters for the batch_norm. If is None don't use it.
- is_training: whether or not the model is in training mode.
- trainable: whether or not the variables should be trainable or not.
- restore: whether or not the variables should be marked for restore.
- scope: Optional scope for variable_scope.
- reuse: whether or not the layer and its variables should be reused. To be
- able to reuse the layer scope must be given.
- Returns:
- a tensor representing the output of the operation.
-
- """
- with tf.variable_scope(scope, 'Conv', [inputs], reuse=reuse):
- kernel_h, kernel_w = _two_element_tuple(kernel_size)
- stride_h, stride_w = _two_element_tuple(stride)
- num_filters_in = inputs.get_shape()[-1]
- weights_shape = [kernel_h, kernel_w,
- num_filters_in, num_filters_out]
- weights_initializer = tf.truncated_normal_initializer(stddev=stddev)
- l2_regularizer = None
- if weight_decay and weight_decay > 0:
- l2_regularizer = losses.l2_regularizer(weight_decay)
- weights = variables.variable('weights',
- shape=weights_shape,
- initializer=weights_initializer,
- regularizer=l2_regularizer,
- trainable=trainable,
- restore=restore)
- conv = tf.nn.conv2d(inputs, weights, [1, stride_h, stride_w, 1],
- padding=padding)
- if batch_norm_params is not None:
- with scopes.arg_scope([batch_norm], is_training=is_training,
- trainable=trainable, restore=restore):
- outputs = batch_norm(conv, **batch_norm_params)
- else:
- bias_shape = [num_filters_out,]
- bias_initializer = tf.constant_initializer(bias)
- biases = variables.variable('biases',
- shape=bias_shape,
- initializer=bias_initializer,
- trainable=trainable,
- restore=restore)
- outputs = tf.nn.bias_add(conv, biases)
- if activation:
- outputs = activation(outputs)
- return outputs
-
-
-@scopes.add_arg_scope
-def fc(inputs,
- num_units_out,
- activation=tf.nn.relu,
- stddev=0.01,
- bias=0.0,
- weight_decay=0,
- batch_norm_params=None,
- is_training=True,
- trainable=True,
- restore=True,
- scope=None,
- reuse=None):
- """Adds a fully connected layer followed by an optional batch_norm layer.
-
- FC creates a variable called 'weights', representing the fully connected
- weight matrix, that is multiplied by the input. If `batch_norm` is None, a
- second variable called 'biases' is added to the result of the initial
- vector-matrix multiplication.
-
- Args:
- inputs: a [B x N] tensor where B is the batch size and N is the number of
- input units in the layer.
- num_units_out: the number of output units in the layer.
- activation: activation function.
- stddev: the standard deviation for the weights.
- bias: the initial value of the biases.
- weight_decay: the weight decay.
- batch_norm_params: parameters for the batch_norm. If is None don't use it.
- is_training: whether or not the model is in training mode.
- trainable: whether or not the variables should be trainable or not.
- restore: whether or not the variables should be marked for restore.
- scope: Optional scope for variable_scope.
- reuse: whether or not the layer and its variables should be reused. To be
- able to reuse the layer scope must be given.
-
- Returns:
- the tensor variable representing the result of the series of operations.
- """
- with tf.variable_scope(scope, 'FC', [inputs], reuse=reuse):
- num_units_in = inputs.get_shape()[1]
- weights_shape = [num_units_in, num_units_out]
- weights_initializer = tf.truncated_normal_initializer(stddev=stddev)
- l2_regularizer = None
- if weight_decay and weight_decay > 0:
- l2_regularizer = losses.l2_regularizer(weight_decay)
- weights = variables.variable('weights',
- shape=weights_shape,
- initializer=weights_initializer,
- regularizer=l2_regularizer,
- trainable=trainable,
- restore=restore)
- if batch_norm_params is not None:
- outputs = tf.matmul(inputs, weights)
- with scopes.arg_scope([batch_norm], is_training=is_training,
- trainable=trainable, restore=restore):
- outputs = batch_norm(outputs, **batch_norm_params)
- else:
- bias_shape = [num_units_out,]
- bias_initializer = tf.constant_initializer(bias)
- biases = variables.variable('biases',
- shape=bias_shape,
- initializer=bias_initializer,
- trainable=trainable,
- restore=restore)
- outputs = tf.nn.xw_plus_b(inputs, weights, biases)
- if activation:
- outputs = activation(outputs)
- return outputs
-
-
-def one_hot_encoding(labels, num_classes, scope=None):
- """Transform numeric labels into onehot_labels.
-
- Args:
- labels: [batch_size] target labels.
- num_classes: total number of classes.
- scope: Optional scope for name_scope.
- Returns:
- one hot encoding of the labels.
- """
- with tf.name_scope(scope, 'OneHotEncoding', [labels]):
- batch_size = labels.get_shape()[0]
- indices = tf.expand_dims(tf.range(0, batch_size), 1)
- labels = tf.cast(tf.expand_dims(labels, 1), indices.dtype)
- concated = tf.concat(axis=1, values=[indices, labels])
- onehot_labels = tf.sparse_to_dense(
- concated, tf.stack([batch_size, num_classes]), 1.0, 0.0)
- onehot_labels.set_shape([batch_size, num_classes])
- return onehot_labels
-
-
-@scopes.add_arg_scope
-def max_pool(inputs, kernel_size, stride=2, padding='VALID', scope=None):
- """Adds a Max Pooling layer.
-
- It is assumed by the wrapper that the pooling is only done per image and not
- in depth or batch.
-
- Args:
- inputs: a tensor of size [batch_size, height, width, depth].
- kernel_size: a list of length 2: [kernel_height, kernel_width] of the
- pooling kernel over which the op is computed. Can be an int if both
- values are the same.
- stride: a list of length 2: [stride_height, stride_width].
- Can be an int if both strides are the same. Note that presently
- both strides must have the same value.
- padding: the padding method, either 'VALID' or 'SAME'.
- scope: Optional scope for name_scope.
-
- Returns:
- a tensor representing the results of the pooling operation.
- Raises:
- ValueError: if 'kernel_size' is not a 2-D list
- """
- with tf.name_scope(scope, 'MaxPool', [inputs]):
- kernel_h, kernel_w = _two_element_tuple(kernel_size)
- stride_h, stride_w = _two_element_tuple(stride)
- return tf.nn.max_pool(inputs,
- ksize=[1, kernel_h, kernel_w, 1],
- strides=[1, stride_h, stride_w, 1],
- padding=padding)
-
-
-@scopes.add_arg_scope
-def avg_pool(inputs, kernel_size, stride=2, padding='VALID', scope=None):
- """Adds a Avg Pooling layer.
-
- It is assumed by the wrapper that the pooling is only done per image and not
- in depth or batch.
-
- Args:
- inputs: a tensor of size [batch_size, height, width, depth].
- kernel_size: a list of length 2: [kernel_height, kernel_width] of the
- pooling kernel over which the op is computed. Can be an int if both
- values are the same.
- stride: a list of length 2: [stride_height, stride_width].
- Can be an int if both strides are the same. Note that presently
- both strides must have the same value.
- padding: the padding method, either 'VALID' or 'SAME'.
- scope: Optional scope for name_scope.
-
- Returns:
- a tensor representing the results of the pooling operation.
- """
- with tf.name_scope(scope, 'AvgPool', [inputs]):
- kernel_h, kernel_w = _two_element_tuple(kernel_size)
- stride_h, stride_w = _two_element_tuple(stride)
- return tf.nn.avg_pool(inputs,
- ksize=[1, kernel_h, kernel_w, 1],
- strides=[1, stride_h, stride_w, 1],
- padding=padding)
-
-
-@scopes.add_arg_scope
-def dropout(inputs, keep_prob=0.5, is_training=True, scope=None):
- """Returns a dropout layer applied to the input.
-
- Args:
- inputs: the tensor to pass to the Dropout layer.
- keep_prob: the probability of keeping each input unit.
- is_training: whether or not the model is in training mode. If so, dropout is
- applied and values scaled. Otherwise, inputs is returned.
- scope: Optional scope for name_scope.
-
- Returns:
- a tensor representing the output of the operation.
- """
- if is_training and keep_prob > 0:
- with tf.name_scope(scope, 'Dropout', [inputs]):
- return tf.nn.dropout(inputs, keep_prob)
- else:
- return inputs
-
-
-def flatten(inputs, scope=None):
- """Flattens the input while maintaining the batch_size.
-
- Assumes that the first dimension represents the batch.
-
- Args:
- inputs: a tensor of size [batch_size, ...].
- scope: Optional scope for name_scope.
-
- Returns:
- a flattened tensor with shape [batch_size, k].
- Raises:
- ValueError: if inputs.shape is wrong.
- """
- if len(inputs.get_shape()) < 2:
- raise ValueError('Inputs must be have a least 2 dimensions')
- dims = inputs.get_shape()[1:]
- k = dims.num_elements()
- with tf.name_scope(scope, 'Flatten', [inputs]):
- return tf.reshape(inputs, [-1, k])
-
-
-def repeat_op(repetitions, inputs, op, *args, **kwargs):
- """Build a sequential Tower starting from inputs by using an op repeatedly.
-
- It creates new scopes for each operation by increasing the counter.
- Example: given repeat_op(3, _, ops.conv2d, 64, [3, 3], scope='conv1')
- it will repeat the given op under the following variable_scopes:
- conv1/Conv
- conv1/Conv_1
- conv1/Conv_2
-
- Args:
- repetitions: number or repetitions.
- inputs: a tensor of size [batch_size, height, width, channels].
- op: an operation.
- *args: args for the op.
- **kwargs: kwargs for the op.
-
- Returns:
- a tensor result of applying the operation op, num times.
- Raises:
- ValueError: if the op is unknown or wrong.
- """
- scope = kwargs.pop('scope', None)
- with tf.variable_scope(scope, 'RepeatOp', [inputs]):
- tower = inputs
- for _ in range(repetitions):
- tower = op(tower, *args, **kwargs)
- return tower
diff --git a/research/inception/inception/slim/ops_test.py b/research/inception/inception/slim/ops_test.py
deleted file mode 100644
index 13dc5d9aacf6e283540a406d419a67d2d7215161..0000000000000000000000000000000000000000
--- a/research/inception/inception/slim/ops_test.py
+++ /dev/null
@@ -1,687 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tests for slim.ops."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import numpy as np
-import tensorflow as tf
-
-from inception.slim import ops
-from inception.slim import scopes
-from inception.slim import variables
-
-
-class ConvTest(tf.test.TestCase):
-
- def testCreateConv(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.conv2d(images, 32, [3, 3])
- self.assertEquals(output.op.name, 'Conv/Relu')
- self.assertListEqual(output.get_shape().as_list(), [5, height, width, 32])
-
- def testCreateSquareConv(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.conv2d(images, 32, 3)
- self.assertEquals(output.op.name, 'Conv/Relu')
- self.assertListEqual(output.get_shape().as_list(), [5, height, width, 32])
-
- def testCreateConvWithTensorShape(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.conv2d(images, 32, images.get_shape()[1:3])
- self.assertEquals(output.op.name, 'Conv/Relu')
- self.assertListEqual(output.get_shape().as_list(), [5, height, width, 32])
-
- def testCreateFullyConv(self):
- height, width = 6, 6
- with self.test_session():
- images = tf.random_uniform((5, height, width, 32), seed=1)
- output = ops.conv2d(images, 64, images.get_shape()[1:3], padding='VALID')
- self.assertEquals(output.op.name, 'Conv/Relu')
- self.assertListEqual(output.get_shape().as_list(), [5, 1, 1, 64])
-
- def testCreateVerticalConv(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.conv2d(images, 32, [3, 1])
- self.assertEquals(output.op.name, 'Conv/Relu')
- self.assertListEqual(output.get_shape().as_list(),
- [5, height, width, 32])
-
- def testCreateHorizontalConv(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.conv2d(images, 32, [1, 3])
- self.assertEquals(output.op.name, 'Conv/Relu')
- self.assertListEqual(output.get_shape().as_list(),
- [5, height, width, 32])
-
- def testCreateConvWithStride(self):
- height, width = 6, 6
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.conv2d(images, 32, [3, 3], stride=2)
- self.assertEquals(output.op.name, 'Conv/Relu')
- self.assertListEqual(output.get_shape().as_list(),
- [5, height/2, width/2, 32])
-
- def testCreateConvCreatesWeightsAndBiasesVars(self):
- height, width = 3, 3
- images = tf.random_uniform((5, height, width, 3), seed=1)
- with self.test_session():
- self.assertFalse(variables.get_variables('conv1/weights'))
- self.assertFalse(variables.get_variables('conv1/biases'))
- ops.conv2d(images, 32, [3, 3], scope='conv1')
- self.assertTrue(variables.get_variables('conv1/weights'))
- self.assertTrue(variables.get_variables('conv1/biases'))
-
- def testCreateConvWithScope(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.conv2d(images, 32, [3, 3], scope='conv1')
- self.assertEquals(output.op.name, 'conv1/Relu')
-
- def testCreateConvWithoutActivation(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.conv2d(images, 32, [3, 3], activation=None)
- self.assertEquals(output.op.name, 'Conv/BiasAdd')
-
- def testCreateConvValid(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.conv2d(images, 32, [3, 3], padding='VALID')
- self.assertListEqual(output.get_shape().as_list(), [5, 1, 1, 32])
-
- def testCreateConvWithWD(self):
- height, width = 3, 3
- with self.test_session() as sess:
- images = tf.random_uniform((5, height, width, 3), seed=1)
- ops.conv2d(images, 32, [3, 3], weight_decay=0.01)
- wd = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)[0]
- self.assertEquals(wd.op.name,
- 'Conv/weights/Regularizer/L2Regularizer/value')
- sess.run(tf.global_variables_initializer())
- self.assertTrue(sess.run(wd) <= 0.01)
-
- def testCreateConvWithoutWD(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- ops.conv2d(images, 32, [3, 3], weight_decay=0)
- self.assertEquals(
- tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES), [])
-
- def testReuseVars(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- ops.conv2d(images, 32, [3, 3], scope='conv1')
- self.assertEquals(len(variables.get_variables()), 2)
- ops.conv2d(images, 32, [3, 3], scope='conv1', reuse=True)
- self.assertEquals(len(variables.get_variables()), 2)
-
- def testNonReuseVars(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- ops.conv2d(images, 32, [3, 3])
- self.assertEquals(len(variables.get_variables()), 2)
- ops.conv2d(images, 32, [3, 3])
- self.assertEquals(len(variables.get_variables()), 4)
-
- def testReuseConvWithWD(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- ops.conv2d(images, 32, [3, 3], weight_decay=0.01, scope='conv1')
- self.assertEquals(len(variables.get_variables()), 2)
- self.assertEquals(
- len(tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)), 1)
- ops.conv2d(images, 32, [3, 3], weight_decay=0.01, scope='conv1',
- reuse=True)
- self.assertEquals(len(variables.get_variables()), 2)
- self.assertEquals(
- len(tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)), 1)
-
- def testConvWithBatchNorm(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 32), seed=1)
- with scopes.arg_scope([ops.conv2d], batch_norm_params={'decay': 0.9}):
- net = ops.conv2d(images, 32, [3, 3])
- net = ops.conv2d(net, 32, [3, 3])
- self.assertEquals(len(variables.get_variables()), 8)
- self.assertEquals(len(variables.get_variables('Conv/BatchNorm')), 3)
- self.assertEquals(len(variables.get_variables('Conv_1/BatchNorm')), 3)
-
- def testReuseConvWithBatchNorm(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 32), seed=1)
- with scopes.arg_scope([ops.conv2d], batch_norm_params={'decay': 0.9}):
- net = ops.conv2d(images, 32, [3, 3], scope='Conv')
- net = ops.conv2d(net, 32, [3, 3], scope='Conv', reuse=True)
- self.assertEquals(len(variables.get_variables()), 4)
- self.assertEquals(len(variables.get_variables('Conv/BatchNorm')), 3)
- self.assertEquals(len(variables.get_variables('Conv_1/BatchNorm')), 0)
-
-
-class FCTest(tf.test.TestCase):
-
- def testCreateFC(self):
- height, width = 3, 3
- with self.test_session():
- inputs = tf.random_uniform((5, height * width * 3), seed=1)
- output = ops.fc(inputs, 32)
- self.assertEquals(output.op.name, 'FC/Relu')
- self.assertListEqual(output.get_shape().as_list(), [5, 32])
-
- def testCreateFCWithScope(self):
- height, width = 3, 3
- with self.test_session():
- inputs = tf.random_uniform((5, height * width * 3), seed=1)
- output = ops.fc(inputs, 32, scope='fc1')
- self.assertEquals(output.op.name, 'fc1/Relu')
-
- def testCreateFcCreatesWeightsAndBiasesVars(self):
- height, width = 3, 3
- inputs = tf.random_uniform((5, height * width * 3), seed=1)
- with self.test_session():
- self.assertFalse(variables.get_variables('fc1/weights'))
- self.assertFalse(variables.get_variables('fc1/biases'))
- ops.fc(inputs, 32, scope='fc1')
- self.assertTrue(variables.get_variables('fc1/weights'))
- self.assertTrue(variables.get_variables('fc1/biases'))
-
- def testReuseVars(self):
- height, width = 3, 3
- inputs = tf.random_uniform((5, height * width * 3), seed=1)
- with self.test_session():
- ops.fc(inputs, 32, scope='fc1')
- self.assertEquals(len(variables.get_variables('fc1')), 2)
- ops.fc(inputs, 32, scope='fc1', reuse=True)
- self.assertEquals(len(variables.get_variables('fc1')), 2)
-
- def testNonReuseVars(self):
- height, width = 3, 3
- inputs = tf.random_uniform((5, height * width * 3), seed=1)
- with self.test_session():
- ops.fc(inputs, 32)
- self.assertEquals(len(variables.get_variables('FC')), 2)
- ops.fc(inputs, 32)
- self.assertEquals(len(variables.get_variables('FC')), 4)
-
- def testCreateFCWithoutActivation(self):
- height, width = 3, 3
- with self.test_session():
- inputs = tf.random_uniform((5, height * width * 3), seed=1)
- output = ops.fc(inputs, 32, activation=None)
- self.assertEquals(output.op.name, 'FC/xw_plus_b')
-
- def testCreateFCWithWD(self):
- height, width = 3, 3
- with self.test_session() as sess:
- inputs = tf.random_uniform((5, height * width * 3), seed=1)
- ops.fc(inputs, 32, weight_decay=0.01)
- wd = tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)[0]
- self.assertEquals(wd.op.name,
- 'FC/weights/Regularizer/L2Regularizer/value')
- sess.run(tf.global_variables_initializer())
- self.assertTrue(sess.run(wd) <= 0.01)
-
- def testCreateFCWithoutWD(self):
- height, width = 3, 3
- with self.test_session():
- inputs = tf.random_uniform((5, height * width * 3), seed=1)
- ops.fc(inputs, 32, weight_decay=0)
- self.assertEquals(
- tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES), [])
-
- def testReuseFCWithWD(self):
- height, width = 3, 3
- with self.test_session():
- inputs = tf.random_uniform((5, height * width * 3), seed=1)
- ops.fc(inputs, 32, weight_decay=0.01, scope='fc')
- self.assertEquals(len(variables.get_variables()), 2)
- self.assertEquals(
- len(tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)), 1)
- ops.fc(inputs, 32, weight_decay=0.01, scope='fc', reuse=True)
- self.assertEquals(len(variables.get_variables()), 2)
- self.assertEquals(
- len(tf.get_collection(tf.GraphKeys.REGULARIZATION_LOSSES)), 1)
-
- def testFCWithBatchNorm(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height * width * 3), seed=1)
- with scopes.arg_scope([ops.fc], batch_norm_params={}):
- net = ops.fc(images, 27)
- net = ops.fc(net, 27)
- self.assertEquals(len(variables.get_variables()), 8)
- self.assertEquals(len(variables.get_variables('FC/BatchNorm')), 3)
- self.assertEquals(len(variables.get_variables('FC_1/BatchNorm')), 3)
-
- def testReuseFCWithBatchNorm(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height * width * 3), seed=1)
- with scopes.arg_scope([ops.fc], batch_norm_params={'decay': 0.9}):
- net = ops.fc(images, 27, scope='fc1')
- net = ops.fc(net, 27, scope='fc1', reuse=True)
- self.assertEquals(len(variables.get_variables()), 4)
- self.assertEquals(len(variables.get_variables('fc1/BatchNorm')), 3)
-
-
-class MaxPoolTest(tf.test.TestCase):
-
- def testCreateMaxPool(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.max_pool(images, [3, 3])
- self.assertEquals(output.op.name, 'MaxPool/MaxPool')
- self.assertListEqual(output.get_shape().as_list(), [5, 1, 1, 3])
-
- def testCreateSquareMaxPool(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.max_pool(images, 3)
- self.assertEquals(output.op.name, 'MaxPool/MaxPool')
- self.assertListEqual(output.get_shape().as_list(), [5, 1, 1, 3])
-
- def testCreateMaxPoolWithScope(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.max_pool(images, [3, 3], scope='pool1')
- self.assertEquals(output.op.name, 'pool1/MaxPool')
-
- def testCreateMaxPoolSAME(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.max_pool(images, [3, 3], padding='SAME')
- self.assertListEqual(output.get_shape().as_list(), [5, 2, 2, 3])
-
- def testCreateMaxPoolStrideSAME(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.max_pool(images, [3, 3], stride=1, padding='SAME')
- self.assertListEqual(output.get_shape().as_list(), [5, height, width, 3])
-
- def testGlobalMaxPool(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.max_pool(images, images.get_shape()[1:3], stride=1)
- self.assertListEqual(output.get_shape().as_list(), [5, 1, 1, 3])
-
-
-class AvgPoolTest(tf.test.TestCase):
-
- def testCreateAvgPool(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.avg_pool(images, [3, 3])
- self.assertEquals(output.op.name, 'AvgPool/AvgPool')
- self.assertListEqual(output.get_shape().as_list(), [5, 1, 1, 3])
-
- def testCreateSquareAvgPool(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.avg_pool(images, 3)
- self.assertEquals(output.op.name, 'AvgPool/AvgPool')
- self.assertListEqual(output.get_shape().as_list(), [5, 1, 1, 3])
-
- def testCreateAvgPoolWithScope(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.avg_pool(images, [3, 3], scope='pool1')
- self.assertEquals(output.op.name, 'pool1/AvgPool')
-
- def testCreateAvgPoolSAME(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.avg_pool(images, [3, 3], padding='SAME')
- self.assertListEqual(output.get_shape().as_list(), [5, 2, 2, 3])
-
- def testCreateAvgPoolStrideSAME(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.avg_pool(images, [3, 3], stride=1, padding='SAME')
- self.assertListEqual(output.get_shape().as_list(), [5, height, width, 3])
-
- def testGlobalAvgPool(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.avg_pool(images, images.get_shape()[1:3], stride=1)
- self.assertListEqual(output.get_shape().as_list(), [5, 1, 1, 3])
-
-
-class OneHotEncodingTest(tf.test.TestCase):
-
- def testOneHotEncodingCreate(self):
- with self.test_session():
- labels = tf.constant([0, 1, 2])
- output = ops.one_hot_encoding(labels, num_classes=3)
- self.assertEquals(output.op.name, 'OneHotEncoding/SparseToDense')
- self.assertListEqual(output.get_shape().as_list(), [3, 3])
-
- def testOneHotEncoding(self):
- with self.test_session():
- labels = tf.constant([0, 1, 2])
- one_hot_labels = tf.constant([[1, 0, 0],
- [0, 1, 0],
- [0, 0, 1]])
- output = ops.one_hot_encoding(labels, num_classes=3)
- self.assertAllClose(output.eval(), one_hot_labels.eval())
-
-
-class DropoutTest(tf.test.TestCase):
-
- def testCreateDropout(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.dropout(images)
- self.assertEquals(output.op.name, 'Dropout/dropout/mul')
- output.get_shape().assert_is_compatible_with(images.get_shape())
-
- def testCreateDropoutNoTraining(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1, name='images')
- output = ops.dropout(images, is_training=False)
- self.assertEquals(output, images)
-
-
-class FlattenTest(tf.test.TestCase):
-
- def testFlatten4D(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1, name='images')
- output = ops.flatten(images)
- self.assertEquals(output.get_shape().num_elements(),
- images.get_shape().num_elements())
- self.assertEqual(output.get_shape()[0], images.get_shape()[0])
-
- def testFlatten3D(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width), seed=1, name='images')
- output = ops.flatten(images)
- self.assertEquals(output.get_shape().num_elements(),
- images.get_shape().num_elements())
- self.assertEqual(output.get_shape()[0], images.get_shape()[0])
-
- def testFlattenBatchSize(self):
- height, width = 3, 3
- with self.test_session() as sess:
- images = tf.random_uniform((5, height, width, 3), seed=1, name='images')
- inputs = tf.placeholder(tf.int32, (None, height, width, 3))
- output = ops.flatten(inputs)
- self.assertEquals(output.get_shape().as_list(),
- [None, height * width * 3])
- output = sess.run(output, {inputs: images.eval()})
- self.assertEquals(output.size,
- images.get_shape().num_elements())
- self.assertEqual(output.shape[0], images.get_shape()[0])
-
-
-class BatchNormTest(tf.test.TestCase):
-
- def testCreateOp(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- output = ops.batch_norm(images)
- self.assertTrue(output.op.name.startswith('BatchNorm/batchnorm'))
- self.assertListEqual(output.get_shape().as_list(), [5, height, width, 3])
-
- def testCreateVariables(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- ops.batch_norm(images)
- beta = variables.get_variables_by_name('beta')[0]
- self.assertEquals(beta.op.name, 'BatchNorm/beta')
- gamma = variables.get_variables_by_name('gamma')
- self.assertEquals(gamma, [])
- moving_mean = tf.moving_average_variables()[0]
- moving_variance = tf.moving_average_variables()[1]
- self.assertEquals(moving_mean.op.name, 'BatchNorm/moving_mean')
- self.assertEquals(moving_variance.op.name, 'BatchNorm/moving_variance')
-
- def testCreateVariablesWithScale(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- ops.batch_norm(images, scale=True)
- beta = variables.get_variables_by_name('beta')[0]
- gamma = variables.get_variables_by_name('gamma')[0]
- self.assertEquals(beta.op.name, 'BatchNorm/beta')
- self.assertEquals(gamma.op.name, 'BatchNorm/gamma')
- moving_mean = tf.moving_average_variables()[0]
- moving_variance = tf.moving_average_variables()[1]
- self.assertEquals(moving_mean.op.name, 'BatchNorm/moving_mean')
- self.assertEquals(moving_variance.op.name, 'BatchNorm/moving_variance')
-
- def testCreateVariablesWithoutCenterWithScale(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- ops.batch_norm(images, center=False, scale=True)
- beta = variables.get_variables_by_name('beta')
- self.assertEquals(beta, [])
- gamma = variables.get_variables_by_name('gamma')[0]
- self.assertEquals(gamma.op.name, 'BatchNorm/gamma')
- moving_mean = tf.moving_average_variables()[0]
- moving_variance = tf.moving_average_variables()[1]
- self.assertEquals(moving_mean.op.name, 'BatchNorm/moving_mean')
- self.assertEquals(moving_variance.op.name, 'BatchNorm/moving_variance')
-
- def testCreateVariablesWithoutCenterWithoutScale(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- ops.batch_norm(images, center=False, scale=False)
- beta = variables.get_variables_by_name('beta')
- self.assertEquals(beta, [])
- gamma = variables.get_variables_by_name('gamma')
- self.assertEquals(gamma, [])
- moving_mean = tf.moving_average_variables()[0]
- moving_variance = tf.moving_average_variables()[1]
- self.assertEquals(moving_mean.op.name, 'BatchNorm/moving_mean')
- self.assertEquals(moving_variance.op.name, 'BatchNorm/moving_variance')
-
- def testMovingAverageVariables(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- ops.batch_norm(images, scale=True)
- moving_mean = tf.moving_average_variables()[0]
- moving_variance = tf.moving_average_variables()[1]
- self.assertEquals(moving_mean.op.name, 'BatchNorm/moving_mean')
- self.assertEquals(moving_variance.op.name, 'BatchNorm/moving_variance')
-
- def testUpdateOps(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- ops.batch_norm(images)
- update_ops = tf.get_collection(ops.UPDATE_OPS_COLLECTION)
- update_moving_mean = update_ops[0]
- update_moving_variance = update_ops[1]
- self.assertEquals(update_moving_mean.op.name,
- 'BatchNorm/AssignMovingAvg')
- self.assertEquals(update_moving_variance.op.name,
- 'BatchNorm/AssignMovingAvg_1')
-
- def testReuseVariables(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- ops.batch_norm(images, scale=True, scope='bn')
- ops.batch_norm(images, scale=True, scope='bn', reuse=True)
- beta = variables.get_variables_by_name('beta')
- gamma = variables.get_variables_by_name('gamma')
- self.assertEquals(len(beta), 1)
- self.assertEquals(len(gamma), 1)
- moving_vars = tf.get_collection('moving_vars')
- self.assertEquals(len(moving_vars), 2)
-
- def testReuseUpdateOps(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- ops.batch_norm(images, scope='bn')
- self.assertEquals(len(tf.get_collection(ops.UPDATE_OPS_COLLECTION)), 2)
- ops.batch_norm(images, scope='bn', reuse=True)
- self.assertEquals(len(tf.get_collection(ops.UPDATE_OPS_COLLECTION)), 4)
-
- def testCreateMovingVars(self):
- height, width = 3, 3
- with self.test_session():
- images = tf.random_uniform((5, height, width, 3), seed=1)
- _ = ops.batch_norm(images, moving_vars='moving_vars')
- moving_mean = tf.get_collection('moving_vars',
- 'BatchNorm/moving_mean')
- self.assertEquals(len(moving_mean), 1)
- self.assertEquals(moving_mean[0].op.name, 'BatchNorm/moving_mean')
- moving_variance = tf.get_collection('moving_vars',
- 'BatchNorm/moving_variance')
- self.assertEquals(len(moving_variance), 1)
- self.assertEquals(moving_variance[0].op.name, 'BatchNorm/moving_variance')
-
- def testComputeMovingVars(self):
- height, width = 3, 3
- with self.test_session() as sess:
- image_shape = (10, height, width, 3)
- image_values = np.random.rand(*image_shape)
- expected_mean = np.mean(image_values, axis=(0, 1, 2))
- expected_var = np.var(image_values, axis=(0, 1, 2))
- images = tf.constant(image_values, shape=image_shape, dtype=tf.float32)
- output = ops.batch_norm(images, decay=0.1)
- update_ops = tf.get_collection(ops.UPDATE_OPS_COLLECTION)
- with tf.control_dependencies(update_ops):
- output = tf.identity(output)
- # Initialize all variables
- sess.run(tf.global_variables_initializer())
- moving_mean = variables.get_variables('BatchNorm/moving_mean')[0]
- moving_variance = variables.get_variables('BatchNorm/moving_variance')[0]
- mean, variance = sess.run([moving_mean, moving_variance])
- # After initialization moving_mean == 0 and moving_variance == 1.
- self.assertAllClose(mean, [0] * 3)
- self.assertAllClose(variance, [1] * 3)
- for _ in range(10):
- sess.run([output])
- mean = moving_mean.eval()
- variance = moving_variance.eval()
- # After 10 updates with decay 0.1 moving_mean == expected_mean and
- # moving_variance == expected_var.
- self.assertAllClose(mean, expected_mean)
- self.assertAllClose(variance, expected_var)
-
- def testEvalMovingVars(self):
- height, width = 3, 3
- with self.test_session() as sess:
- image_shape = (10, height, width, 3)
- image_values = np.random.rand(*image_shape)
- expected_mean = np.mean(image_values, axis=(0, 1, 2))
- expected_var = np.var(image_values, axis=(0, 1, 2))
- images = tf.constant(image_values, shape=image_shape, dtype=tf.float32)
- output = ops.batch_norm(images, decay=0.1, is_training=False)
- update_ops = tf.get_collection(ops.UPDATE_OPS_COLLECTION)
- with tf.control_dependencies(update_ops):
- output = tf.identity(output)
- # Initialize all variables
- sess.run(tf.global_variables_initializer())
- moving_mean = variables.get_variables('BatchNorm/moving_mean')[0]
- moving_variance = variables.get_variables('BatchNorm/moving_variance')[0]
- mean, variance = sess.run([moving_mean, moving_variance])
- # After initialization moving_mean == 0 and moving_variance == 1.
- self.assertAllClose(mean, [0] * 3)
- self.assertAllClose(variance, [1] * 3)
- # Simulate assigment from saver restore.
- init_assigns = [tf.assign(moving_mean, expected_mean),
- tf.assign(moving_variance, expected_var)]
- sess.run(init_assigns)
- for _ in range(10):
- sess.run([output], {images: np.random.rand(*image_shape)})
- mean = moving_mean.eval()
- variance = moving_variance.eval()
- # Although we feed different images, the moving_mean and moving_variance
- # shouldn't change.
- self.assertAllClose(mean, expected_mean)
- self.assertAllClose(variance, expected_var)
-
- def testReuseVars(self):
- height, width = 3, 3
- with self.test_session() as sess:
- image_shape = (10, height, width, 3)
- image_values = np.random.rand(*image_shape)
- expected_mean = np.mean(image_values, axis=(0, 1, 2))
- expected_var = np.var(image_values, axis=(0, 1, 2))
- images = tf.constant(image_values, shape=image_shape, dtype=tf.float32)
- output = ops.batch_norm(images, decay=0.1, is_training=False)
- update_ops = tf.get_collection(ops.UPDATE_OPS_COLLECTION)
- with tf.control_dependencies(update_ops):
- output = tf.identity(output)
- # Initialize all variables
- sess.run(tf.global_variables_initializer())
- moving_mean = variables.get_variables('BatchNorm/moving_mean')[0]
- moving_variance = variables.get_variables('BatchNorm/moving_variance')[0]
- mean, variance = sess.run([moving_mean, moving_variance])
- # After initialization moving_mean == 0 and moving_variance == 1.
- self.assertAllClose(mean, [0] * 3)
- self.assertAllClose(variance, [1] * 3)
- # Simulate assigment from saver restore.
- init_assigns = [tf.assign(moving_mean, expected_mean),
- tf.assign(moving_variance, expected_var)]
- sess.run(init_assigns)
- for _ in range(10):
- sess.run([output], {images: np.random.rand(*image_shape)})
- mean = moving_mean.eval()
- variance = moving_variance.eval()
- # Although we feed different images, the moving_mean and moving_variance
- # shouldn't change.
- self.assertAllClose(mean, expected_mean)
- self.assertAllClose(variance, expected_var)
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/inception/inception/slim/scopes.py b/research/inception/inception/slim/scopes.py
deleted file mode 100644
index 2c2fb0a2efa7d30eaddb36fc30265f30cbaeb9ef..0000000000000000000000000000000000000000
--- a/research/inception/inception/slim/scopes.py
+++ /dev/null
@@ -1,170 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Contains the new arg_scope used for TF-Slim ops.
-
- Allows one to define models much more compactly by eliminating boilerplate
- code. This is accomplished through the use of argument scoping (arg_scope).
-
- Example of how to use scopes.arg_scope:
-
- with scopes.arg_scope(ops.conv2d, padding='SAME',
- stddev=0.01, weight_decay=0.0005):
- net = ops.conv2d(inputs, 64, [11, 11], 4, padding='VALID', scope='conv1')
- net = ops.conv2d(net, 256, [5, 5], scope='conv2')
-
- The first call to conv2d will overwrite padding:
- ops.conv2d(inputs, 64, [11, 11], 4, padding='VALID',
- stddev=0.01, weight_decay=0.0005, scope='conv1')
-
- The second call to Conv will use predefined args:
- ops.conv2d(inputs, 256, [5, 5], padding='SAME',
- stddev=0.01, weight_decay=0.0005, scope='conv2')
-
- Example of how to reuse an arg_scope:
- with scopes.arg_scope(ops.conv2d, padding='SAME',
- stddev=0.01, weight_decay=0.0005) as conv2d_arg_scope:
- net = ops.conv2d(net, 256, [5, 5], scope='conv1')
- ....
-
- with scopes.arg_scope(conv2d_arg_scope):
- net = ops.conv2d(net, 256, [5, 5], scope='conv2')
-
- Example of how to use scopes.add_arg_scope:
-
- @scopes.add_arg_scope
- def conv2d(*args, **kwargs)
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import contextlib
-import functools
-
-from tensorflow.python.framework import ops
-
-_ARGSTACK_KEY = ("__arg_stack",)
-
-_DECORATED_OPS = set()
-
-
-def _get_arg_stack():
- stack = ops.get_collection(_ARGSTACK_KEY)
- if stack:
- return stack[0]
- else:
- stack = [{}]
- ops.add_to_collection(_ARGSTACK_KEY, stack)
- return stack
-
-
-def _current_arg_scope():
- stack = _get_arg_stack()
- return stack[-1]
-
-
-def _add_op(op):
- key_op = (op.__module__, op.__name__)
- if key_op not in _DECORATED_OPS:
- _DECORATED_OPS.add(key_op)
-
-
-@contextlib.contextmanager
-def arg_scope(list_ops_or_scope, **kwargs):
- """Stores the default arguments for the given set of list_ops.
-
- For usage, please see examples at top of the file.
-
- Args:
- list_ops_or_scope: List or tuple of operations to set argument scope for or
- a dictionary containg the current scope. When list_ops_or_scope is a dict,
- kwargs must be empty. When list_ops_or_scope is a list or tuple, then
- every op in it need to be decorated with @add_arg_scope to work.
- **kwargs: keyword=value that will define the defaults for each op in
- list_ops. All the ops need to accept the given set of arguments.
-
- Yields:
- the current_scope, which is a dictionary of {op: {arg: value}}
- Raises:
- TypeError: if list_ops is not a list or a tuple.
- ValueError: if any op in list_ops has not be decorated with @add_arg_scope.
- """
- if isinstance(list_ops_or_scope, dict):
- # Assumes that list_ops_or_scope is a scope that is being reused.
- if kwargs:
- raise ValueError("When attempting to re-use a scope by suppling a"
- "dictionary, kwargs must be empty.")
- current_scope = list_ops_or_scope.copy()
- try:
- _get_arg_stack().append(current_scope)
- yield current_scope
- finally:
- _get_arg_stack().pop()
- else:
- # Assumes that list_ops_or_scope is a list/tuple of ops with kwargs.
- if not isinstance(list_ops_or_scope, (list, tuple)):
- raise TypeError("list_ops_or_scope must either be a list/tuple or reused"
- "scope (i.e. dict)")
- try:
- current_scope = _current_arg_scope().copy()
- for op in list_ops_or_scope:
- key_op = (op.__module__, op.__name__)
- if not has_arg_scope(op):
- raise ValueError("%s is not decorated with @add_arg_scope", key_op)
- if key_op in current_scope:
- current_kwargs = current_scope[key_op].copy()
- current_kwargs.update(kwargs)
- current_scope[key_op] = current_kwargs
- else:
- current_scope[key_op] = kwargs.copy()
- _get_arg_stack().append(current_scope)
- yield current_scope
- finally:
- _get_arg_stack().pop()
-
-
-def add_arg_scope(func):
- """Decorates a function with args so it can be used within an arg_scope.
-
- Args:
- func: function to decorate.
-
- Returns:
- A tuple with the decorated function func_with_args().
- """
- @functools.wraps(func)
- def func_with_args(*args, **kwargs):
- current_scope = _current_arg_scope()
- current_args = kwargs
- key_func = (func.__module__, func.__name__)
- if key_func in current_scope:
- current_args = current_scope[key_func].copy()
- current_args.update(kwargs)
- return func(*args, **current_args)
- _add_op(func)
- return func_with_args
-
-
-def has_arg_scope(func):
- """Checks whether a func has been decorated with @add_arg_scope or not.
-
- Args:
- func: function to check.
-
- Returns:
- a boolean.
- """
- key_op = (func.__module__, func.__name__)
- return key_op in _DECORATED_OPS
diff --git a/research/inception/inception/slim/scopes_test.py b/research/inception/inception/slim/scopes_test.py
deleted file mode 100644
index cd349399ed7300dde38ac9bcb9818abc9d0680b4..0000000000000000000000000000000000000000
--- a/research/inception/inception/slim/scopes_test.py
+++ /dev/null
@@ -1,162 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tests slim.scopes."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import tensorflow as tf
-from inception.slim import scopes
-
-
-@scopes.add_arg_scope
-def func1(*args, **kwargs):
- return (args, kwargs)
-
-
-@scopes.add_arg_scope
-def func2(*args, **kwargs):
- return (args, kwargs)
-
-
-class ArgScopeTest(tf.test.TestCase):
-
- def testEmptyArgScope(self):
- with self.test_session():
- self.assertEqual(scopes._current_arg_scope(), {})
-
- def testCurrentArgScope(self):
- func1_kwargs = {'a': 1, 'b': None, 'c': [1]}
- key_op = (func1.__module__, func1.__name__)
- current_scope = {key_op: func1_kwargs.copy()}
- with self.test_session():
- with scopes.arg_scope([func1], a=1, b=None, c=[1]) as scope:
- self.assertDictEqual(scope, current_scope)
-
- def testCurrentArgScopeNested(self):
- func1_kwargs = {'a': 1, 'b': None, 'c': [1]}
- func2_kwargs = {'b': 2, 'd': [2]}
- key = lambda f: (f.__module__, f.__name__)
- current_scope = {key(func1): func1_kwargs.copy(),
- key(func2): func2_kwargs.copy()}
- with self.test_session():
- with scopes.arg_scope([func1], a=1, b=None, c=[1]):
- with scopes.arg_scope([func2], b=2, d=[2]) as scope:
- self.assertDictEqual(scope, current_scope)
-
- def testReuseArgScope(self):
- func1_kwargs = {'a': 1, 'b': None, 'c': [1]}
- key_op = (func1.__module__, func1.__name__)
- current_scope = {key_op: func1_kwargs.copy()}
- with self.test_session():
- with scopes.arg_scope([func1], a=1, b=None, c=[1]) as scope1:
- pass
- with scopes.arg_scope(scope1) as scope:
- self.assertDictEqual(scope, current_scope)
-
- def testReuseArgScopeNested(self):
- func1_kwargs = {'a': 1, 'b': None, 'c': [1]}
- func2_kwargs = {'b': 2, 'd': [2]}
- key = lambda f: (f.__module__, f.__name__)
- current_scope1 = {key(func1): func1_kwargs.copy()}
- current_scope2 = {key(func1): func1_kwargs.copy(),
- key(func2): func2_kwargs.copy()}
- with self.test_session():
- with scopes.arg_scope([func1], a=1, b=None, c=[1]) as scope1:
- with scopes.arg_scope([func2], b=2, d=[2]) as scope2:
- pass
- with scopes.arg_scope(scope1):
- self.assertDictEqual(scopes._current_arg_scope(), current_scope1)
- with scopes.arg_scope(scope2):
- self.assertDictEqual(scopes._current_arg_scope(), current_scope2)
-
- def testSimpleArgScope(self):
- func1_args = (0,)
- func1_kwargs = {'a': 1, 'b': None, 'c': [1]}
- with self.test_session():
- with scopes.arg_scope([func1], a=1, b=None, c=[1]):
- args, kwargs = func1(0)
- self.assertTupleEqual(args, func1_args)
- self.assertDictEqual(kwargs, func1_kwargs)
-
- def testSimpleArgScopeWithTuple(self):
- func1_args = (0,)
- func1_kwargs = {'a': 1, 'b': None, 'c': [1]}
- with self.test_session():
- with scopes.arg_scope((func1,), a=1, b=None, c=[1]):
- args, kwargs = func1(0)
- self.assertTupleEqual(args, func1_args)
- self.assertDictEqual(kwargs, func1_kwargs)
-
- def testOverwriteArgScope(self):
- func1_args = (0,)
- func1_kwargs = {'a': 1, 'b': 2, 'c': [1]}
- with scopes.arg_scope([func1], a=1, b=None, c=[1]):
- args, kwargs = func1(0, b=2)
- self.assertTupleEqual(args, func1_args)
- self.assertDictEqual(kwargs, func1_kwargs)
-
- def testNestedArgScope(self):
- func1_args = (0,)
- func1_kwargs = {'a': 1, 'b': None, 'c': [1]}
- with scopes.arg_scope([func1], a=1, b=None, c=[1]):
- args, kwargs = func1(0)
- self.assertTupleEqual(args, func1_args)
- self.assertDictEqual(kwargs, func1_kwargs)
- func1_kwargs['b'] = 2
- with scopes.arg_scope([func1], b=2):
- args, kwargs = func1(0)
- self.assertTupleEqual(args, func1_args)
- self.assertDictEqual(kwargs, func1_kwargs)
-
- def testSharedArgScope(self):
- func1_args = (0,)
- func1_kwargs = {'a': 1, 'b': None, 'c': [1]}
- with scopes.arg_scope([func1, func2], a=1, b=None, c=[1]):
- args, kwargs = func1(0)
- self.assertTupleEqual(args, func1_args)
- self.assertDictEqual(kwargs, func1_kwargs)
- args, kwargs = func2(0)
- self.assertTupleEqual(args, func1_args)
- self.assertDictEqual(kwargs, func1_kwargs)
-
- def testSharedArgScopeTuple(self):
- func1_args = (0,)
- func1_kwargs = {'a': 1, 'b': None, 'c': [1]}
- with scopes.arg_scope((func1, func2), a=1, b=None, c=[1]):
- args, kwargs = func1(0)
- self.assertTupleEqual(args, func1_args)
- self.assertDictEqual(kwargs, func1_kwargs)
- args, kwargs = func2(0)
- self.assertTupleEqual(args, func1_args)
- self.assertDictEqual(kwargs, func1_kwargs)
-
- def testPartiallySharedArgScope(self):
- func1_args = (0,)
- func1_kwargs = {'a': 1, 'b': None, 'c': [1]}
- func2_args = (1,)
- func2_kwargs = {'a': 1, 'b': None, 'd': [2]}
- with scopes.arg_scope([func1, func2], a=1, b=None):
- with scopes.arg_scope([func1], c=[1]), scopes.arg_scope([func2], d=[2]):
- args, kwargs = func1(0)
- self.assertTupleEqual(args, func1_args)
- self.assertDictEqual(kwargs, func1_kwargs)
- args, kwargs = func2(1)
- self.assertTupleEqual(args, func2_args)
- self.assertDictEqual(kwargs, func2_kwargs)
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/inception/inception/slim/slim.py b/research/inception/inception/slim/slim.py
deleted file mode 100644
index b7a5c0f8c52b66db899835480c331ffafdc386e2..0000000000000000000000000000000000000000
--- a/research/inception/inception/slim/slim.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""TF-Slim grouped API. Please see README.md for details and usage."""
-# pylint: disable=unused-import
-
-# Collapse tf-slim into a single namespace.
-from inception.slim import inception_model as inception
-from inception.slim import losses
-from inception.slim import ops
-from inception.slim import scopes
-from inception.slim import variables
-from inception.slim.scopes import arg_scope
diff --git a/research/inception/inception/slim/variables.py b/research/inception/inception/slim/variables.py
deleted file mode 100644
index 1d967b79e9563724b1114995a732cfd4dd486afd..0000000000000000000000000000000000000000
--- a/research/inception/inception/slim/variables.py
+++ /dev/null
@@ -1,289 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Contains convenience wrappers for creating variables in TF-Slim.
-
-The variables module is typically used for defining model variables from the
-ops routines (see slim.ops). Such variables are used for training, evaluation
-and inference of models.
-
-All the variables created through this module would be added to the
-MODEL_VARIABLES collection, if you create a model variable outside slim, it can
-be added with slim.variables.add_variable(external_variable, reuse).
-
-Usage:
- weights_initializer = tf.truncated_normal_initializer(stddev=0.01)
- l2_regularizer = lambda t: losses.l2_loss(t, weight=0.0005)
- weights = variables.variable('weights',
- shape=[100, 100],
- initializer=weights_initializer,
- regularizer=l2_regularizer,
- device='/cpu:0')
-
- biases = variables.variable('biases',
- shape=[100],
- initializer=tf.zeros_initializer(),
- device='/cpu:0')
-
- # More complex example.
-
- net = slim.ops.conv2d(input, 32, [3, 3], scope='conv1')
- net = slim.ops.conv2d(net, 64, [3, 3], scope='conv2')
- with slim.arg_scope([variables.variable], restore=False):
- net = slim.ops.conv2d(net, 64, [3, 3], scope='conv3')
-
- # Get all model variables from all the layers.
- model_variables = slim.variables.get_variables()
-
- # Get all model variables from a specific the layer, i.e 'conv1'.
- conv1_variables = slim.variables.get_variables('conv1')
-
- # Get all weights from all the layers.
- weights = slim.variables.get_variables_by_name('weights')
-
- # Get all bias from all the layers.
- biases = slim.variables.get_variables_by_name('biases')
-
- # Get all variables to restore.
- # (i.e. only those created by 'conv1' and 'conv2')
- variables_to_restore = slim.variables.get_variables_to_restore()
-
-************************************************
-* Initializing model variables from a checkpoint
-************************************************
-
-# Create some variables.
-v1 = slim.variables.variable(name="v1", ..., restore=False)
-v2 = slim.variables.variable(name="v2", ...) # By default restore=True
-...
-# The list of variables to restore should only contain 'v2'.
-variables_to_restore = slim.variables.get_variables_to_restore()
-restorer = tf.train.Saver(variables_to_restore)
-with tf.Session() as sess:
- # Restore variables from disk.
- restorer.restore(sess, "/tmp/model.ckpt")
- print("Model restored.")
- # Do some work with the model
- ...
-
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-from inception.slim import scopes
-
-# Collection containing all the variables created using slim.variables
-MODEL_VARIABLES = '_model_variables_'
-
-# Collection containing the slim.variables that are created with restore=True.
-VARIABLES_TO_RESTORE = '_variables_to_restore_'
-
-
-def add_variable(var, restore=True):
- """Adds a variable to the MODEL_VARIABLES collection.
-
- Optionally it will add the variable to the VARIABLES_TO_RESTORE collection.
- Args:
- var: a variable.
- restore: whether the variable should be added to the
- VARIABLES_TO_RESTORE collection.
-
- """
- collections = [MODEL_VARIABLES]
- if restore:
- collections.append(VARIABLES_TO_RESTORE)
- for collection in collections:
- if var not in tf.get_collection(collection):
- tf.add_to_collection(collection, var)
-
-
-def get_variables(scope=None, suffix=None):
- """Gets the list of variables, filtered by scope and/or suffix.
-
- Args:
- scope: an optional scope for filtering the variables to return.
- suffix: an optional suffix for filtering the variables to return.
-
- Returns:
- a copied list of variables with scope and suffix.
- """
- candidates = tf.get_collection(MODEL_VARIABLES, scope)[:]
- if suffix is not None:
- candidates = [var for var in candidates if var.op.name.endswith(suffix)]
- return candidates
-
-
-def get_variables_to_restore():
- """Gets the list of variables to restore.
-
- Returns:
- a copied list of variables.
- """
- return tf.get_collection(VARIABLES_TO_RESTORE)[:]
-
-
-def get_variables_by_name(given_name, scope=None):
- """Gets the list of variables that were given that name.
-
- Args:
- given_name: name given to the variable without scope.
- scope: an optional scope for filtering the variables to return.
-
- Returns:
- a copied list of variables with the given name and prefix.
- """
- return get_variables(scope=scope, suffix=given_name)
-
-
-def get_unique_variable(name):
- """Gets the variable uniquely identified by that name.
-
- Args:
- name: a name that uniquely identifies the variable.
-
- Returns:
- a tensorflow variable.
-
- Raises:
- ValueError: if no variable uniquely identified by the name exists.
- """
- candidates = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, name)
- if not candidates:
- raise ValueError('Couldnt find variable %s' % name)
-
- for candidate in candidates:
- if candidate.op.name == name:
- return candidate
- raise ValueError('Variable %s does not uniquely identify a variable', name)
-
-
-class VariableDeviceChooser(object):
- """Slim device chooser for variables.
-
- When using a parameter server it will assign them in a round-robin fashion.
- When not using a parameter server it allows GPU:0 placement otherwise CPU:0.
- """
-
- def __init__(self,
- num_parameter_servers=0,
- ps_device='/job:ps',
- placement='CPU:0'):
- """Initialize VariableDeviceChooser.
-
- Args:
- num_parameter_servers: number of parameter servers.
- ps_device: string representing the parameter server device.
- placement: string representing the placement of the variable either CPU:0
- or GPU:0. When using parameter servers forced to CPU:0.
- """
- self._num_ps = num_parameter_servers
- self._ps_device = ps_device
- self._placement = placement if num_parameter_servers == 0 else 'CPU:0'
- self._next_task_id = 0
-
- def __call__(self, op):
- device_string = ''
- if self._num_ps > 0:
- task_id = self._next_task_id
- self._next_task_id = (self._next_task_id + 1) % self._num_ps
- device_string = '%s/task:%d' % (self._ps_device, task_id)
- device_string += '/%s' % self._placement
- return device_string
-
-
-# TODO(sguada) Remove once get_variable is able to colocate op.devices.
-def variable_device(device, name):
- """Fix the variable device to colocate its ops."""
- if callable(device):
- var_name = tf.get_variable_scope().name + '/' + name
- var_def = tf.NodeDef(name=var_name, op='Variable')
- device = device(var_def)
- if device is None:
- device = ''
- return device
-
-
-@scopes.add_arg_scope
-def global_step(device=''):
- """Returns the global step variable.
-
- Args:
- device: Optional device to place the variable. It can be an string or a
- function that is called to get the device for the variable.
-
- Returns:
- the tensor representing the global step variable.
- """
- global_step_ref = tf.get_collection(tf.GraphKeys.GLOBAL_STEP)
- if global_step_ref:
- return global_step_ref[0]
- else:
- collections = [
- VARIABLES_TO_RESTORE,
- tf.GraphKeys.GLOBAL_VARIABLES,
- tf.GraphKeys.GLOBAL_STEP,
- ]
- # Get the device for the variable.
- with tf.device(variable_device(device, 'global_step')):
- return tf.get_variable('global_step', shape=[], dtype=tf.int64,
- initializer=tf.zeros_initializer(),
- trainable=False, collections=collections)
-
-
-@scopes.add_arg_scope
-def variable(name, shape=None, dtype=tf.float32, initializer=None,
- regularizer=None, trainable=True, collections=None, device='',
- restore=True):
- """Gets an existing variable with these parameters or creates a new one.
-
- It also add itself to a group with its name.
-
- Args:
- name: the name of the new or existing variable.
- shape: shape of the new or existing variable.
- dtype: type of the new or existing variable (defaults to `DT_FLOAT`).
- initializer: initializer for the variable if one is created.
- regularizer: a (Tensor -> Tensor or None) function; the result of
- applying it on a newly created variable will be added to the collection
- GraphKeys.REGULARIZATION_LOSSES and can be used for regularization.
- trainable: If `True` also add the variable to the graph collection
- `GraphKeys.TRAINABLE_VARIABLES` (see tf.Variable).
- collections: A list of collection names to which the Variable will be added.
- Note that the variable is always also added to the tf.GraphKeys.GLOBAL_VARIABLES
- and MODEL_VARIABLES collections.
- device: Optional device to place the variable. It can be an string or a
- function that is called to get the device for the variable.
- restore: whether the variable should be added to the
- VARIABLES_TO_RESTORE collection.
-
- Returns:
- The created or existing variable.
- """
- collections = list(collections or [])
-
- # Make sure variables are added to tf.GraphKeys.GLOBAL_VARIABLES and MODEL_VARIABLES
- collections += [tf.GraphKeys.GLOBAL_VARIABLES, MODEL_VARIABLES]
- # Add to VARIABLES_TO_RESTORE if necessary
- if restore:
- collections.append(VARIABLES_TO_RESTORE)
- # Remove duplicates
- collections = set(collections)
- # Get the device for the variable.
- with tf.device(variable_device(device, name)):
- return tf.get_variable(name, shape=shape, dtype=dtype,
- initializer=initializer, regularizer=regularizer,
- trainable=trainable, collections=collections)
diff --git a/research/inception/inception/slim/variables_test.py b/research/inception/inception/slim/variables_test.py
deleted file mode 100644
index b8c1944dfeb0fba7ad99f104b0c366c41d737c63..0000000000000000000000000000000000000000
--- a/research/inception/inception/slim/variables_test.py
+++ /dev/null
@@ -1,392 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tests for slim.variables."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-from inception.slim import scopes
-from inception.slim import variables
-
-
-class VariablesTest(tf.test.TestCase):
-
- def testCreateVariable(self):
- with self.test_session():
- with tf.variable_scope('A'):
- a = variables.variable('a', [5])
- self.assertEquals(a.op.name, 'A/a')
- self.assertListEqual(a.get_shape().as_list(), [5])
-
- def testGetVariables(self):
- with self.test_session():
- with tf.variable_scope('A'):
- a = variables.variable('a', [5])
- with tf.variable_scope('B'):
- b = variables.variable('a', [5])
- self.assertEquals([a, b], variables.get_variables())
- self.assertEquals([a], variables.get_variables('A'))
- self.assertEquals([b], variables.get_variables('B'))
-
- def testGetVariablesSuffix(self):
- with self.test_session():
- with tf.variable_scope('A'):
- a = variables.variable('a', [5])
- with tf.variable_scope('A'):
- b = variables.variable('b', [5])
- self.assertEquals([a], variables.get_variables(suffix='a'))
- self.assertEquals([b], variables.get_variables(suffix='b'))
-
- def testGetVariableWithSingleVar(self):
- with self.test_session():
- with tf.variable_scope('parent'):
- a = variables.variable('child', [5])
- self.assertEquals(a, variables.get_unique_variable('parent/child'))
-
- def testGetVariableWithDistractors(self):
- with self.test_session():
- with tf.variable_scope('parent'):
- a = variables.variable('child', [5])
- with tf.variable_scope('child'):
- variables.variable('grandchild1', [7])
- variables.variable('grandchild2', [9])
- self.assertEquals(a, variables.get_unique_variable('parent/child'))
-
- def testGetVariableThrowsExceptionWithNoMatch(self):
- var_name = 'cant_find_me'
- with self.test_session():
- with self.assertRaises(ValueError):
- variables.get_unique_variable(var_name)
-
- def testGetThrowsExceptionWithChildrenButNoMatch(self):
- var_name = 'parent/child'
- with self.test_session():
- with tf.variable_scope(var_name):
- variables.variable('grandchild1', [7])
- variables.variable('grandchild2', [9])
- with self.assertRaises(ValueError):
- variables.get_unique_variable(var_name)
-
- def testGetVariablesToRestore(self):
- with self.test_session():
- with tf.variable_scope('A'):
- a = variables.variable('a', [5])
- with tf.variable_scope('B'):
- b = variables.variable('a', [5])
- self.assertEquals([a, b], variables.get_variables_to_restore())
-
- def testNoneGetVariablesToRestore(self):
- with self.test_session():
- with tf.variable_scope('A'):
- a = variables.variable('a', [5], restore=False)
- with tf.variable_scope('B'):
- b = variables.variable('a', [5], restore=False)
- self.assertEquals([], variables.get_variables_to_restore())
- self.assertEquals([a, b], variables.get_variables())
-
- def testGetMixedVariablesToRestore(self):
- with self.test_session():
- with tf.variable_scope('A'):
- a = variables.variable('a', [5])
- b = variables.variable('b', [5], restore=False)
- with tf.variable_scope('B'):
- c = variables.variable('c', [5])
- d = variables.variable('d', [5], restore=False)
- self.assertEquals([a, b, c, d], variables.get_variables())
- self.assertEquals([a, c], variables.get_variables_to_restore())
-
- def testReuseVariable(self):
- with self.test_session():
- with tf.variable_scope('A'):
- a = variables.variable('a', [])
- with tf.variable_scope('A', reuse=True):
- b = variables.variable('a', [])
- self.assertEquals(a, b)
- self.assertListEqual([a], variables.get_variables())
-
- def testVariableWithDevice(self):
- with self.test_session():
- with tf.variable_scope('A'):
- a = variables.variable('a', [], device='cpu:0')
- b = variables.variable('b', [], device='cpu:1')
- self.assertDeviceEqual(a.device, 'cpu:0')
- self.assertDeviceEqual(b.device, 'cpu:1')
-
- def testVariableWithDeviceFromScope(self):
- with self.test_session():
- with tf.device('/cpu:0'):
- a = variables.variable('a', [])
- b = variables.variable('b', [], device='cpu:1')
- self.assertDeviceEqual(a.device, 'cpu:0')
- self.assertDeviceEqual(b.device, 'cpu:1')
-
- def testVariableWithDeviceFunction(self):
- class DevFn(object):
-
- def __init__(self):
- self.counter = -1
-
- def __call__(self, op):
- self.counter += 1
- return 'cpu:%d' % self.counter
-
- with self.test_session():
- with scopes.arg_scope([variables.variable], device=DevFn()):
- a = variables.variable('a', [])
- b = variables.variable('b', [])
- c = variables.variable('c', [], device='cpu:12')
- d = variables.variable('d', [])
- with tf.device('cpu:99'):
- e_init = tf.constant(12)
- e = variables.variable('e', initializer=e_init)
- self.assertDeviceEqual(a.device, 'cpu:0')
- self.assertDeviceEqual(a.initial_value.device, 'cpu:0')
- self.assertDeviceEqual(b.device, 'cpu:1')
- self.assertDeviceEqual(b.initial_value.device, 'cpu:1')
- self.assertDeviceEqual(c.device, 'cpu:12')
- self.assertDeviceEqual(c.initial_value.device, 'cpu:12')
- self.assertDeviceEqual(d.device, 'cpu:2')
- self.assertDeviceEqual(d.initial_value.device, 'cpu:2')
- self.assertDeviceEqual(e.device, 'cpu:3')
- self.assertDeviceEqual(e.initial_value.device, 'cpu:99')
-
- def testVariableWithReplicaDeviceSetter(self):
- with self.test_session():
- with tf.device(tf.train.replica_device_setter(ps_tasks=2)):
- a = variables.variable('a', [])
- b = variables.variable('b', [])
- c = variables.variable('c', [], device='cpu:12')
- d = variables.variable('d', [])
- with tf.device('cpu:99'):
- e_init = tf.constant(12)
- e = variables.variable('e', initializer=e_init)
- # The values below highlight how the replica_device_setter puts initial
- # values on the worker job, and how it merges explicit devices.
- self.assertDeviceEqual(a.device, '/job:ps/task:0/cpu:0')
- self.assertDeviceEqual(a.initial_value.device, '/job:worker/cpu:0')
- self.assertDeviceEqual(b.device, '/job:ps/task:1/cpu:0')
- self.assertDeviceEqual(b.initial_value.device, '/job:worker/cpu:0')
- self.assertDeviceEqual(c.device, '/job:ps/task:0/cpu:12')
- self.assertDeviceEqual(c.initial_value.device, '/job:worker/cpu:12')
- self.assertDeviceEqual(d.device, '/job:ps/task:1/cpu:0')
- self.assertDeviceEqual(d.initial_value.device, '/job:worker/cpu:0')
- self.assertDeviceEqual(e.device, '/job:ps/task:0/cpu:0')
- self.assertDeviceEqual(e.initial_value.device, '/job:worker/cpu:99')
-
- def testVariableWithVariableDeviceChooser(self):
-
- with tf.Graph().as_default():
- device_fn = variables.VariableDeviceChooser(num_parameter_servers=2)
- with scopes.arg_scope([variables.variable], device=device_fn):
- a = variables.variable('a', [])
- b = variables.variable('b', [])
- c = variables.variable('c', [], device='cpu:12')
- d = variables.variable('d', [])
- with tf.device('cpu:99'):
- e_init = tf.constant(12)
- e = variables.variable('e', initializer=e_init)
- # The values below highlight how the VariableDeviceChooser puts initial
- # values on the same device as the variable job.
- self.assertDeviceEqual(a.device, '/job:ps/task:0/cpu:0')
- self.assertDeviceEqual(a.initial_value.device, a.device)
- self.assertDeviceEqual(b.device, '/job:ps/task:1/cpu:0')
- self.assertDeviceEqual(b.initial_value.device, b.device)
- self.assertDeviceEqual(c.device, '/cpu:12')
- self.assertDeviceEqual(c.initial_value.device, c.device)
- self.assertDeviceEqual(d.device, '/job:ps/task:0/cpu:0')
- self.assertDeviceEqual(d.initial_value.device, d.device)
- self.assertDeviceEqual(e.device, '/job:ps/task:1/cpu:0')
- self.assertDeviceEqual(e.initial_value.device, '/cpu:99')
-
- def testVariableGPUPlacement(self):
-
- with tf.Graph().as_default():
- device_fn = variables.VariableDeviceChooser(placement='gpu:0')
- with scopes.arg_scope([variables.variable], device=device_fn):
- a = variables.variable('a', [])
- b = variables.variable('b', [])
- c = variables.variable('c', [], device='cpu:12')
- d = variables.variable('d', [])
- with tf.device('cpu:99'):
- e_init = tf.constant(12)
- e = variables.variable('e', initializer=e_init)
- # The values below highlight how the VariableDeviceChooser puts initial
- # values on the same device as the variable job.
- self.assertDeviceEqual(a.device, '/gpu:0')
- self.assertDeviceEqual(a.initial_value.device, a.device)
- self.assertDeviceEqual(b.device, '/gpu:0')
- self.assertDeviceEqual(b.initial_value.device, b.device)
- self.assertDeviceEqual(c.device, '/cpu:12')
- self.assertDeviceEqual(c.initial_value.device, c.device)
- self.assertDeviceEqual(d.device, '/gpu:0')
- self.assertDeviceEqual(d.initial_value.device, d.device)
- self.assertDeviceEqual(e.device, '/gpu:0')
- self.assertDeviceEqual(e.initial_value.device, '/cpu:99')
-
- def testVariableCollection(self):
- with self.test_session():
- a = variables.variable('a', [], collections='A')
- b = variables.variable('b', [], collections='B')
- self.assertEquals(a, tf.get_collection('A')[0])
- self.assertEquals(b, tf.get_collection('B')[0])
-
- def testVariableCollections(self):
- with self.test_session():
- a = variables.variable('a', [], collections=['A', 'C'])
- b = variables.variable('b', [], collections=['B', 'C'])
- self.assertEquals(a, tf.get_collection('A')[0])
- self.assertEquals(b, tf.get_collection('B')[0])
-
- def testVariableCollectionsWithArgScope(self):
- with self.test_session():
- with scopes.arg_scope([variables.variable], collections='A'):
- a = variables.variable('a', [])
- b = variables.variable('b', [])
- self.assertListEqual([a, b], tf.get_collection('A'))
-
- def testVariableCollectionsWithArgScopeNested(self):
- with self.test_session():
- with scopes.arg_scope([variables.variable], collections='A'):
- a = variables.variable('a', [])
- with scopes.arg_scope([variables.variable], collections='B'):
- b = variables.variable('b', [])
- self.assertEquals(a, tf.get_collection('A')[0])
- self.assertEquals(b, tf.get_collection('B')[0])
-
- def testVariableCollectionsWithArgScopeNonNested(self):
- with self.test_session():
- with scopes.arg_scope([variables.variable], collections='A'):
- a = variables.variable('a', [])
- with scopes.arg_scope([variables.variable], collections='B'):
- b = variables.variable('b', [])
- variables.variable('c', [])
- self.assertListEqual([a], tf.get_collection('A'))
- self.assertListEqual([b], tf.get_collection('B'))
-
- def testVariableRestoreWithArgScopeNested(self):
- with self.test_session():
- with scopes.arg_scope([variables.variable], restore=True):
- a = variables.variable('a', [])
- with scopes.arg_scope([variables.variable],
- trainable=False,
- collections=['A', 'B']):
- b = variables.variable('b', [])
- c = variables.variable('c', [])
- self.assertListEqual([a, b, c], variables.get_variables_to_restore())
- self.assertListEqual([a, c], tf.trainable_variables())
- self.assertListEqual([b], tf.get_collection('A'))
- self.assertListEqual([b], tf.get_collection('B'))
-
-
-class GetVariablesByNameTest(tf.test.TestCase):
-
- def testGetVariableGivenNameScoped(self):
- with self.test_session():
- with tf.variable_scope('A'):
- a = variables.variable('a', [5])
- b = variables.variable('b', [5])
- self.assertEquals([a], variables.get_variables_by_name('a'))
- self.assertEquals([b], variables.get_variables_by_name('b'))
-
- def testGetVariablesByNameReturnsByValueWithScope(self):
- with self.test_session():
- with tf.variable_scope('A'):
- a = variables.variable('a', [5])
- matched_variables = variables.get_variables_by_name('a')
-
- # If variables.get_variables_by_name returns the list by reference, the
- # following append should persist, and be returned, in subsequent calls
- # to variables.get_variables_by_name('a').
- matched_variables.append(4)
-
- matched_variables = variables.get_variables_by_name('a')
- self.assertEquals([a], matched_variables)
-
- def testGetVariablesByNameReturnsByValueWithoutScope(self):
- with self.test_session():
- a = variables.variable('a', [5])
- matched_variables = variables.get_variables_by_name('a')
-
- # If variables.get_variables_by_name returns the list by reference, the
- # following append should persist, and be returned, in subsequent calls
- # to variables.get_variables_by_name('a').
- matched_variables.append(4)
-
- matched_variables = variables.get_variables_by_name('a')
- self.assertEquals([a], matched_variables)
-
-
-class GlobalStepTest(tf.test.TestCase):
-
- def testStable(self):
- with tf.Graph().as_default():
- gs = variables.global_step()
- gs2 = variables.global_step()
- self.assertTrue(gs is gs2)
-
- def testDevice(self):
- with tf.Graph().as_default():
- with scopes.arg_scope([variables.global_step], device='/gpu:0'):
- gs = variables.global_step()
- self.assertDeviceEqual(gs.device, '/gpu:0')
-
- def testDeviceFn(self):
- class DevFn(object):
-
- def __init__(self):
- self.counter = -1
-
- def __call__(self, op):
- self.counter += 1
- return '/cpu:%d' % self.counter
-
- with tf.Graph().as_default():
- with scopes.arg_scope([variables.global_step], device=DevFn()):
- gs = variables.global_step()
- gs2 = variables.global_step()
- self.assertDeviceEqual(gs.device, '/cpu:0')
- self.assertEquals(gs, gs2)
- self.assertDeviceEqual(gs2.device, '/cpu:0')
-
- def testReplicaDeviceSetter(self):
- device_fn = tf.train.replica_device_setter(2)
- with tf.Graph().as_default():
- with scopes.arg_scope([variables.global_step], device=device_fn):
- gs = variables.global_step()
- gs2 = variables.global_step()
- self.assertEquals(gs, gs2)
- self.assertDeviceEqual(gs.device, '/job:ps/task:0')
- self.assertDeviceEqual(gs.initial_value.device, '/job:ps/task:0')
- self.assertDeviceEqual(gs2.device, '/job:ps/task:0')
- self.assertDeviceEqual(gs2.initial_value.device, '/job:ps/task:0')
-
- def testVariableWithVariableDeviceChooser(self):
-
- with tf.Graph().as_default():
- device_fn = variables.VariableDeviceChooser()
- with scopes.arg_scope([variables.global_step], device=device_fn):
- gs = variables.global_step()
- gs2 = variables.global_step()
- self.assertEquals(gs, gs2)
- self.assertDeviceEqual(gs.device, 'cpu:0')
- self.assertDeviceEqual(gs.initial_value.device, gs.device)
- self.assertDeviceEqual(gs2.device, 'cpu:0')
- self.assertDeviceEqual(gs2.initial_value.device, gs2.device)
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/keypointnet/CONTRIBUTING.md b/research/keypointnet/CONTRIBUTING.md
deleted file mode 100644
index 939e5341e74dc2371c8b47f0e27b50581bed5f63..0000000000000000000000000000000000000000
--- a/research/keypointnet/CONTRIBUTING.md
+++ /dev/null
@@ -1,28 +0,0 @@
-# How to Contribute
-
-We'd love to accept your patches and contributions to this project. There are
-just a few small guidelines you need to follow.
-
-## Contributor License Agreement
-
-Contributions to this project must be accompanied by a Contributor License
-Agreement. You (or your employer) retain the copyright to your contribution;
-this simply gives us permission to use and redistribute your contributions as
-part of the project. Head over to to see
-your current agreements on file or to sign a new one.
-
-You generally only need to submit a CLA once, so if you've already submitted one
-(even if it was for a different project), you probably don't need to do it
-again.
-
-## Code reviews
-
-All submissions, including submissions by project members, require review. We
-use GitHub pull requests for this purpose. Consult
-[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
-information on using pull requests.
-
-## Community Guidelines
-
-This project follows [Google's Open Source Community
-Guidelines](https://opensource.google.com/conduct/).
diff --git a/research/keypointnet/LICENSE b/research/keypointnet/LICENSE
deleted file mode 100644
index d645695673349e3947e8e5ae42332d0ac3164cd7..0000000000000000000000000000000000000000
--- a/research/keypointnet/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
diff --git a/research/keypointnet/README.md b/research/keypointnet/README.md
deleted file mode 100644
index 8de88ca5a18816984302a9c20639364a7c8cde53..0000000000000000000000000000000000000000
--- a/research/keypointnet/README.md
+++ /dev/null
@@ -1,46 +0,0 @@
-
-
-
-
-# KeypointNet
-This is an implementation of the keypoint network proposed in "Discovery of
-Latent 3D Keypoints via End-to-end Geometric Reasoning
-[[pdf](https://arxiv.org/pdf/1807.03146.pdf)]". Given a single 2D image of a
-known class, this network can predict a set of 3D keypoints that are consistent
-across viewing angles of the same object and across object instances. These
-keypoints and their detectors are discovered and learned automatically without
-keypoint location supervision [[demo](https://keypointnet.github.io)].
-
-## Datasets:
- ShapeNet's rendering for
- [Cars](https://storage.googleapis.com/discovery-3dkeypoints-data/cars_with_keypoints.zip),
- [Planes](https://storage.googleapis.com/discovery-3dkeypoints-data/planes_with_keypoints.zip),
- [Chairs](https://storage.googleapis.com/discovery-3dkeypoints-data/chairs_with_keypoints.zip).
-
- Each set contains:
-1. tfrecords
-2. train.txt, a list of tfrecords used for training.
-2. dev.txt, a list of tfrecords used for validation.
-3. test.txt, a list of tfrecords used for testing.
-4. projection.txt, storing the global 4x4 camera projection matrix.
-5. job.txt, storing ShapeNet's object IDs in each tfrecord.
-
-## Training:
- Run `main.py --model_dir=MODEL_DIR --dset=DSET`
-
- where MODEL_DIR is a folder for storing model checkpoints: (see [tf.estimator](https://www.tensorflow.org/api_docs/python/tf/estimator/Estimator)), and DSET should point to the folder containing tfrecords (download above).
-
-## Inference:
- Run `main.py --model_dir=MODEL_DIR --input=INPUT --predict`
-
- where MODEL_DIR is the model checkpoint folder, and INPUT is a folder containing png or jpeg test images.
- We trained the network using the total batch size of 256 (8 x 32 replicas). You may have to tune the learning rate if your batch size is different.
-
-## Code credit:
- Supasorn Suwajanakorn
-
-## Contact:
- supasorn@gmail.com, [snavely,tompson,mnorouzi]@google.com
-
-
-(This is not an officially supported Google product)
diff --git a/research/keypointnet/main.py b/research/keypointnet/main.py
deleted file mode 100644
index 04b30159404e01529c898ee75fb1ed78f705f539..0000000000000000000000000000000000000000
--- a/research/keypointnet/main.py
+++ /dev/null
@@ -1,697 +0,0 @@
-# Copyright 2018 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# =============================================================================
-"""KeypointNet!!
-
-A reimplementation of 'Discovery of Latent 3D Keypoints via End-to-end
-Geometric Reasoning' keypoint network. Given a single 2D image of a known class,
-this network can predict a set of 3D keypoints that are consistent across
-viewing angles of the same object and across object instances. These keypoints
-and their detectors are discovered and learned automatically without
-keypoint location supervision.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import math
-import matplotlib.pyplot as plt
-import numpy as np
-import os
-from scipy import misc
-import sys
-import tensorflow as tf
-import tensorflow.contrib.slim as slim
-import utils
-
-FLAGS = tf.app.flags.FLAGS
-
-tf.app.flags.DEFINE_boolean("predict", False, "Running inference if true")
-tf.app.flags.DEFINE_string(
- "input",
- "",
- "Input folder containing images")
-tf.app.flags.DEFINE_string("model_dir", None, "Estimator model_dir")
-tf.app.flags.DEFINE_string(
- "dset",
- "",
- "Path to the directory containing the dataset.")
-tf.app.flags.DEFINE_integer("steps", 200000, "Training steps")
-tf.app.flags.DEFINE_integer("batch_size", 8, "Size of mini-batch.")
-tf.app.flags.DEFINE_string(
- "hparams", "",
- "A comma-separated list of `name=value` hyperparameter values. This flag "
- "is used to override hyperparameter settings either when manually "
- "selecting hyperparameters or when using Vizier.")
-tf.app.flags.DEFINE_integer(
- "sync_replicas", -1,
- "If > 0, use SyncReplicasOptimizer and use this many replicas per sync.")
-
-# Fixed input size 128 x 128.
-vw = vh = 128
-
-
-def create_input_fn(split, batch_size):
- """Returns input_fn for tf.estimator.Estimator.
-
- Reads tfrecords and construts input_fn for either training or eval. All
- tfrecords not in test.txt or dev.txt will be assigned to training set.
-
- Args:
- split: A string indicating the split. Can be either 'train' or 'validation'.
- batch_size: The batch size!
-
- Returns:
- input_fn for tf.estimator.Estimator.
-
- Raises:
- IOError: If test.txt or dev.txt are not found.
- """
-
- if (not os.path.exists(os.path.join(FLAGS.dset, "test.txt")) or
- not os.path.exists(os.path.join(FLAGS.dset, "dev.txt"))):
- raise IOError("test.txt or dev.txt not found")
-
- with open(os.path.join(FLAGS.dset, "test.txt"), "r") as f:
- testset = [x.strip() for x in f.readlines()]
-
- with open(os.path.join(FLAGS.dset, "dev.txt"), "r") as f:
- validset = [x.strip() for x in f.readlines()]
-
- files = os.listdir(FLAGS.dset)
- filenames = []
- for f in files:
- sp = os.path.splitext(f)
- if sp[1] != ".tfrecord" or sp[0] in testset:
- continue
-
- if ((split == "validation" and sp[0] in validset) or
- (split == "train" and sp[0] not in validset)):
- filenames.append(os.path.join(FLAGS.dset, f))
-
- def input_fn():
- """input_fn for tf.estimator.Estimator."""
-
- def parser(serialized_example):
- """Parses a single tf.Example into image and label tensors."""
- fs = tf.parse_single_example(
- serialized_example,
- features={
- "img0": tf.FixedLenFeature([], tf.string),
- "img1": tf.FixedLenFeature([], tf.string),
- "mv0": tf.FixedLenFeature([16], tf.float32),
- "mvi0": tf.FixedLenFeature([16], tf.float32),
- "mv1": tf.FixedLenFeature([16], tf.float32),
- "mvi1": tf.FixedLenFeature([16], tf.float32),
- })
-
- fs["img0"] = tf.div(tf.to_float(tf.image.decode_png(fs["img0"], 4)), 255)
- fs["img1"] = tf.div(tf.to_float(tf.image.decode_png(fs["img1"], 4)), 255)
-
- fs["img0"].set_shape([vh, vw, 4])
- fs["img1"].set_shape([vh, vw, 4])
-
- # fs["lr0"] = [fs["mv0"][0]]
- # fs["lr1"] = [fs["mv1"][0]]
-
- fs["lr0"] = tf.convert_to_tensor([fs["mv0"][0]])
- fs["lr1"] = tf.convert_to_tensor([fs["mv1"][0]])
-
- return fs
-
- np.random.shuffle(filenames)
- dataset = tf.data.TFRecordDataset(filenames)
- dataset = dataset.map(parser, num_parallel_calls=4)
- dataset = dataset.shuffle(400).repeat().batch(batch_size)
- dataset = dataset.prefetch(buffer_size=256)
-
- return dataset.make_one_shot_iterator().get_next(), None
-
- return input_fn
-
-
-class Transformer(object):
- """A utility for projecting 3D points to 2D coordinates and vice versa.
-
- 3D points are represented in 4D-homogeneous world coordinates. The pixel
- coordinates are represented in normalized device coordinates [-1, 1].
- See https://learnopengl.com/Getting-started/Coordinate-Systems.
- """
-
- def __get_matrix(self, lines):
- return np.array([[float(y) for y in x.strip().split(" ")] for x in lines])
-
- def __read_projection_matrix(self, filename):
- if not os.path.exists(filename):
- filename = "/cns/vz-d/home/supasorn/datasets/cars/projection.txt"
- with open(filename, "r") as f:
- lines = f.readlines()
- return self.__get_matrix(lines)
-
- def __init__(self, w, h, dataset_dir):
- self.w = w
- self.h = h
- p = self.__read_projection_matrix(dataset_dir + "projection.txt")
-
- # transposed of inversed projection matrix.
- self.pinv_t = tf.constant([[1.0 / p[0, 0], 0, 0,
- 0], [0, 1.0 / p[1, 1], 0, 0], [0, 0, 1, 0],
- [0, 0, 0, 1]])
- self.f = p[0, 0]
-
- def project(self, xyzw):
- """Projects homogeneous 3D coordinates to normalized device coordinates."""
-
- z = xyzw[:, :, 2:3] + 1e-8
- return tf.concat([-self.f * xyzw[:, :, :2] / z, z], axis=2)
-
- def unproject(self, xyz):
- """Unprojects normalized device coordinates with depth to 3D coordinates."""
-
- z = xyz[:, :, 2:]
- xy = -xyz * z
-
- def batch_matmul(a, b):
- return tf.reshape(
- tf.matmul(tf.reshape(a, [-1, a.shape[2].value]), b),
- [-1, a.shape[1].value, a.shape[2].value])
-
- return batch_matmul(
- tf.concat([xy[:, :, :2], z, tf.ones_like(z)], axis=2), self.pinv_t)
-
-
-def meshgrid(h):
- """Returns a meshgrid ranging from [-1, 1] in x, y axes."""
-
- r = np.arange(0.5, h, 1) / (h / 2) - 1
- ranx, rany = tf.meshgrid(r, -r)
- return tf.to_float(ranx), tf.to_float(rany)
-
-
-def estimate_rotation(xyz0, xyz1, pconf, noise):
- """Estimates the rotation between two sets of keypoints.
-
- The rotation is estimated by first subtracting mean from each set of keypoints
- and computing SVD of the covariance matrix.
-
- Args:
- xyz0: [batch, num_kp, 3] The first set of keypoints.
- xyz1: [batch, num_kp, 3] The second set of keypoints.
- pconf: [batch, num_kp] The weights used to compute the rotation estimate.
- noise: A number indicating the noise added to the keypoints.
-
- Returns:
- [batch, 3, 3] A batch of transposed 3 x 3 rotation matrices.
- """
-
- xyz0 += tf.random_normal(tf.shape(xyz0), mean=0, stddev=noise)
- xyz1 += tf.random_normal(tf.shape(xyz1), mean=0, stddev=noise)
-
- pconf2 = tf.expand_dims(pconf, 2)
- cen0 = tf.reduce_sum(xyz0 * pconf2, 1, keepdims=True)
- cen1 = tf.reduce_sum(xyz1 * pconf2, 1, keepdims=True)
-
- x = xyz0 - cen0
- y = xyz1 - cen1
-
- cov = tf.matmul(tf.matmul(x, tf.matrix_diag(pconf), transpose_a=True), y)
- _, u, v = tf.svd(cov, full_matrices=True)
-
- d = tf.matrix_determinant(tf.matmul(v, u, transpose_b=True))
- ud = tf.concat(
- [u[:, :, :-1], u[:, :, -1:] * tf.expand_dims(tf.expand_dims(d, 1), 1)],
- axis=2)
- return tf.matmul(ud, v, transpose_b=True)
-
-
-def relative_pose_loss(xyz0, xyz1, rot, pconf, noise):
- """Computes the relative pose loss (chordal, angular).
-
- Args:
- xyz0: [batch, num_kp, 3] The first set of keypoints.
- xyz1: [batch, num_kp, 3] The second set of keypoints.
- rot: [batch, 4, 4] The ground-truth rotation matrices.
- pconf: [batch, num_kp] The weights used to compute the rotation estimate.
- noise: A number indicating the noise added to the keypoints.
-
- Returns:
- A tuple (chordal loss, angular loss).
- """
-
- r_transposed = estimate_rotation(xyz0, xyz1, pconf, noise)
- rotation = rot[:, :3, :3]
- frob_sqr = tf.reduce_sum(tf.square(r_transposed - rotation), axis=[1, 2])
- frob = tf.sqrt(frob_sqr)
-
- return tf.reduce_mean(frob_sqr), \
- 2.0 * tf.reduce_mean(tf.asin(tf.minimum(1.0, frob / (2 * math.sqrt(2)))))
-
-
-def separation_loss(xyz, delta):
- """Computes the separation loss.
-
- Args:
- xyz: [batch, num_kp, 3] Input keypoints.
- delta: A separation threshold. Incur 0 cost if the distance >= delta.
-
- Returns:
- The seperation loss.
- """
-
- num_kp = tf.shape(xyz)[1]
- t1 = tf.tile(xyz, [1, num_kp, 1])
-
- t2 = tf.reshape(tf.tile(xyz, [1, 1, num_kp]), tf.shape(t1))
- diffsq = tf.square(t1 - t2)
-
- # -> [batch, num_kp ^ 2]
- lensqr = tf.reduce_sum(diffsq, axis=2)
-
- return (tf.reduce_sum(tf.maximum(-lensqr + delta, 0.0)) / tf.to_float(
- num_kp * FLAGS.batch_size * 2))
-
-
-def consistency_loss(uv0, uv1, pconf):
- """Computes multi-view consistency loss between two sets of keypoints.
-
- Args:
- uv0: [batch, num_kp, 2] The first set of keypoint 2D coordinates.
- uv1: [batch, num_kp, 2] The second set of keypoint 2D coordinates.
- pconf: [batch, num_kp] The weights used to compute the rotation estimate.
-
- Returns:
- The consistency loss.
- """
-
- # [batch, num_kp, 2]
- wd = tf.square(uv0 - uv1) * tf.expand_dims(pconf, 2)
- wd = tf.reduce_sum(wd, axis=[1, 2])
- return tf.reduce_mean(wd)
-
-
-def variance_loss(probmap, ranx, rany, uv):
- """Computes the variance loss as part of Sillhouette consistency.
-
- Args:
- probmap: [batch, num_kp, h, w] The distribution map of keypoint locations.
- ranx: X-axis meshgrid.
- rany: Y-axis meshgrid.
- uv: [batch, num_kp, 2] Keypoint locations (in NDC).
-
- Returns:
- The variance loss.
- """
-
- ran = tf.stack([ranx, rany], axis=2)
-
- sh = tf.shape(ran)
- # [batch, num_kp, vh, vw, 2]
- ran = tf.reshape(ran, [1, 1, sh[0], sh[1], 2])
-
- sh = tf.shape(uv)
- uv = tf.reshape(uv, [sh[0], sh[1], 1, 1, 2])
-
- diff = tf.reduce_sum(tf.square(uv - ran), axis=4)
- diff *= probmap
-
- return tf.reduce_mean(tf.reduce_sum(diff, axis=[2, 3]))
-
-
-def dilated_cnn(images, num_filters, is_training):
- """Constructs a base dilated convolutional network.
-
- Args:
- images: [batch, h, w, 3] Input RGB images.
- num_filters: The number of filters for all layers.
- is_training: True if this function is called during training.
-
- Returns:
- Output of this dilated CNN.
- """
-
- net = images
-
- with slim.arg_scope(
- [slim.conv2d, slim.fully_connected],
- normalizer_fn=slim.batch_norm,
- activation_fn=lambda x: tf.nn.leaky_relu(x, alpha=0.1),
- normalizer_params={"is_training": is_training}):
- for i, r in enumerate([1, 1, 2, 4, 8, 16, 1, 2, 4, 8, 16, 1]):
- net = slim.conv2d(net, num_filters, [3, 3], rate=r, scope="dconv%d" % i)
-
- return net
-
-
-def orientation_network(images, num_filters, is_training):
- """Constructs a network that infers the orientation of an object.
-
- Args:
- images: [batch, h, w, 3] Input RGB images.
- num_filters: The number of filters for all layers.
- is_training: True if this function is called during training.
-
- Returns:
- Output of the orientation network.
- """
-
- with tf.variable_scope("OrientationNetwork"):
- net = dilated_cnn(images, num_filters, is_training)
-
- modules = 2
- prob = slim.conv2d(net, 2, [3, 3], rate=1, activation_fn=None)
- prob = tf.transpose(prob, [0, 3, 1, 2])
-
- prob = tf.reshape(prob, [-1, modules, vh * vw])
- prob = tf.nn.softmax(prob)
- ranx, rany = meshgrid(vh)
-
- prob = tf.reshape(prob, [-1, 2, vh, vw])
-
- sx = tf.reduce_sum(prob * ranx, axis=[2, 3])
- sy = tf.reduce_sum(prob * rany, axis=[2, 3]) # -> batch x modules
-
- out_xy = tf.reshape(tf.stack([sx, sy], -1), [-1, modules, 2])
-
- return out_xy
-
-
-def keypoint_network(rgba,
- num_filters,
- num_kp,
- is_training,
- lr_gt=None,
- anneal=1):
- """Constructs our main keypoint network that predicts 3D keypoints.
-
- Args:
- rgba: [batch, h, w, 4] Input RGB images with alpha channel.
- num_filters: The number of filters for all layers.
- num_kp: The number of keypoints.
- is_training: True if this function is called during training.
- lr_gt: The groundtruth orientation flag used at the beginning of training.
- Then we linearly anneal in the prediction.
- anneal: A number between [0, 1] where 1 means using the ground-truth
- orientation and 0 means using our estimate.
-
- Returns:
- uv: [batch, num_kp, 2] 2D locations of keypoints.
- z: [batch, num_kp] The depth of keypoints.
- orient: [batch, 2, 2] Two 2D coordinates that correspond to [1, 0, 0] and
- [-1, 0, 0] in object space.
- sill: The Sillhouette loss.
- variance: The variance loss.
- prob_viz: A visualization of all predicted keypoints.
- prob_vizs: A list of visualizations of each keypoint.
-
- """
-
- images = rgba[:, :, :, :3]
-
- # [batch, 1]
- orient = orientation_network(images, num_filters * 0.5, is_training)
-
- # [batch, 1]
- lr_estimated = tf.maximum(0.0, tf.sign(orient[:, 0, :1] - orient[:, 1, :1]))
-
- if lr_gt is None:
- lr = lr_estimated
- else:
- lr_gt = tf.maximum(0.0, tf.sign(lr_gt[:, :1]))
- lr = tf.round(lr_gt * anneal + lr_estimated * (1 - anneal))
-
- lrtiled = tf.tile(
- tf.expand_dims(tf.expand_dims(lr, 1), 1),
- [1, images.shape[1], images.shape[2], 1])
-
- images = tf.concat([images, lrtiled], axis=3)
-
- mask = rgba[:, :, :, 3]
- mask = tf.cast(tf.greater(mask, tf.zeros_like(mask)), dtype=tf.float32)
-
- net = dilated_cnn(images, num_filters, is_training)
-
- # The probability distribution map.
- prob = slim.conv2d(
- net, num_kp, [3, 3], rate=1, scope="conv_xy", activation_fn=None)
-
- # We added the fixed camera distance as a bias.
- z = -30 + slim.conv2d(
- net, num_kp, [3, 3], rate=1, scope="conv_z", activation_fn=None)
-
- prob = tf.transpose(prob, [0, 3, 1, 2])
- z = tf.transpose(z, [0, 3, 1, 2])
-
- prob = tf.reshape(prob, [-1, num_kp, vh * vw])
- prob = tf.nn.softmax(prob, name="softmax")
-
- ranx, rany = meshgrid(vh)
- prob = tf.reshape(prob, [-1, num_kp, vh, vw])
-
- # These are for visualizing the distribution maps.
- prob_viz = tf.expand_dims(tf.reduce_sum(prob, 1), 3)
- prob_vizs = [tf.expand_dims(prob[:, i, :, :], 3) for i in range(num_kp)]
-
- sx = tf.reduce_sum(prob * ranx, axis=[2, 3])
- sy = tf.reduce_sum(prob * rany, axis=[2, 3]) # -> batch x num_kp
-
- # [batch, num_kp]
- sill = tf.reduce_sum(prob * tf.expand_dims(mask, 1), axis=[2, 3])
- sill = tf.reduce_mean(-tf.log(sill + 1e-12))
-
- z = tf.reduce_sum(prob * z, axis=[2, 3])
- uv = tf.reshape(tf.stack([sx, sy], -1), [-1, num_kp, 2])
-
- variance = variance_loss(prob, ranx, rany, uv)
-
- return uv, z, orient, sill, variance, prob_viz, prob_vizs
-
-
-def model_fn(features, labels, mode, hparams):
- """Returns model_fn for tf.estimator.Estimator."""
-
- del labels
-
- is_training = (mode == tf.estimator.ModeKeys.TRAIN)
- t = Transformer(vw, vh, FLAGS.dset)
-
- def func1(x):
- return tf.transpose(tf.reshape(features[x], [-1, 4, 4]), [0, 2, 1])
-
- mv = [func1("mv%d" % i) for i in range(2)]
- mvi = [func1("mvi%d" % i) for i in range(2)]
-
- uvz = [None] * 2
- uvz_proj = [None] * 2 # uvz coordinates projected on to the other view.
- viz = [None] * 2
- vizs = [None] * 2
-
- loss_sill = 0
- loss_variance = 0
- loss_con = 0
- loss_sep = 0
- loss_lr = 0
-
- for i in range(2):
- with tf.variable_scope("KeypointNetwork", reuse=i > 0):
- # anneal: 1 = using ground-truth, 0 = using our estimate orientation.
- anneal = tf.to_float(hparams.lr_anneal_end - tf.train.get_global_step())
- anneal = tf.clip_by_value(
- anneal / (hparams.lr_anneal_end - hparams.lr_anneal_start), 0.0, 1.0)
-
- uv, z, orient, sill, variance, viz[i], vizs[i] = keypoint_network(
- features["img%d" % i],
- hparams.num_filters,
- hparams.num_kp,
- is_training,
- lr_gt=features["lr%d" % i],
- anneal=anneal)
-
- # x-positive/negative axes (dominant direction).
- xp_axis = tf.tile(
- tf.constant([[[1.0, 0, 0, 1], [-1.0, 0, 0, 1]]]),
- [tf.shape(orient)[0], 1, 1])
-
- # [batch, 2, 4] = [batch, 2, 4] x [batch, 4, 4]
- xp = tf.matmul(xp_axis, mv[i])
-
- # [batch, 2, 3]
- xp = t.project(xp)
-
- loss_lr += tf.losses.mean_squared_error(orient[:, :, :2], xp[:, :, :2])
- loss_variance += variance
- loss_sill += sill
-
- uv = tf.reshape(uv, [-1, hparams.num_kp, 2])
- z = tf.reshape(z, [-1, hparams.num_kp, 1])
-
- # [batch, num_kp, 3]
- uvz[i] = tf.concat([uv, z], axis=2)
-
- world_coords = tf.matmul(t.unproject(uvz[i]), mvi[i])
-
- # [batch, num_kp, 3]
- uvz_proj[i] = t.project(tf.matmul(world_coords, mv[1 - i]))
-
- pconf = tf.ones(
- [tf.shape(uv)[0], tf.shape(uv)[1]], dtype=tf.float32) / hparams.num_kp
-
- for i in range(2):
- loss_con += consistency_loss(uvz_proj[i][:, :, :2], uvz[1 - i][:, :, :2],
- pconf)
- loss_sep += separation_loss(
- t.unproject(uvz[i])[:, :, :3], hparams.sep_delta)
-
- chordal, angular = relative_pose_loss(
- t.unproject(uvz[0])[:, :, :3],
- t.unproject(uvz[1])[:, :, :3], tf.matmul(mvi[0], mv[1]), pconf,
- hparams.noise)
-
- loss = (
- hparams.loss_pose * angular +
- hparams.loss_con * loss_con +
- hparams.loss_sep * loss_sep +
- hparams.loss_sill * loss_sill +
- hparams.loss_lr * loss_lr +
- hparams.loss_variance * loss_variance
- )
-
- def touint8(img):
- return tf.cast(img * 255.0, tf.uint8)
-
- with tf.variable_scope("output"):
- tf.summary.image("0_img0", touint8(features["img0"][:, :, :, :3]))
- tf.summary.image("1_combined", viz[0])
- for i in range(hparams.num_kp):
- tf.summary.image("2_f%02d" % i, vizs[0][i])
-
- with tf.variable_scope("stats"):
- tf.summary.scalar("anneal", anneal)
- tf.summary.scalar("closs", loss_con)
- tf.summary.scalar("seploss", loss_sep)
- tf.summary.scalar("angular", angular)
- tf.summary.scalar("chordal", chordal)
- tf.summary.scalar("lrloss", loss_lr)
- tf.summary.scalar("sill", loss_sill)
- tf.summary.scalar("vloss", loss_variance)
-
- return {
- "loss": loss,
- "predictions": {
- "img0": features["img0"],
- "img1": features["img1"],
- "uvz0": uvz[0],
- "uvz1": uvz[1]
- },
- "eval_metric_ops": {
- "closs": tf.metrics.mean(loss_con),
- "angular_loss": tf.metrics.mean(angular),
- "chordal_loss": tf.metrics.mean(chordal),
- }
- }
-
-
-def predict(input_folder, hparams):
- """Predicts keypoints on all images in input_folder."""
-
- cols = plt.cm.get_cmap("rainbow")(
- np.linspace(0, 1.0, hparams.num_kp))[:, :4]
-
- img = tf.placeholder(tf.float32, shape=(1, 128, 128, 4))
-
- with tf.variable_scope("KeypointNetwork"):
- ret = keypoint_network(
- img, hparams.num_filters, hparams.num_kp, False)
-
- uv = tf.reshape(ret[0], [-1, hparams.num_kp, 2])
- z = tf.reshape(ret[1], [-1, hparams.num_kp, 1])
- uvz = tf.concat([uv, z], axis=2)
-
- sess = tf.Session()
- saver = tf.train.Saver()
- ckpt = tf.train.get_checkpoint_state(FLAGS.model_dir)
-
- print("loading model: ", ckpt.model_checkpoint_path)
- saver.restore(sess, ckpt.model_checkpoint_path)
-
- files = [x for x in os.listdir(input_folder)
- if x[-3:] in ["jpg", "png"]]
-
- output_folder = os.path.join(input_folder, "output")
- if not os.path.exists(output_folder):
- os.mkdir(output_folder)
-
- for f in files:
- orig = misc.imread(os.path.join(input_folder, f)).astype(float) / 255
- if orig.shape[2] == 3:
- orig = np.concatenate((orig, np.ones_like(orig[:, :, :1])), axis=2)
-
- uv_ret = sess.run(uvz, feed_dict={img: np.expand_dims(orig, 0)})
-
- utils.draw_ndc_points(orig, uv_ret.reshape(hparams.num_kp, 3), cols)
- misc.imsave(os.path.join(output_folder, f), orig)
-
-
-def _default_hparams():
- """Returns default or overridden user-specified hyperparameters."""
-
- hparams = tf.contrib.training.HParams(
- num_filters=64, # Number of filters.
- num_kp=10, # Numer of keypoints.
-
- loss_pose=0.2, # Pose Loss.
- loss_con=1.0, # Multiview consistency Loss.
- loss_sep=1.0, # Seperation Loss.
- loss_sill=1.0, # Sillhouette Loss.
- loss_lr=1.0, # Orientation Loss.
- loss_variance=0.5, # Variance Loss (part of Sillhouette loss).
-
- sep_delta=0.05, # Seperation threshold.
- noise=0.1, # Noise added during estimating rotation.
-
- learning_rate=1.0e-3,
- lr_anneal_start=30000, # When to anneal in the orientation prediction.
- lr_anneal_end=60000, # When to use the prediction completely.
- )
- if FLAGS.hparams:
- hparams = hparams.parse(FLAGS.hparams)
- return hparams
-
-
-def main(argv):
- del argv
-
- hparams = _default_hparams()
-
- if FLAGS.predict:
- predict(FLAGS.input, hparams)
- else:
- utils.train_and_eval(
- model_dir=FLAGS.model_dir,
- model_fn=model_fn,
- input_fn=create_input_fn,
- hparams=hparams,
- steps=FLAGS.steps,
- batch_size=FLAGS.batch_size,
- save_checkpoints_secs=600,
- eval_throttle_secs=1800,
- eval_steps=5,
- sync_replicas=FLAGS.sync_replicas,
- )
-
-
-if __name__ == "__main__":
- sys.excepthook = utils.colored_hook(
- os.path.dirname(os.path.realpath(__file__)))
- tf.app.run()
diff --git a/research/keypointnet/tools/gen_tfrecords.py b/research/keypointnet/tools/gen_tfrecords.py
deleted file mode 100644
index 2f973b7fe5f16951dbfa01edd2a759b96b4f79db..0000000000000000000000000000000000000000
--- a/research/keypointnet/tools/gen_tfrecords.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# Copyright 2018 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# =============================================================================
-"""An example script to generate a tfrecord file from a folder containing the
-renderings.
-
-Example usage:
- python gen_tfrecords.py --input=FOLDER --output=output.tfrecord
-
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import os
-from scipy import misc
-import tensorflow as tf
-
-FLAGS = tf.app.flags.FLAGS
-tf.app.flags.DEFINE_string("input", "", "Input folder containing images")
-tf.app.flags.DEFINE_string("output", "", "Output tfrecord.")
-
-
-def get_matrix(lines):
- return np.array([[float(y) for y in x.strip().split(" ")] for x in lines])
-
-
-def read_model_view_matrices(filename):
- with open(filename, "r") as f:
- lines = f.readlines()
- return get_matrix(lines[:4]), get_matrix(lines[4:])
-
-
-def bytes_feature(values):
- return tf.train.Feature(bytes_list=tf.train.BytesList(value=[values]))
-
-
-def generate():
- with tf.python_io.TFRecordWriter(FLAGS.output) as tfrecord_writer:
- with tf.Graph().as_default():
- im0 = tf.placeholder(dtype=tf.uint8)
- im1 = tf.placeholder(dtype=tf.uint8)
- encoded0 = tf.image.encode_png(im0)
- encoded1 = tf.image.encode_png(im1)
-
- with tf.Session() as sess:
- count = 0
- indir = FLAGS.input + "/"
- while tf.gfile.Exists(indir + "%06d.txt" % count):
- print("saving %06d" % count)
- image0 = misc.imread(indir + "%06d.png" % (count * 2))
- image1 = misc.imread(indir + "%06d.png" % (count * 2 + 1))
-
- mat0, mat1 = read_model_view_matrices(indir + "%06d.txt" % count)
-
- mati0 = np.linalg.inv(mat0).flatten()
- mati1 = np.linalg.inv(mat1).flatten()
- mat0 = mat0.flatten()
- mat1 = mat1.flatten()
-
- st0, st1 = sess.run([encoded0, encoded1],
- feed_dict={im0: image0, im1: image1})
-
- example = tf.train.Example(features=tf.train.Features(feature={
- 'img0': bytes_feature(st0),
- 'img1': bytes_feature(st1),
- 'mv0': tf.train.Feature(
- float_list=tf.train.FloatList(value=mat0)),
- 'mvi0': tf.train.Feature(
- float_list=tf.train.FloatList(value=mati0)),
- 'mv1': tf.train.Feature(
- float_list=tf.train.FloatList(value=mat1)),
- 'mvi1': tf.train.Feature(
- float_list=tf.train.FloatList(value=mati1)),
- }))
-
- tfrecord_writer.write(example.SerializeToString())
- count += 1
-
-
-def main(argv):
- del argv
- generate()
-
-
-if __name__ == "__main__":
- tf.app.run()
diff --git a/research/keypointnet/tools/render.py b/research/keypointnet/tools/render.py
deleted file mode 100644
index 3a8872675d83cc414d6348dbc7a56e924541b8d7..0000000000000000000000000000000000000000
--- a/research/keypointnet/tools/render.py
+++ /dev/null
@@ -1,310 +0,0 @@
-# Copyright 2018 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# =============================================================================
-"""Script to render object views from ShapeNet obj models.
-
-Example usage:
- blender -b --python render.py -- -m model.obj -o output/ -s 128 -n 120 -fov 5
-
-"""
-from __future__ import print_function
-
-import argparse
-import itertools
-import json
-from math import pi
-import os
-import random
-import sys
-from mathutils import Vector
-import math
-import mathutils
-import time
-import copy
-
-import bpy
-
-sys.path.append(os.path.dirname(__file__))
-
-BG_LUMINANCE = 0
-
-
-def look_at(obj_camera, point):
- loc_camera = obj_camera.location
- direction = point - loc_camera
- # point the cameras '-Z' and use its 'Y' as up
- rot_quat = direction.to_track_quat('-Z', 'Y')
-
- obj_camera.rotation_euler = rot_quat.to_euler()
-
-
-def roll_camera(obj_camera):
- roll_rotate = mathutils.Euler(
- (0, 0, random.random() * math.pi - math.pi * 0.5), 'XYZ')
- obj_camera.rotation_euler = (obj_camera.rotation_euler.to_matrix() *
- roll_rotate.to_matrix()).to_euler()
-
-
-def norm(x):
- return math.sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2])
-
-
-def normalize(x):
- n = norm(x)
- x[0] /= n
- x[1] /= n
- x[2] /= n
-
-
-def random_top_sphere():
- xyz = [random.normalvariate(0, 1) for x in range(3)]
- normalize(xyz)
-
- if xyz[2] < 0:
- xyz[2] *= -1
- return xyz
-
-
-def perturb_sphere(loc, size):
- while True:
- xyz = [random.normalvariate(0, 1) for x in range(3)]
- normalize(xyz)
-
- nloc = [loc[i] + xyz[i] * random.random() * size for i in range(3)]
- normalize(nloc)
-
- if nloc[2] >= 0:
- return nloc
-
-
-def perturb(loc, size):
- while True:
- nloc = [loc[i] + random.random() * size * 2 - size for i in range(3)]
- if nloc[2] >= 0:
- return nloc
-
- bpy.ops.object.mode_set()
-
-
-def delete_all_objects():
- bpy.ops.object.select_by_type(type="MESH")
- bpy.ops.object.delete(use_global=False)
-
-
-def set_scene(render_size, fov, alpha=False):
- """Set up default scene properties."""
- delete_all_objects()
-
- cam = bpy.data.cameras["Camera"]
- cam.angle = fov * pi / 180
-
- light = bpy.data.objects["Lamp"]
- light.location = (0, 0, 1)
- look_at(light, Vector((0.0, 0, 0)))
- bpy.data.lamps['Lamp'].type = "HEMI"
- bpy.data.lamps['Lamp'].energy = 1
- bpy.data.lamps['Lamp'].use_specular = False
- bpy.data.lamps['Lamp'].use_diffuse = True
-
- bpy.context.scene.world.horizon_color = (
- BG_LUMINANCE, BG_LUMINANCE, BG_LUMINANCE)
-
- bpy.context.scene.render.resolution_x = render_size
- bpy.context.scene.render.resolution_y = render_size
- bpy.context.scene.render.resolution_percentage = 100
-
- bpy.context.scene.render.use_antialiasing = True
- bpy.context.scene.render.antialiasing_samples = '5'
-
-
-def get_modelview_matrix():
- cam = bpy.data.objects["Camera"]
- bpy.context.scene.update()
-
- # when apply to object with CV coordinate i.e. to_blender * obj
- # this gives object in blender coordinate
- to_blender = mathutils.Matrix(
- ((1., 0., 0., 0.),
- (0., 0., -1., 0.),
- (0., 1., 0., 0.),
- (0., 0., 0., 1.)))
- return cam.matrix_world.inverted() * to_blender
-
-
-def print_matrix(f, mat):
- for i in range(4):
- for j in range(4):
- f.write("%lf " % mat[i][j])
- f.write("\n")
-
-
-def mul(loc, v):
- return [loc[i] * v for i in range(3)]
-
-
-def merge_all():
- bpy.ops.object.select_by_type(type="MESH")
- bpy.context.scene.objects.active = bpy.context.selected_objects[0]
- bpy.ops.object.join()
- obj = bpy.context.scene.objects.active
- bpy.ops.object.origin_set(type="ORIGIN_CENTER_OF_MASS")
- return obj
-
-
-def insert_frame(obj, frame_number):
- obj.keyframe_insert(data_path="location", frame=frame_number)
- obj.keyframe_insert(data_path="rotation_euler", frame=frame_number)
- obj.keyframe_insert(data_path="scale", frame=frame_number)
-
-
-def render(output_prefix):
- bpy.context.scene.render.filepath = output_prefix
- bpy.context.scene.render.image_settings.file_format = "PNG"
- bpy.context.scene.render.alpha_mode = "TRANSPARENT"
- bpy.context.scene.render.image_settings.color_mode = "RGBA"
- bpy.ops.render.render(write_still=True, animation=True)
-
-
-def render_obj(
- obj_fn, save_dir, n, perturb_size, rotate=False, roll=False, scale=1.0):
-
- # Load object.
- bpy.ops.import_scene.obj(filepath=obj_fn)
- cur_obj = merge_all()
-
- scale = 2.0 / max(cur_obj.dimensions) * scale
- cur_obj.scale = (scale, scale, scale)
- # Using the center of mass as the origin doesn't really work, because Blender
- # assumes the object is a solid shell. This seems to generate better-looking
- # rotations.
-
- bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='BOUNDS')
-
- # bpy.ops.mesh.primitive_cube_add(location=(0, 0, 1))
- # cube = bpy.data.objects["Cube"]
- # cube.scale = (0.2, 0.2, 0.2)
-
- for polygon in cur_obj.data.polygons:
- polygon.use_smooth = True
-
- bpy.ops.object.select_all(action="DESELECT")
-
- camera = bpy.data.objects["Camera"]
-
- # os.system("mkdir " + save_dir)
- for i in range(n):
- fo = open(save_dir + "/%06d.txt" % i, "w")
- d = 30
- shift = 0.2
- if rotate:
- t = 1.0 * i / (n-1) * 2 * math.pi
- loc = [math.sin(t), math.cos(t), 1]
-
- normalize(loc)
- camera.location = mul(loc, d)
- look_at(camera, Vector((0.0, 0, 0)))
-
- print_matrix(fo, get_modelview_matrix())
- print_matrix(fo, get_modelview_matrix())
-
- insert_frame(camera, 2 * i)
- insert_frame(camera, 2 * i + 1)
-
- else:
- loc = random_top_sphere()
-
- camera.location = mul(loc, d)
- look_at(camera, Vector((0.0, 0, 0)))
-
- if roll:
- roll_camera(camera)
- camera.location = perturb(mul(loc, d), shift)
-
- print_matrix(fo, get_modelview_matrix())
- insert_frame(camera, 2 * i)
-
- if perturb_size > 0:
- loc = perturb_sphere(loc, perturb_size)
- else:
- loc = random_top_sphere()
-
- camera.location = mul(loc, d)
- look_at(camera, Vector((0.0, 0, 0)))
- if roll:
- roll_camera(camera)
- camera.location = perturb(mul(loc, d), shift)
-
- print_matrix(fo, get_modelview_matrix())
- insert_frame(camera, 2 * i + 1)
-
- fo.close()
-
- # Create a bunch of views of the object
- bpy.context.scene.frame_start = 0
- bpy.context.scene.frame_end = 2 * n - 1
-
- stem = os.path.join(save_dir, '######')
- render(stem)
-
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument('-m', '--model', dest='model',
- required=True,
- help='Path to model obj file.')
- parser.add_argument('-o', '--output_dir', dest='output_dir',
- required=True,
- help='Where to output files.')
- parser.add_argument('-s', '--output_size', dest='output_size',
- required=True,
- help='Width and height of output in pixels, e.g. 32x32.')
- parser.add_argument('-n', '--num_frames', dest='n', type=int,
- required=True,
- help='Number of frames to generate per clip.')
-
- parser.add_argument('-scale', '--scale', dest='scale', type=float,
- help='object scaling', default=1)
-
- parser.add_argument('-perturb', '--perturb', dest='perturb', type=float,
- help='sphere perturbation', default=0)
-
- parser.add_argument('-rotate', '--rotate', dest='rotate', action='store_true',
- help='render rotating test set')
-
- parser.add_argument('-roll', '--roll', dest='roll', action='store_true',
- help='add roll')
-
- parser.add_argument(
- '-fov', '--fov', dest='fov', type=float, required=True,
- help='field of view')
-
- if '--' not in sys.argv:
- parser.print_help()
- exit(1)
-
- argv = sys.argv[sys.argv.index('--') + 1:]
- args, _ = parser.parse_known_args(argv)
-
- random.seed(args.model + str(time.time()) + str(os.getpid()))
- # random.seed(0)
-
- set_scene(int(args.output_size), args.fov)
- render_obj(
- args.model, args.output_dir, args.n, args.perturb, args.rotate,
- args.roll, args.scale)
- exit()
-
-
-if __name__ == '__main__':
- main()
diff --git a/research/keypointnet/utils.py b/research/keypointnet/utils.py
deleted file mode 100644
index 148b7a3ed843638cff597be0c462b7e335df9857..0000000000000000000000000000000000000000
--- a/research/keypointnet/utils.py
+++ /dev/null
@@ -1,307 +0,0 @@
-# Copyright 2018 Google LLC
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# https://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# =============================================================================
-"""Utility functions for KeypointNet.
-
-These are helper / tensorflow related functions. The actual implementation and
-algorithm is in main.py.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import math
-import numpy as np
-import os
-import re
-import tensorflow as tf
-import tensorflow.contrib.slim as slim
-import time
-import traceback
-
-
-class TrainingHook(tf.train.SessionRunHook):
- """A utility for displaying training information such as the loss, percent
- completed, estimated finish date and time."""
-
- def __init__(self, steps):
- self.steps = steps
-
- self.last_time = time.time()
- self.last_est = self.last_time
-
- self.eta_interval = int(math.ceil(0.1 * self.steps))
- self.current_interval = 0
-
- def before_run(self, run_context):
- graph = tf.get_default_graph()
- return tf.train.SessionRunArgs(
- {"loss": graph.get_collection("total_loss")[0]})
-
- def after_run(self, run_context, run_values):
- step = run_context.session.run(tf.train.get_global_step())
- now = time.time()
-
- if self.current_interval < self.eta_interval:
- self.duration = now - self.last_est
- self.current_interval += 1
- if step % self.eta_interval == 0:
- self.duration = now - self.last_est
- self.last_est = now
-
- eta_time = float(self.steps - step) / self.current_interval * \
- self.duration
- m, s = divmod(eta_time, 60)
- h, m = divmod(m, 60)
- eta = "%d:%02d:%02d" % (h, m, s)
-
- print("%.2f%% (%d/%d): %.3e t %.3f @ %s (%s)" % (
- step * 100.0 / self.steps,
- step,
- self.steps,
- run_values.results["loss"],
- now - self.last_time,
- time.strftime("%a %d %H:%M:%S", time.localtime(time.time() + eta_time)),
- eta))
-
- self.last_time = now
-
-
-def standard_model_fn(
- func, steps, run_config=None, sync_replicas=0, optimizer_fn=None):
- """Creates model_fn for tf.Estimator.
-
- Args:
- func: A model_fn with prototype model_fn(features, labels, mode, hparams).
- steps: Training steps.
- run_config: tf.estimatorRunConfig (usually passed in from TF_CONFIG).
- sync_replicas: The number of replicas used to compute gradient for
- synchronous training.
- optimizer_fn: The type of the optimizer. Default to Adam.
-
- Returns:
- model_fn for tf.estimator.Estimator.
- """
-
- def fn(features, labels, mode, params):
- """Returns model_fn for tf.estimator.Estimator."""
-
- is_training = (mode == tf.estimator.ModeKeys.TRAIN)
- ret = func(features, labels, mode, params)
-
- tf.add_to_collection("total_loss", ret["loss"])
- train_op = None
-
- training_hooks = []
- if is_training:
- training_hooks.append(TrainingHook(steps))
-
- if optimizer_fn is None:
- optimizer = tf.train.AdamOptimizer(params.learning_rate)
- else:
- optimizer = optimizer_fn
-
- if run_config is not None and run_config.num_worker_replicas > 1:
- sr = sync_replicas
- if sr <= 0:
- sr = run_config.num_worker_replicas
-
- optimizer = tf.train.SyncReplicasOptimizer(
- optimizer,
- replicas_to_aggregate=sr,
- total_num_replicas=run_config.num_worker_replicas)
-
- training_hooks.append(
- optimizer.make_session_run_hook(
- run_config.is_chief, num_tokens=run_config.num_worker_replicas))
-
- optimizer = tf.contrib.estimator.clip_gradients_by_norm(optimizer, 5)
- train_op = slim.learning.create_train_op(ret["loss"], optimizer)
-
- if "eval_metric_ops" not in ret:
- ret["eval_metric_ops"] = {}
-
- return tf.estimator.EstimatorSpec(
- mode=mode,
- predictions=ret["predictions"],
- loss=ret["loss"],
- train_op=train_op,
- eval_metric_ops=ret["eval_metric_ops"],
- training_hooks=training_hooks)
- return fn
-
-
-def train_and_eval(
- model_dir,
- steps,
- batch_size,
- model_fn,
- input_fn,
- hparams,
- keep_checkpoint_every_n_hours=0.5,
- save_checkpoints_secs=180,
- save_summary_steps=50,
- eval_steps=20,
- eval_start_delay_secs=10,
- eval_throttle_secs=300,
- sync_replicas=0):
- """Trains and evaluates our model. Supports local and distributed training.
-
- Args:
- model_dir: The output directory for trained parameters, checkpoints, etc.
- steps: Training steps.
- batch_size: Batch size.
- model_fn: A func with prototype model_fn(features, labels, mode, hparams).
- input_fn: A input function for the tf.estimator.Estimator.
- hparams: tf.HParams containing a set of hyperparameters.
- keep_checkpoint_every_n_hours: Number of hours between each checkpoint
- to be saved.
- save_checkpoints_secs: Save checkpoints every this many seconds.
- save_summary_steps: Save summaries every this many steps.
- eval_steps: Number of steps to evaluate model.
- eval_start_delay_secs: Start evaluating after waiting for this many seconds.
- eval_throttle_secs: Do not re-evaluate unless the last evaluation was
- started at least this many seconds ago
- sync_replicas: Number of synchronous replicas for distributed training.
-
- Returns:
- None
- """
-
- run_config = tf.estimator.RunConfig(
- keep_checkpoint_every_n_hours=keep_checkpoint_every_n_hours,
- save_checkpoints_secs=save_checkpoints_secs,
- save_summary_steps=save_summary_steps)
-
- estimator = tf.estimator.Estimator(
- model_dir=model_dir,
- model_fn=standard_model_fn(
- model_fn,
- steps,
- run_config,
- sync_replicas=sync_replicas),
- params=hparams, config=run_config)
-
- train_spec = tf.estimator.TrainSpec(
- input_fn=input_fn(split="train", batch_size=batch_size),
- max_steps=steps)
-
- eval_spec = tf.estimator.EvalSpec(
- input_fn=input_fn(split="validation", batch_size=batch_size),
- steps=eval_steps,
- start_delay_secs=eval_start_delay_secs,
- throttle_secs=eval_throttle_secs)
-
- tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec)
-
-
-def draw_circle(rgb, u, v, col, r):
- """Draws a simple anti-aliasing circle in-place.
-
- Args:
- rgb: Input image to be modified.
- u: Horizontal coordinate.
- v: Vertical coordinate.
- col: Color.
- r: Radius.
- """
-
- ir = int(math.ceil(r))
- for i in range(-ir-1, ir+2):
- for j in range(-ir-1, ir+2):
- nu = int(round(u + i))
- nv = int(round(v + j))
- if nu < 0 or nu >= rgb.shape[1] or nv < 0 or nv >= rgb.shape[0]:
- continue
-
- du = abs(nu - u)
- dv = abs(nv - v)
-
- # need sqrt to keep scale
- t = math.sqrt(du * du + dv * dv) - math.sqrt(r * r)
- if t < 0:
- rgb[nv, nu, :] = col
- else:
- t = 1 - t
- if t > 0:
- # t = t ** 0.3
- rgb[nv, nu, :] = col * t + rgb[nv, nu, :] * (1-t)
-
-
-def draw_ndc_points(rgb, xy, cols):
- """Draws keypoints onto an input image.
-
- Args:
- rgb: Input image to be modified.
- xy: [n x 2] matrix of 2D locations.
- cols: A list of colors for the keypoints.
- """
-
- vh, vw = rgb.shape[0], rgb.shape[1]
-
- for j in range(len(cols)):
- x, y = xy[j, :2]
- x = (min(max(x, -1), 1) * vw / 2 + vw / 2) - 0.5
- y = vh - 0.5 - (min(max(y, -1), 1) * vh / 2 + vh / 2)
-
- x = int(round(x))
- y = int(round(y))
- if x < 0 or y < 0 or x >= vw or y >= vh:
- continue
-
- rad = 1.5
- rad *= rgb.shape[0] / 128.0
- draw_circle(rgb, x, y, np.array([0.0, 0.0, 0.0, 1.0]), rad * 1.5)
- draw_circle(rgb, x, y, cols[j], rad)
-
-
-def colored_hook(home_dir):
- """Colorizes python's error message.
-
- Args:
- home_dir: directory where code resides (to highlight your own files).
- Returns:
- The traceback hook.
- """
-
- def hook(type_, value, tb):
- def colorize(text, color, own=0):
- """Returns colorized text."""
- endcolor = "\x1b[0m"
- codes = {
- "green": "\x1b[0;32m",
- "green_own": "\x1b[1;32;40m",
- "red": "\x1b[0;31m",
- "red_own": "\x1b[1;31m",
- "yellow": "\x1b[0;33m",
- "yellow_own": "\x1b[1;33m",
- "black": "\x1b[0;90m",
- "black_own": "\x1b[1;90m",
- "cyan": "\033[1;36m",
- }
- return codes[color + ("_own" if own else "")] + text + endcolor
-
- for filename, line_num, func, text in traceback.extract_tb(tb):
- basename = os.path.basename(filename)
- own = (home_dir in filename) or ("/" not in filename)
-
- print(colorize("\"" + basename + '"', "green", own) + " in " + func)
- print("%s: %s" % (
- colorize("%5d" % line_num, "red", own),
- colorize(text, "yellow", own)))
- print(" %s" % colorize(filename, "black", own))
-
- print(colorize("%s: %s" % (type_.__name__, value), "cyan"))
- return hook
diff --git a/research/learned_optimizer/.gitignore b/research/learned_optimizer/.gitignore
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/learned_optimizer/BUILD b/research/learned_optimizer/BUILD
deleted file mode 100644
index 629c9a06b51d10eb7cab69ed0d9dd0bfa52fd2f0..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/BUILD
+++ /dev/null
@@ -1,33 +0,0 @@
-# Learning to Optimize Learning (LOL)
-
-package(default_visibility = ["//visibility:public"])
-
-# Libraries
-# =========
-
-py_library(
- name = "metaopt",
- srcs = ["metaopt.py"],
- deps = [
- "//learned_optimizer/problems:datasets",
- "//learned_optimizer/problems:problem_generator",
- ],
-)
-
-# Binaries
-# ========
-py_binary(
- name = "metarun",
- srcs = ["metarun.py"],
- deps = [
- ":metaopt",
- "//learned_optimizer/optimizer:coordinatewise_rnn",
- "//learned_optimizer/optimizer:global_learning_rate",
- "//learned_optimizer/optimizer:hierarchical_rnn",
- "//learned_optimizer/optimizer:learning_rate_schedule",
- "//learned_optimizer/optimizer:trainable_adam",
- "//learned_optimizer/problems:problem_sets",
- "//learned_optimizer/problems:problem_spec",
- ],
-)
-
diff --git a/research/learned_optimizer/README.md b/research/learned_optimizer/README.md
deleted file mode 100644
index 6a32514f053f97bc64dc87c4ec972c8223a83fe2..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/README.md
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
-# Learned Optimizer
-
-Code for [Learned Optimizers that Scale and Generalize](https://arxiv.org/abs/1703.04813).
-
-## Requirements
-
-* Bazel ([install](https://bazel.build/versions/master/docs/install.html))
-* TensorFlow >= v1.3
-* Python 2.7.x
-
-## Training a Learned Optimizer
-
-## Code Overview
-In the top-level directory, ```metaopt.py``` contains the code to train and test a learned optimizer. ```metarun.py``` packages the actual training procedure into a
-single file, defining and exposing many flags to tune the procedure, from selecting the optimizer type and problem set to more fine-grained hyperparameter settings.
-There is no testing binary; testing can be done ad-hoc via ```metaopt.test_optimizer``` by passing an optimizer object and a directory with a checkpoint.
-
-The ```optimizer``` directory contains a base ```trainable_optimizer.py``` class and a number of extensions, including the ```hierarchical_rnn``` optimizer used in
-the paper, a ```coordinatewise_rnn``` optimizer that more closely matches previous work, and a number of simpler optimizers to demonstrate the basic mechanics of
-a learnable optimizer.
-
-The ```problems``` directory contains the code to build the problems that were used in the meta-training set.
-
-### Binaries
-```metarun.py```: meta-training of a learned optimizer
-
-### Command-Line Flags
-The flags most relevant to meta-training are defined in ```metarun.py```. The default values will meta-train a HierarchicalRNN optimizer with the hyperparameter
-settings used in the paper.
-
-### Using a Learned Optimizer as a Black Box
-The ```trainable_optimizer``` inherits from ```tf.train.Optimizer```, so a properly instantiated version can be used to train any model in any APIs that accept
-this class. There are just 2 caveats:
-
-1. If using the Hierarchical RNN optimizer, the apply_gradients return type must be changed (see comments inline for what exactly must be removed)
-
-2. Care must be taken to restore the variables from the optimizer without overriding them. Optimizer variables should be loaded manually using a pretrained checkpoint
-and a ```tf.train.Saver``` with only the optimizer variables. Then, when constructing the session, ensure that any automatic variable initialization does not
-re-initialize the loaded optimizer variables.
-
-## Contact for Issues
-
-* Olga Wichrowska (@olganw), Niru Maheswaranathan (@nirum)
diff --git a/research/learned_optimizer/metaopt.py b/research/learned_optimizer/metaopt.py
deleted file mode 100644
index 62c06272d3096ed63296744792c8742826380536..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/metaopt.py
+++ /dev/null
@@ -1,639 +0,0 @@
-# Copyright 2017 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Helper utilities for training and testing optimizers."""
-
-from collections import defaultdict
-import random
-import sys
-import time
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-from learned_optimizer.optimizer import trainable_optimizer
-from learned_optimizer.optimizer import utils
-from learned_optimizer.problems import datasets
-from learned_optimizer.problems import problem_generator
-
-tf.app.flags.DEFINE_integer("ps_tasks", 0,
- """Number of tasks in the ps job.
- If 0 no ps job is used.""")
-tf.app.flags.DEFINE_float("nan_l2_reg", 1e-2,
- """Strength of l2-reg when NaNs are encountered.""")
-tf.app.flags.DEFINE_float("l2_reg", 0.,
- """Lambda value for parameter regularization.""")
-# Default is 0.9
-tf.app.flags.DEFINE_float("rms_decay", 0.9,
- """Decay value for the RMSProp metaoptimizer.""")
-# Default is 1e-10
-tf.app.flags.DEFINE_float("rms_epsilon", 1e-20,
- """Epsilon value for the RMSProp metaoptimizer.""")
-tf.app.flags.DEFINE_boolean("set_profiling", False,
- """Enable memory usage and computation time """
- """tracing for tensorflow nodes (available in """
- """TensorBoard).""")
-tf.app.flags.DEFINE_boolean("reset_rnn_params", True,
- """Reset the parameters of the optimizer
- from one meta-iteration to the next.""")
-
-FLAGS = tf.app.flags.FLAGS
-OPTIMIZER_SCOPE = "LOL"
-OPT_SUM_COLLECTION = "LOL_summaries"
-
-
-def sigmoid_weights(n, slope=0.1, offset=5):
- """Generates a sigmoid, scaled to sum to 1.
-
- This function is used to generate weights that serve to mask out
- the early objective values of an optimization problem such that
- initial variation in the objective is phased out (hence the sigmoid
- starts at zero and ramps up to the maximum value, and the total
- weight is normalized to sum to one)
-
- Args:
- n: the number of samples
- slope: slope of the sigmoid (Default: 0.1)
- offset: threshold of the sigmoid (Default: 5)
-
- Returns:
- No
- """
- x = np.arange(n)
- y = 1. / (1. + np.exp(-slope * (x-offset)))
- y_normalized = y / np.sum(y)
- return y_normalized
-
-
-def sample_numiter(scale, min_steps=50):
- """Samples a number of iterations from an exponential distribution.
-
- Args:
- scale: parameter for the exponential distribution
- min_steps: minimum number of steps to run (additive)
-
- Returns:
- num_steps: An integer equal to a rounded sample from the exponential
- distribution + the value of min_steps.
- """
- return int(np.round(np.random.exponential(scale=scale)) + min_steps)
-
-
-def train_optimizer(logdir,
- optimizer_spec,
- problems_and_data,
- num_problems,
- num_meta_iterations,
- num_unroll_func,
- num_partial_unroll_itrs_func,
- learning_rate=1e-4,
- gradient_clip=5.,
- is_chief=False,
- select_random_problems=True,
- callbacks=None,
- obj_train_max_multiplier=-1,
- out=sys.stdout):
- """Trains the meta-parameters of this optimizer.
-
- Args:
- logdir: a directory filepath for storing model checkpoints (must exist)
- optimizer_spec: specification for an Optimizer (see utils.Spec)
- problems_and_data: a list of tuples containing three elements: a problem
- specification (see utils.Spec), a dataset (see datasets.Dataset), and
- a batch_size (int) for generating a problem and corresponding dataset. If
- the problem doesn't have data, set dataset to None.
- num_problems: the number of problems to sample during meta-training
- num_meta_iterations: the number of iterations (steps) to run the
- meta-optimizer for on each subproblem.
- num_unroll_func: called once per meta iteration and returns the number of
- unrolls to do for that meta iteration.
- num_partial_unroll_itrs_func: called once per unroll and returns the number
- of iterations to do for that unroll.
- learning_rate: learning rate of the RMSProp meta-optimizer (Default: 1e-4)
- gradient_clip: value to clip gradients at (Default: 5.0)
- is_chief: whether this is the chief task (Default: False)
- select_random_problems: whether to select training problems randomly
- (Default: True)
- callbacks: a list of callback functions that is run after every random
- problem draw
- obj_train_max_multiplier: the maximum increase in the objective value over
- a single training run. Ignored if < 0.
- out: where to write output to, e.g. a file handle (Default: sys.stdout)
-
- Raises:
- ValueError: If one of the subproblems has a negative objective value.
- """
-
- if select_random_problems:
- # iterate over random draws of problem / dataset pairs
- sampler = (random.choice(problems_and_data) for _ in range(num_problems))
- else:
- # iterate over a random shuffle of problems, looping if necessary
- num_repeats = (num_problems / len(problems_and_data)) + 1
- random.shuffle(problems_and_data)
- sampler = (problems_and_data * num_repeats)[:num_problems]
-
- for problem_itr, (problem_spec, dataset, batch_size) in enumerate(sampler):
-
- # timer used to time how long it takes to initialize a problem
- problem_start_time = time.time()
-
- # if dataset is None, use the EMPTY_DATASET
- if dataset is None:
- dataset = datasets.EMPTY_DATASET
- batch_size = dataset.size
-
- # build a new graph for this problem
- graph = tf.Graph()
- real_device_setter = tf.train.replica_device_setter(FLAGS.ps_tasks)
-
- def custom_device_setter(op):
- # Places the local variables onto the workers.
- if trainable_optimizer.is_local_state_variable(op):
- return "/job:worker"
- else:
- return real_device_setter(op)
-
- if real_device_setter:
- device_setter = custom_device_setter
- else:
- device_setter = None
-
- with graph.as_default(), graph.device(device_setter):
-
- # initialize a problem
- problem = problem_spec.build()
-
- # build the optimizer
- opt = optimizer_spec.build()
-
- # get the meta-objective for training the optimizer
- train_output = opt.train(problem, dataset)
-
- state_keys = opt.state_keys
- for key, val in zip(state_keys, train_output.output_state[0]):
- finite_val = utils.make_finite(val, replacement=tf.zeros_like(val))
- tf.summary.histogram("State/{}".format(key), finite_val,
- collections=[OPT_SUM_COLLECTION])
-
- tf.summary.scalar("MetaObjective", train_output.metaobj,
- collections=[OPT_SUM_COLLECTION])
-
- # Per-problem meta-objective
- tf.summary.scalar(problem_spec.callable.__name__ + "_MetaObjective",
- train_output.metaobj,
- collections=[OPT_SUM_COLLECTION])
-
- # create the meta-train_op
- global_step = tf.Variable(0, name="global_step", trainable=False)
- meta_parameters = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES,
- scope=OPTIMIZER_SCOPE)
- # parameter regularization
- reg_l2 = FLAGS.l2_reg * sum([tf.reduce_sum(param ** 2)
- for param in meta_parameters])
-
- # compute the meta-gradients
- meta_opt = tf.train.RMSPropOptimizer(learning_rate, decay=FLAGS.rms_decay,
- use_locking=True,
- epsilon=FLAGS.rms_epsilon)
- grads_and_vars = meta_opt.compute_gradients(train_output.metaobj + reg_l2,
- meta_parameters)
-
- # clip the gradients
- clipped_grads_and_vars = []
- for grad, var in grads_and_vars:
- clipped_grad = tf.clip_by_value(
- utils.make_finite(grad, replacement=tf.zeros_like(var)),
- -gradient_clip, gradient_clip)
- clipped_grads_and_vars.append((clipped_grad, var))
-
- # histogram summary of grads and vars
- for grad, var in grads_and_vars:
- tf.summary.histogram(
- var.name + "_rawgrad",
- utils.make_finite(
- grad, replacement=tf.zeros_like(grad)),
- collections=[OPT_SUM_COLLECTION])
- for grad, var in clipped_grads_and_vars:
- tf.summary.histogram(var.name + "_var", var,
- collections=[OPT_SUM_COLLECTION])
- tf.summary.histogram(var.name + "_grad", grad,
- collections=[OPT_SUM_COLLECTION])
-
- # builds the train and summary operations
- train_op = meta_opt.apply_gradients(clipped_grads_and_vars,
- global_step=global_step)
-
- # only grab summaries defined for LOL, not inside the problem
- summary_op = tf.summary.merge_all(key=OPT_SUM_COLLECTION)
-
- # make sure the state gets propagated after the gradients and summaries
- # were computed.
- with tf.control_dependencies([train_op, summary_op]):
- propagate_loop_state_ops = []
- for dest, src in zip(
- train_output.init_loop_vars, train_output.output_loop_vars):
- propagate_loop_state_ops.append(dest.assign(src))
- propagate_loop_state_op = tf.group(*propagate_loop_state_ops)
-
- # create the supervisor
- sv = tf.train.Supervisor(
- graph=graph,
- is_chief=is_chief,
- logdir=logdir,
- summary_op=None,
- save_model_secs=0, # we save checkpoints manually
- global_step=global_step,
- )
-
- with sv.managed_session() as sess:
-
- init_time = time.time() - problem_start_time
- out.write("--------- Problem #{} ---------\n".format(problem_itr))
- out.write("{callable.__name__}{args}{kwargs}\n".format(
- **problem_spec.__dict__))
- out.write("Took {} seconds to initialize.\n".format(init_time))
- out.flush()
-
- # For profiling summaries
- if FLAGS.set_profiling:
- summary_writer = tf.summary.FileWriter(logdir, graph=sess.graph)
-
- # used to store information during training
- metadata = defaultdict(list)
-
- for k in range(num_meta_iterations):
-
- if sv.should_stop():
- break
-
- problem.init_fn(sess)
-
- # set run options (for profiling)
- full_trace_opt = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
- run_options = full_trace_opt if FLAGS.set_profiling else None
- run_metadata = tf.RunMetadata() if FLAGS.set_profiling else None
-
- num_unrolls = num_unroll_func()
- partial_unroll_iters = [
- num_partial_unroll_itrs_func() for _ in xrange(num_unrolls)
- ]
- total_num_iter = sum(partial_unroll_iters)
-
- objective_weights = [np.ones(num) / float(num)
- for num in partial_unroll_iters]
- db = dataset.batch_indices(total_num_iter, batch_size)
- dataset_batches = []
- last_index = 0
- for num in partial_unroll_iters:
- dataset_batches.append(db[last_index:last_index + num])
- last_index += num
-
- train_start_time = time.time()
-
- unroll_itr = 0
- additional_log_info = ""
-
- for unroll_itr in range(num_unrolls):
- first_unroll = unroll_itr == 0
- if FLAGS.reset_rnn_params:
- reset_state = first_unroll and k == 0
- else:
- reset_state = first_unroll
-
- feed = {
- train_output.obj_weights: objective_weights[unroll_itr],
- train_output.batches: dataset_batches[unroll_itr],
- train_output.first_unroll: first_unroll,
- train_output.reset_state: reset_state,
- }
-
- # run the train and summary ops
- # when a "save_diagnostics" flag is turned on
- fetches_list = [
- train_output.metaobj,
- train_output.problem_objectives,
- train_output.initial_obj,
- summary_op,
- clipped_grads_and_vars,
- train_op
- ]
- if unroll_itr + 1 < num_unrolls:
- fetches_list += [propagate_loop_state_op]
-
- fetched = sess.run(fetches_list, feed_dict=feed,
- options=run_options, run_metadata=run_metadata)
- meta_obj = fetched[0]
- sub_obj = fetched[1]
- init_obj = fetched[2]
- summ = fetched[3]
- meta_grads_and_params = fetched[4]
-
- # assert that the subproblem objectives are non-negative
- # (this is so that we can rescale the objective by the initial value
- # and not worry about rescaling by a negative value)
- if np.any(sub_obj < 0):
- raise ValueError(
- "Training problem objectives must be nonnegative.")
- # If the objective has increased more than we want, exit this
- # training run and start over on another meta iteration.
- if obj_train_max_multiplier > 0 and (
- sub_obj[-1] > (init_obj +
- abs(init_obj) * (obj_train_max_multiplier - 1))):
- msg = " Broke early at {} out of {} unrolls. ".format(
- unroll_itr + 1, num_unrolls)
- additional_log_info += msg
- break
-
- # only the chief task is allowed to write the summary
- if is_chief:
- sv.summary_computed(sess, summ)
-
- metadata["subproblem_objs"].append(sub_obj)
- # store training metadata to pass to the callback
- metadata["meta_objs"].append(meta_obj)
- metadata["meta_grads_and_params"].append(meta_grads_and_params)
-
- optimization_time = time.time() - train_start_time
-
- if FLAGS.set_profiling:
- summary_name = "%02d_iter%04d_%02d" % (FLAGS.task, problem_itr, k)
- summary_writer.add_run_metadata(run_metadata, summary_name)
-
- metadata["global_step"].append(sess.run(global_step))
- metadata["runtimes"].append(optimization_time)
-
- # write a diagnostic message to the output
- args = (k, meta_obj, optimization_time,
- sum(partial_unroll_iters[:unroll_itr+1]))
- out.write(" [{:02}] {}, {} seconds, {} iters ".format(*args))
- out.write("(unrolled {} steps)".format(
- ", ".join([str(s) for s in partial_unroll_iters[:unroll_itr+1]])))
- out.write("{}\n".format(additional_log_info))
- out.flush()
-
- if FLAGS.set_profiling:
- summary_writer.close()
-
- # force a checkpoint save before we load a new problem
- # only the chief task has the save_path and can write the checkpoint
- if is_chief:
- sv.saver.save(sess, sv.save_path, global_step=global_step)
-
- # run the callbacks on the chief
- if is_chief and callbacks is not None:
- for callback in callbacks:
- if hasattr(callback, "__call__"):
- problem_name = problem_spec.callable.__name__
- callback(problem_name, problem_itr, logdir, metadata)
-
-
-def test_optimizer(optimizer,
- problem,
- num_iter,
- dataset=datasets.EMPTY_DATASET,
- batch_size=None,
- seed=None,
- graph=None,
- logdir=None,
- record_every=None):
- """Tests an optimization algorithm on a given problem.
-
- Args:
- optimizer: Either a tf.train.Optimizer instance, or an Optimizer instance
- inheriting from trainable_optimizer.py
- problem: A Problem instance that defines an optimization problem to solve
- num_iter: The number of iterations of the optimizer to run
- dataset: The dataset to train the problem against
- batch_size: The number of samples per batch. If None (default), the
- batch size is set to the full batch (dataset.size)
- seed: A random seed used for drawing the initial parameters, or a list of
- numpy arrays used to explicitly initialize the parameters.
- graph: The tensorflow graph to execute (if None, uses the default graph)
- logdir: A directory containing model checkpoints. If given, then the
- parameters of the optimizer are loaded from the latest checkpoint
- in this folder.
- record_every: if an integer, stores the parameters, objective, and gradient
- every recored_every iterations. If None, nothing is stored
-
- Returns:
- objective_values: A list of the objective values during optimization
- parameters: The parameters obtained after training
- records: A dictionary containing lists of the parameters and gradients
- during optimization saved every record_every iterations (empty if
- record_every is set to None)
- """
-
- if dataset is None:
- dataset = datasets.EMPTY_DATASET
- batch_size = dataset.size
- else:
- # default batch size is the entire dataset
- batch_size = dataset.size if batch_size is None else batch_size
-
- graph = tf.get_default_graph() if graph is None else graph
- with graph.as_default():
-
- # define the parameters of the optimization problem
- if isinstance(seed, (list, tuple)):
- # seed is a list of arrays
- params = problem_generator.init_fixed_variables(seed)
- else:
- # seed is an int or None
- params = problem.init_variables(seed)
-
- data_placeholder = tf.placeholder(tf.float32)
- labels_placeholder = tf.placeholder(tf.int32)
-
- # get the problem objective and gradient(s)
- obj = problem.objective(params, data_placeholder, labels_placeholder)
- gradients = problem.gradients(obj, params)
-
- vars_to_preinitialize = params
-
- with tf.Session(graph=graph) as sess:
- # initialize the parameter scope variables; necessary for apply_gradients
- sess.run(tf.variables_initializer(vars_to_preinitialize))
- coord = tf.train.Coordinator()
- threads = tf.train.start_queue_runners(sess=sess, coord=coord)
-
- # create the train operation and training variables
- try:
- train_op, real_params = optimizer.apply_gradients(zip(gradients, params))
- obj = problem.objective(real_params, data_placeholder, labels_placeholder)
- except TypeError:
- # If all goes well, this exception should only be thrown when we are using
- # a non-hrnn optimizer.
- train_op = optimizer.apply_gradients(zip(gradients, params))
-
- vars_to_restore = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES,
- scope=OPTIMIZER_SCOPE)
- vars_to_initialize = list(
- set(tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES)) -
- set(vars_to_restore) - set(vars_to_preinitialize))
- # load or initialize optimizer variables
- if logdir is not None:
- restorer = tf.Saver(var_list=vars_to_restore)
- ckpt = tf.train.latest_checkpoint(logdir)
- restorer.restore(sess, ckpt)
- else:
- sess.run(tf.variables_initializer(vars_to_restore))
- # initialize all the other variables
- sess.run(tf.variables_initializer(vars_to_initialize))
-
- problem.init_fn(sess)
-
- # generate the minibatch indices
- batch_inds = dataset.batch_indices(num_iter, batch_size)
-
- # run the train operation for n iterations and save the objectives
- records = defaultdict(list)
- objective_values = []
- for itr, batch in enumerate(batch_inds):
-
- # data to feed in
- feed = {data_placeholder: dataset.data[batch],
- labels_placeholder: dataset.labels[batch]}
- full_feed = {data_placeholder: dataset.data,
- labels_placeholder: dataset.labels}
-
- # record stuff
- if record_every is not None and (itr % record_every) == 0:
- def grad_value(g):
- if isinstance(g, tf.IndexedSlices):
- return g.values
- else:
- return g
-
- records_fetch = {}
- for p in params:
- for key in optimizer.get_slot_names():
- v = optimizer.get_slot(p, key)
- records_fetch[p.name + "_" + key] = v
- gav_fetch = [(grad_value(g), v) for g, v in zip(gradients, params)]
-
- _, gav_eval, records_eval = sess.run(
- (obj, gav_fetch, records_fetch), feed_dict=feed)
- full_obj_eval = sess.run([obj], feed_dict=full_feed)
-
- records["objective"].append(full_obj_eval)
- records["grad_norm"].append([np.linalg.norm(g.ravel())
- for g, _ in gav_eval])
- records["param_norm"].append([np.linalg.norm(v.ravel())
- for _, v in gav_eval])
- records["grad"].append([g for g, _ in gav_eval])
- records["param"].append([v for _, v in gav_eval])
- records["iter"].append(itr)
-
- for k, v in records_eval.iteritems():
- records[k].append(v)
-
- # run the optimization train operation
- objective_values.append(sess.run([train_op, obj], feed_dict=feed)[1])
-
- # final parameters
- parameters = [sess.run(p) for p in params]
- coord.request_stop()
- coord.join(threads)
-
- return objective_values, parameters, records
-
-
-def run_wall_clock_test(optimizer,
- problem,
- num_steps,
- dataset=datasets.EMPTY_DATASET,
- seed=None,
- logdir=None,
- batch_size=None):
- """Runs optimization with the given parameters and return average iter time.
-
- Args:
- optimizer: The tf.train.Optimizer instance
- problem: The problem to optimize (a problem_generator.Problem)
- num_steps: The number of steps to run optimization for
- dataset: The dataset to train the problem against
- seed: The seed used for drawing the initial parameters, or a list of
- numpy arrays used to explicitly initialize the parameters
- logdir: A directory containing model checkpoints. If given, then the
- parameters of the optimizer are loaded from the latest checkpoint
- in this folder.
- batch_size: The number of samples per batch.
-
- Returns:
- The average time in seconds for a single optimization iteration.
- """
- if dataset is None:
- dataset = datasets.EMPTY_DATASET
- batch_size = dataset.size
- else:
- # default batch size is the entire dataset
- batch_size = dataset.size if batch_size is None else batch_size
-
- # define the parameters of the optimization problem
- if isinstance(seed, (list, tuple)):
- # seed is a list of arrays
- params = problem_generator.init_fixed_variables(seed)
- else:
- # seed is an int or None
- params = problem.init_variables(seed)
-
- data_placeholder = tf.placeholder(tf.float32)
- labels_placeholder = tf.placeholder(tf.int32)
-
- obj = problem.objective(params, data_placeholder, labels_placeholder)
- gradients = problem.gradients(obj, params)
- vars_to_preinitialize = params
-
- with tf.Session(graph=tf.get_default_graph()) as sess:
- # initialize the parameter scope variables; necessary for apply_gradients
- sess.run(tf.variables_initializer(vars_to_preinitialize))
- train_op = optimizer.apply_gradients(zip(gradients, params))
- if isinstance(train_op, tuple) or isinstance(train_op, list):
- # LOL apply_gradients returns a tuple. Regular optimizers do not.
- train_op = train_op[0]
- vars_to_restore = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES,
- scope=OPTIMIZER_SCOPE)
- vars_to_initialize = list(
- set(tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES)) -
- set(vars_to_restore) - set(vars_to_preinitialize))
- # load or initialize optimizer variables
- if logdir is not None:
- restorer = tf.Saver(var_list=vars_to_restore)
- ckpt = tf.train.latest_checkpoint(logdir)
- restorer.restore(sess, ckpt)
- else:
- sess.run(tf.variables_initializer(vars_to_restore))
- # initialize all the other variables
- sess.run(tf.variables_initializer(vars_to_initialize))
-
- problem.init_fn(sess)
-
- # generate the minibatch indices
- batch_inds = dataset.batch_indices(num_steps, batch_size)
-
- avg_iter_time = []
- for batch in batch_inds:
- # data to feed in
- feed = {data_placeholder: dataset.data[batch],
- labels_placeholder: dataset.labels[batch]}
-
- # run the optimization train operation
- start = time.time()
- sess.run([train_op], feed_dict=feed)
- avg_iter_time.append(time.time() - start)
-
- return np.median(np.array(avg_iter_time))
diff --git a/research/learned_optimizer/metarun.py b/research/learned_optimizer/metarun.py
deleted file mode 100644
index 45a29623c7fd1381cef590c4e8440d8749585b72..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/metarun.py
+++ /dev/null
@@ -1,394 +0,0 @@
-# Copyright 2017 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Scripts for meta-optimization."""
-
-from __future__ import print_function
-
-import os
-
-import tensorflow as tf
-
-import metaopt
-from learned_optimizer.optimizer import coordinatewise_rnn
-from learned_optimizer.optimizer import global_learning_rate
-from learned_optimizer.optimizer import hierarchical_rnn
-from learned_optimizer.optimizer import learning_rate_schedule
-from learned_optimizer.optimizer import trainable_adam
-from learned_optimizer.problems import problem_sets as ps
-from learned_optimizer.problems import problem_spec
-
-tf.app.flags.DEFINE_string("train_dir", "/tmp/lol/",
- """Directory to store parameters and results.""")
-
-tf.app.flags.DEFINE_integer("task", 0,
- """Task id of the replica running the training.""")
-tf.app.flags.DEFINE_integer("worker_tasks", 1,
- """Number of tasks in the worker job.""")
-
-tf.app.flags.DEFINE_integer("num_problems", 1000,
- """Number of sub-problems to run.""")
-tf.app.flags.DEFINE_integer("num_meta_iterations", 5,
- """Number of meta-iterations to optimize.""")
-tf.app.flags.DEFINE_integer("num_unroll_scale", 40,
- """The scale parameter of the exponential
- distribution from which the number of partial
- unrolls is drawn""")
-tf.app.flags.DEFINE_integer("min_num_unrolls", 1,
- """The minimum number of unrolls per problem.""")
-tf.app.flags.DEFINE_integer("num_partial_unroll_itr_scale", 200,
- """The scale parameter of the exponential
- distribution from which the number of iterations
- per unroll is drawn.""")
-tf.app.flags.DEFINE_integer("min_num_itr_partial_unroll", 50,
- """The minimum number of iterations for one
- unroll.""")
-
-tf.app.flags.DEFINE_string("optimizer", "HierarchicalRNN",
- """Which meta-optimizer to train.""")
-
-# CoordinatewiseRNN-specific flags
-tf.app.flags.DEFINE_integer("cell_size", 20,
- """Size of the RNN hidden state in each layer.""")
-tf.app.flags.DEFINE_integer("num_cells", 2,
- """Number of RNN layers.""")
-tf.app.flags.DEFINE_string("cell_cls", "GRUCell",
- """Type of RNN cell to use.""")
-
-# Metaoptimization parameters
-tf.app.flags.DEFINE_float("meta_learning_rate", 1e-6,
- """The learning rate for the meta-optimizer.""")
-tf.app.flags.DEFINE_float("gradient_clip_level", 1e4,
- """The level to clip gradients to.""")
-
-# Training set selection
-tf.app.flags.DEFINE_boolean("include_quadratic_problems", False,
- """Include non-noisy quadratic problems.""")
-tf.app.flags.DEFINE_boolean("include_noisy_quadratic_problems", True,
- """Include noisy quadratic problems.""")
-tf.app.flags.DEFINE_boolean("include_large_quadratic_problems", True,
- """Include very large quadratic problems.""")
-tf.app.flags.DEFINE_boolean("include_bowl_problems", True,
- """Include 2D bowl problems.""")
-tf.app.flags.DEFINE_boolean("include_softmax_2_class_problems", True,
- """Include 2-class logistic regression problems.""")
-tf.app.flags.DEFINE_boolean("include_noisy_softmax_2_class_problems", True,
- """Include noisy 2-class logistic regression
- problems.""")
-tf.app.flags.DEFINE_boolean("include_optimization_test_problems", True,
- """Include non-noisy versions of classic
- optimization test problems, e.g. Rosenbrock.""")
-tf.app.flags.DEFINE_boolean("include_noisy_optimization_test_problems", True,
- """Include gradient-noise versions of classic
- optimization test problems, e.g. Rosenbrock""")
-tf.app.flags.DEFINE_boolean("include_fully_connected_random_2_class_problems",
- True, """Include MLP problems for 2 classes.""")
-tf.app.flags.DEFINE_boolean("include_matmul_problems", True,
- """Include matrix multiplication problems.""")
-tf.app.flags.DEFINE_boolean("include_log_objective_problems", True,
- """Include problems where the objective is the log
- objective of another problem, e.g. Bowl.""")
-tf.app.flags.DEFINE_boolean("include_rescale_problems", True,
- """Include problems where the parameters are scaled
- version of the original parameters.""")
-tf.app.flags.DEFINE_boolean("include_norm_problems", True,
- """Include problems where the objective is the
- N-norm of another problem, e.g. Quadratic.""")
-tf.app.flags.DEFINE_boolean("include_sum_problems", True,
- """Include problems where the objective is the sum
- of the objectives of the subproblems that make
- up the problem parameters. Per-problem tensors
- are still independent of each other.""")
-tf.app.flags.DEFINE_boolean("include_sparse_gradient_problems", True,
- """Include problems where the gradient is set to 0
- with some high probability.""")
-tf.app.flags.DEFINE_boolean("include_sparse_softmax_problems", False,
- """Include sparse softmax problems.""")
-tf.app.flags.DEFINE_boolean("include_one_hot_sparse_softmax_problems", False,
- """Include one-hot sparse softmax problems.""")
-tf.app.flags.DEFINE_boolean("include_noisy_bowl_problems", True,
- """Include noisy bowl problems.""")
-tf.app.flags.DEFINE_boolean("include_noisy_norm_problems", True,
- """Include noisy norm problems.""")
-tf.app.flags.DEFINE_boolean("include_noisy_sum_problems", True,
- """Include noisy sum problems.""")
-tf.app.flags.DEFINE_boolean("include_sum_of_quadratics_problems", False,
- """Include sum of quadratics problems.""")
-tf.app.flags.DEFINE_boolean("include_projection_quadratic_problems", False,
- """Include projection quadratic problems.""")
-tf.app.flags.DEFINE_boolean("include_outward_snake_problems", False,
- """Include outward snake problems.""")
-tf.app.flags.DEFINE_boolean("include_dependency_chain_problems", False,
- """Include dependency chain problems.""")
-tf.app.flags.DEFINE_boolean("include_min_max_well_problems", False,
- """Include min-max well problems.""")
-
-# Optimizer parameters: initialization and scale values
-tf.app.flags.DEFINE_float("min_lr", 1e-6,
- """The minimum initial learning rate.""")
-tf.app.flags.DEFINE_float("max_lr", 1e-2,
- """The maximum initial learning rate.""")
-
-# Optimizer parameters: small features.
-tf.app.flags.DEFINE_boolean("zero_init_lr_weights", True,
- """Whether to initialize the learning rate weights
- to 0 rather than the scaled random initialization
- used for other RNN variables.""")
-tf.app.flags.DEFINE_boolean("use_relative_lr", True,
- """Whether to use the relative learning rate as an
- input during training. Can only be used if
- learnable_decay is also True.""")
-tf.app.flags.DEFINE_boolean("use_extreme_indicator", False,
- """Whether to use the extreme indicator for learning
- rates as an input during training. Can only be
- used if learnable_decay is also True.""")
-tf.app.flags.DEFINE_boolean("use_log_means_squared", True,
- """Whether to track the log of the mean squared
- grads instead of the means squared grads.""")
-tf.app.flags.DEFINE_boolean("use_problem_lr_mean", True,
- """Whether to use the mean over all learning rates
- in the problem when calculating the relative
- learning rate.""")
-
-# Optimizer parameters: major features
-tf.app.flags.DEFINE_boolean("learnable_decay", True,
- """Whether to learn weights that dynamically
- modulate the input scale via RMS decay.""")
-tf.app.flags.DEFINE_boolean("dynamic_output_scale", True,
- """Whether to learn weights that dynamically
- modulate the output scale.""")
-tf.app.flags.DEFINE_boolean("use_log_objective", True,
- """Whether to use the log of the scaled objective
- rather than just the scaled obj for training.""")
-tf.app.flags.DEFINE_boolean("use_attention", False,
- """Whether to learn where to attend.""")
-tf.app.flags.DEFINE_boolean("use_second_derivatives", True,
- """Whether to use second derivatives.""")
-tf.app.flags.DEFINE_integer("num_gradient_scales", 4,
- """How many different timescales to keep for
- gradient history. If > 1, also learns a scale
- factor for gradient history.""")
-tf.app.flags.DEFINE_float("max_log_lr", 33,
- """The maximum log learning rate allowed.""")
-tf.app.flags.DEFINE_float("objective_training_max_multiplier", -1,
- """How much the objective can grow before training on
- this problem / param pair is terminated. Sets a max
- on the objective value when multiplied by the
- initial objective. If <= 0, not used.""")
-tf.app.flags.DEFINE_boolean("use_gradient_shortcut", True,
- """Whether to add a learned affine projection of the
- gradient to the update delta in addition to the
- gradient function computed by the RNN.""")
-tf.app.flags.DEFINE_boolean("use_lr_shortcut", False,
- """Whether to add the difference between the current
- learning rate and the desired learning rate to
- the RNN input.""")
-tf.app.flags.DEFINE_boolean("use_grad_products", True,
- """Whether to use gradient products in the input to
- the RNN. Only applicable when num_gradient_scales
- > 1.""")
-tf.app.flags.DEFINE_boolean("use_multiple_scale_decays", False,
- """Whether to use many-timescale scale decays.""")
-tf.app.flags.DEFINE_boolean("use_numerator_epsilon", False,
- """Whether to use epsilon in the numerator of the
- log objective.""")
-tf.app.flags.DEFINE_boolean("learnable_inp_decay", True,
- """Whether to learn input decay weight and bias.""")
-tf.app.flags.DEFINE_boolean("learnable_rnn_init", True,
- """Whether to learn RNN state initialization.""")
-
-FLAGS = tf.app.flags.FLAGS
-
-# The Size of the RNN hidden state in each layer:
-# [PerParam, PerTensor, Global]. The length of this list must be 1, 2, or 3.
-# If less than 3, the Global and/or PerTensor RNNs will not be created.
-
-HRNN_CELL_SIZES = [10, 20, 20]
-
-
-
-def register_optimizers():
- opts = {}
- opts["CoordinatewiseRNN"] = coordinatewise_rnn.CoordinatewiseRNN
- opts["GlobalLearningRate"] = global_learning_rate.GlobalLearningRate
- opts["HierarchicalRNN"] = hierarchical_rnn.HierarchicalRNN
- opts["LearningRateSchedule"] = learning_rate_schedule.LearningRateSchedule
- opts["TrainableAdam"] = trainable_adam.TrainableAdam
- return opts
-
-
-def main(unused_argv):
- """Runs the main script."""
-
- opts = register_optimizers()
-
- # Choose a set of problems to optimize. By default this includes quadratics,
- # 2-dimensional bowls, 2-class softmax problems, and non-noisy optimization
- # test problems (e.g. Rosenbrock, Beale)
- problems_and_data = []
-
- if FLAGS.include_sparse_softmax_problems:
- problems_and_data.extend(ps.sparse_softmax_2_class_sparse_problems())
-
- if FLAGS.include_one_hot_sparse_softmax_problems:
- problems_and_data.extend(
- ps.one_hot_sparse_softmax_2_class_sparse_problems())
-
- if FLAGS.include_quadratic_problems:
- problems_and_data.extend(ps.quadratic_problems())
-
- if FLAGS.include_noisy_quadratic_problems:
- problems_and_data.extend(ps.quadratic_problems_noisy())
-
- if FLAGS.include_large_quadratic_problems:
- problems_and_data.extend(ps.quadratic_problems_large())
-
- if FLAGS.include_bowl_problems:
- problems_and_data.extend(ps.bowl_problems())
-
- if FLAGS.include_noisy_bowl_problems:
- problems_and_data.extend(ps.bowl_problems_noisy())
-
- if FLAGS.include_softmax_2_class_problems:
- problems_and_data.extend(ps.softmax_2_class_problems())
-
- if FLAGS.include_noisy_softmax_2_class_problems:
- problems_and_data.extend(ps.softmax_2_class_problems_noisy())
-
- if FLAGS.include_optimization_test_problems:
- problems_and_data.extend(ps.optimization_test_problems())
-
- if FLAGS.include_noisy_optimization_test_problems:
- problems_and_data.extend(ps.optimization_test_problems_noisy())
-
- if FLAGS.include_fully_connected_random_2_class_problems:
- problems_and_data.extend(ps.fully_connected_random_2_class_problems())
-
- if FLAGS.include_matmul_problems:
- problems_and_data.extend(ps.matmul_problems())
-
- if FLAGS.include_log_objective_problems:
- problems_and_data.extend(ps.log_objective_problems())
-
- if FLAGS.include_rescale_problems:
- problems_and_data.extend(ps.rescale_problems())
-
- if FLAGS.include_norm_problems:
- problems_and_data.extend(ps.norm_problems())
-
- if FLAGS.include_noisy_norm_problems:
- problems_and_data.extend(ps.norm_problems_noisy())
-
- if FLAGS.include_sum_problems:
- problems_and_data.extend(ps.sum_problems())
-
- if FLAGS.include_noisy_sum_problems:
- problems_and_data.extend(ps.sum_problems_noisy())
-
- if FLAGS.include_sparse_gradient_problems:
- problems_and_data.extend(ps.sparse_gradient_problems())
- if FLAGS.include_fully_connected_random_2_class_problems:
- problems_and_data.extend(ps.sparse_gradient_problems_mlp())
-
- if FLAGS.include_min_max_well_problems:
- problems_and_data.extend(ps.min_max_well_problems())
-
- if FLAGS.include_sum_of_quadratics_problems:
- problems_and_data.extend(ps.sum_of_quadratics_problems())
-
- if FLAGS.include_projection_quadratic_problems:
- problems_and_data.extend(ps.projection_quadratic_problems())
-
- if FLAGS.include_outward_snake_problems:
- problems_and_data.extend(ps.outward_snake_problems())
-
- if FLAGS.include_dependency_chain_problems:
- problems_and_data.extend(ps.dependency_chain_problems())
-
- # log directory
- logdir = os.path.join(FLAGS.train_dir,
- "{}_{}_{}_{}".format(FLAGS.optimizer,
- FLAGS.cell_cls,
- FLAGS.cell_size,
- FLAGS.num_cells))
-
- # get the optimizer class and arguments
- optimizer_cls = opts[FLAGS.optimizer]
-
- assert len(HRNN_CELL_SIZES) in [1, 2, 3]
- optimizer_args = (HRNN_CELL_SIZES,)
-
- optimizer_kwargs = {
- "init_lr_range": (FLAGS.min_lr, FLAGS.max_lr),
- "learnable_decay": FLAGS.learnable_decay,
- "dynamic_output_scale": FLAGS.dynamic_output_scale,
- "cell_cls": getattr(tf.contrib.rnn, FLAGS.cell_cls),
- "use_attention": FLAGS.use_attention,
- "use_log_objective": FLAGS.use_log_objective,
- "num_gradient_scales": FLAGS.num_gradient_scales,
- "zero_init_lr_weights": FLAGS.zero_init_lr_weights,
- "use_log_means_squared": FLAGS.use_log_means_squared,
- "use_relative_lr": FLAGS.use_relative_lr,
- "use_extreme_indicator": FLAGS.use_extreme_indicator,
- "max_log_lr": FLAGS.max_log_lr,
- "obj_train_max_multiplier": FLAGS.objective_training_max_multiplier,
- "use_problem_lr_mean": FLAGS.use_problem_lr_mean,
- "use_gradient_shortcut": FLAGS.use_gradient_shortcut,
- "use_second_derivatives": FLAGS.use_second_derivatives,
- "use_lr_shortcut": FLAGS.use_lr_shortcut,
- "use_grad_products": FLAGS.use_grad_products,
- "use_multiple_scale_decays": FLAGS.use_multiple_scale_decays,
- "use_numerator_epsilon": FLAGS.use_numerator_epsilon,
- "learnable_inp_decay": FLAGS.learnable_inp_decay,
- "learnable_rnn_init": FLAGS.learnable_rnn_init,
- }
- optimizer_spec = problem_spec.Spec(
- optimizer_cls, optimizer_args, optimizer_kwargs)
-
- # make log directory
- tf.gfile.MakeDirs(logdir)
-
- is_chief = FLAGS.task == 0
- # if this is a distributed run, make the chief run through problems in order
- select_random_problems = FLAGS.worker_tasks == 1 or not is_chief
-
- def num_unrolls():
- return metaopt.sample_numiter(FLAGS.num_unroll_scale, FLAGS.min_num_unrolls)
-
- def num_partial_unroll_itrs():
- return metaopt.sample_numiter(FLAGS.num_partial_unroll_itr_scale,
- FLAGS.min_num_itr_partial_unroll)
-
- # run it
- metaopt.train_optimizer(
- logdir,
- optimizer_spec,
- problems_and_data,
- FLAGS.num_problems,
- FLAGS.num_meta_iterations,
- num_unrolls,
- num_partial_unroll_itrs,
- learning_rate=FLAGS.meta_learning_rate,
- gradient_clip=FLAGS.gradient_clip_level,
- is_chief=is_chief,
- select_random_problems=select_random_problems,
- obj_train_max_multiplier=FLAGS.objective_training_max_multiplier,
- callbacks=[])
-
- return 0
-
-
-if __name__ == "__main__":
- tf.app.run()
diff --git a/research/learned_optimizer/optimizer/BUILD b/research/learned_optimizer/optimizer/BUILD
deleted file mode 100644
index 8953e7592ace416b786be2a6fa59f4c537c82644..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/optimizer/BUILD
+++ /dev/null
@@ -1,69 +0,0 @@
-package(default_visibility = ["//visibility:public"])
-
-# Libraries
-# =========
-py_library(
- name = "coordinatewise_rnn",
- srcs = ["coordinatewise_rnn.py"],
- deps = [
- ":trainable_optimizer",
- ":utils",
- ],
-)
-
-py_library(
- name = "global_learning_rate",
- srcs = ["global_learning_rate.py"],
- deps = [
- ":trainable_optimizer",
- ],
-)
-
-py_library(
- name = "hierarchical_rnn",
- srcs = ["hierarchical_rnn.py"],
- deps = [
- ":rnn_cells",
- ":trainable_optimizer",
- ":utils",
- ],
-)
-
-py_library(
- name = "learning_rate_schedule",
- srcs = ["learning_rate_schedule.py"],
- deps = [
- ":trainable_optimizer",
- ],
-)
-
-py_library(
- name = "rnn_cells",
- srcs = ["rnn_cells.py"],
- deps = [
- ":utils",
- ],
-)
-
-py_library(
- name = "trainable_adam",
- srcs = ["trainable_adam.py"],
- deps = [
- ":trainable_optimizer",
- ":utils",
- ],
-)
-
-py_library(
- name = "trainable_optimizer",
- srcs = ["trainable_optimizer.py"],
- deps = [
- ],
-)
-
-py_library(
- name = "utils",
- srcs = ["utils.py"],
- deps = [
- ],
-)
diff --git a/research/learned_optimizer/optimizer/coordinatewise_rnn.py b/research/learned_optimizer/optimizer/coordinatewise_rnn.py
deleted file mode 100644
index 3d699504b7a3d86643bea6b295d20b2434131a99..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/optimizer/coordinatewise_rnn.py
+++ /dev/null
@@ -1,316 +0,0 @@
-# Copyright 2017 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Collection of trainable optimizers for meta-optimization."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import math
-
-import numpy as np
-import tensorflow as tf
-
-from learned_optimizer.optimizer import utils
-from learned_optimizer.optimizer import trainable_optimizer as opt
-
-
-# Default was 1e-3
-tf.app.flags.DEFINE_float("crnn_rnn_readout_scale", 0.5,
- """The initialization scale for the RNN readouts.""")
-tf.app.flags.DEFINE_float("crnn_default_decay_var_init", 2.2,
- """The default initializer value for any decay/
- momentum style variables and constants.
- sigmoid(2.2) ~ 0.9, sigmoid(-2.2) ~ 0.01.""")
-
-FLAGS = tf.flags.FLAGS
-
-
-class CoordinatewiseRNN(opt.TrainableOptimizer):
- """RNN that operates on each coordinate of the problem independently."""
-
- def __init__(self,
- cell_sizes,
- cell_cls,
- init_lr_range=(1., 1.),
- dynamic_output_scale=True,
- learnable_decay=True,
- zero_init_lr_weights=False,
- **kwargs):
- """Initializes the RNN per-parameter optimizer.
-
- Args:
- cell_sizes: List of hidden state sizes for each RNN cell in the network
- cell_cls: tf.contrib.rnn class for specifying the RNN cell type
- init_lr_range: the range in which to initialize the learning rates.
- dynamic_output_scale: whether to learn weights that dynamically modulate
- the output scale (default: True)
- learnable_decay: whether to learn weights that dynamically modulate the
- input scale via RMS style decay (default: True)
- zero_init_lr_weights: whether to initialize the lr weights to zero
- **kwargs: args passed to TrainableOptimizer's constructor
-
- Raises:
- ValueError: If the init lr range is not of length 2.
- ValueError: If the init lr range is not a valid range (min > max).
- """
- if len(init_lr_range) != 2:
- raise ValueError(
- "Initial LR range must be len 2, was {}".format(len(init_lr_range)))
- if init_lr_range[0] > init_lr_range[1]:
- raise ValueError("Initial LR range min is greater than max.")
- self.init_lr_range = init_lr_range
-
- self.zero_init_lr_weights = zero_init_lr_weights
- self.reuse_vars = False
-
- # create the RNN cell
- with tf.variable_scope(opt.OPTIMIZER_SCOPE):
- self.component_cells = [cell_cls(sz) for sz in cell_sizes]
- self.cell = tf.contrib.rnn.MultiRNNCell(self.component_cells)
-
- # random normal initialization scaled by the output size
- scale_factor = FLAGS.crnn_rnn_readout_scale / math.sqrt(cell_sizes[-1])
- scaled_init = tf.random_normal_initializer(0., scale_factor)
-
- # weights for projecting the hidden state to a parameter update
- self.update_weights = tf.get_variable("update_weights",
- shape=(cell_sizes[-1], 1),
- initializer=scaled_init)
-
- self._initialize_decay(learnable_decay, (cell_sizes[-1], 1), scaled_init)
-
- self._initialize_lr(dynamic_output_scale, (cell_sizes[-1], 1),
- scaled_init)
-
- state_size = sum([sum(state_size) for state_size in self.cell.state_size])
- self._init_vector = tf.get_variable(
- "init_vector", shape=[1, state_size],
- initializer=tf.random_uniform_initializer(-1., 1.))
-
- state_keys = ["rms", "rnn", "learning_rate", "decay"]
- super(CoordinatewiseRNN, self).__init__("cRNN", state_keys, **kwargs)
-
- def _initialize_decay(
- self, learnable_decay, weights_tensor_shape, scaled_init):
- """Initializes the decay weights and bias variables or tensors.
-
- Args:
- learnable_decay: Whether to use learnable decay.
- weights_tensor_shape: The shape the weight tensor should take.
- scaled_init: The scaled initialization for the weights tensor.
- """
- if learnable_decay:
-
- # weights for projecting the hidden state to the RMS decay term
- self.decay_weights = tf.get_variable("decay_weights",
- shape=weights_tensor_shape,
- initializer=scaled_init)
- self.decay_bias = tf.get_variable(
- "decay_bias", shape=(1,),
- initializer=tf.constant_initializer(
- FLAGS.crnn_default_decay_var_init))
- else:
- self.decay_weights = tf.zeros_like(self.update_weights)
- self.decay_bias = tf.constant(FLAGS.crnn_default_decay_var_init)
-
- def _initialize_lr(
- self, dynamic_output_scale, weights_tensor_shape, scaled_init):
- """Initializes the learning rate weights and bias variables or tensors.
-
- Args:
- dynamic_output_scale: Whether to use a dynamic output scale.
- weights_tensor_shape: The shape the weight tensor should take.
- scaled_init: The scaled initialization for the weights tensor.
- """
- if dynamic_output_scale:
- zero_init = tf.constant_initializer(0.)
- wt_init = zero_init if self.zero_init_lr_weights else scaled_init
- self.lr_weights = tf.get_variable("learning_rate_weights",
- shape=weights_tensor_shape,
- initializer=wt_init)
- self.lr_bias = tf.get_variable("learning_rate_bias", shape=(1,),
- initializer=zero_init)
- else:
- self.lr_weights = tf.zeros_like(self.update_weights)
- self.lr_bias = tf.zeros([1, 1])
-
- def _initialize_state(self, var):
- """Return a dictionary mapping names of state variables to their values."""
- vectorized_shape = [var.get_shape().num_elements(), 1]
-
- min_lr = self.init_lr_range[0]
- max_lr = self.init_lr_range[1]
- if min_lr == max_lr:
- init_lr = tf.constant(min_lr, shape=vectorized_shape)
- else:
- actual_vals = tf.random_uniform(vectorized_shape,
- np.log(min_lr),
- np.log(max_lr))
- init_lr = tf.exp(actual_vals)
-
- ones = tf.ones(vectorized_shape)
- rnn_init = ones * self._init_vector
-
- return {
- "rms": tf.ones(vectorized_shape),
- "learning_rate": init_lr,
- "rnn": rnn_init,
- "decay": tf.ones(vectorized_shape),
- }
-
- def _compute_update(self, param, grad, state):
- """Update parameters given the gradient and state.
-
- Args:
- param: tensor of parameters
- grad: tensor of gradients with the same shape as param
- state: a dictionary containing any state for the optimizer
-
- Returns:
- updated_param: updated parameters
- updated_state: updated state variables in a dictionary
- """
-
- with tf.variable_scope(opt.OPTIMIZER_SCOPE) as scope:
-
- if self.reuse_vars:
- scope.reuse_variables()
- else:
- self.reuse_vars = True
-
- param_shape = tf.shape(param)
-
- (grad_values, decay_state, rms_state, rnn_state, learning_rate_state,
- grad_indices) = self._extract_gradients_and_internal_state(
- grad, state, param_shape)
-
- # Vectorize and scale the gradients.
- grad_scaled, rms = utils.rms_scaling(grad_values, decay_state, rms_state)
-
- # Apply the RNN update.
- rnn_state_tuples = self._unpack_rnn_state_into_tuples(rnn_state)
- rnn_output, rnn_state_tuples = self.cell(grad_scaled, rnn_state_tuples)
- rnn_state = self._pack_tuples_into_rnn_state(rnn_state_tuples)
-
- # Compute the update direction (a linear projection of the RNN output).
- delta = utils.project(rnn_output, self.update_weights)
-
- # The updated decay is an affine projection of the hidden state
- decay = utils.project(rnn_output, self.decay_weights,
- bias=self.decay_bias, activation=tf.nn.sigmoid)
-
- # Compute the change in learning rate (an affine projection of the RNN
- # state, passed through a 2x sigmoid, so the change is bounded).
- learning_rate_change = 2. * utils.project(rnn_output, self.lr_weights,
- bias=self.lr_bias,
- activation=tf.nn.sigmoid)
-
- # Update the learning rate.
- new_learning_rate = learning_rate_change * learning_rate_state
-
- # Apply the update to the parameters.
- update = tf.reshape(new_learning_rate * delta, tf.shape(grad_values))
-
- if isinstance(grad, tf.IndexedSlices):
- update = utils.stack_tensor(update, grad_indices, param,
- param_shape[:1])
- rms = utils.update_slices(rms, grad_indices, state["rms"], param_shape)
- new_learning_rate = utils.update_slices(new_learning_rate, grad_indices,
- state["learning_rate"],
- param_shape)
- rnn_state = utils.update_slices(rnn_state, grad_indices, state["rnn"],
- param_shape)
- decay = utils.update_slices(decay, grad_indices, state["decay"],
- param_shape)
-
- new_param = param - update
-
- # Collect the update and new state.
- new_state = {
- "rms": rms,
- "learning_rate": new_learning_rate,
- "rnn": rnn_state,
- "decay": decay,
- }
-
- return new_param, new_state
-
- def _extract_gradients_and_internal_state(self, grad, state, param_shape):
- """Extracts the gradients and relevant internal state.
-
- If the gradient is sparse, extracts the appropriate slices from the state.
-
- Args:
- grad: The current gradient.
- state: The current state.
- param_shape: The shape of the parameter (used if gradient is sparse).
-
- Returns:
- grad_values: The gradient value tensor.
- decay_state: The current decay state.
- rms_state: The current rms state.
- rnn_state: The current state of the internal rnns.
- learning_rate_state: The current learning rate state.
- grad_indices: The indices for the gradient tensor, if sparse.
- None otherwise.
- """
- if isinstance(grad, tf.IndexedSlices):
- grad_indices, grad_values = utils.accumulate_sparse_gradients(grad)
- decay_state = utils.slice_tensor(state["decay"], grad_indices,
- param_shape)
- rms_state = utils.slice_tensor(state["rms"], grad_indices, param_shape)
- rnn_state = utils.slice_tensor(state["rnn"], grad_indices, param_shape)
- learning_rate_state = utils.slice_tensor(state["learning_rate"],
- grad_indices, param_shape)
- decay_state.set_shape([None, 1])
- rms_state.set_shape([None, 1])
- else:
- grad_values = grad
- grad_indices = None
-
- decay_state = state["decay"]
- rms_state = state["rms"]
- rnn_state = state["rnn"]
- learning_rate_state = state["learning_rate"]
- return (grad_values, decay_state, rms_state, rnn_state, learning_rate_state,
- grad_indices)
-
- def _unpack_rnn_state_into_tuples(self, rnn_state):
- """Creates state tuples from the rnn state vector."""
- rnn_state_tuples = []
- cur_state_pos = 0
- for cell in self.component_cells:
- total_state_size = sum(cell.state_size)
- cur_state = tf.slice(rnn_state, [0, cur_state_pos],
- [-1, total_state_size])
- cur_state_tuple = tf.split(value=cur_state, num_or_size_splits=2,
- axis=1)
- rnn_state_tuples.append(cur_state_tuple)
- cur_state_pos += total_state_size
- return rnn_state_tuples
-
- def _pack_tuples_into_rnn_state(self, rnn_state_tuples):
- """Creates a single state vector concatenated along column axis."""
- rnn_state = None
- for new_state_tuple in rnn_state_tuples:
- new_c, new_h = new_state_tuple
- if rnn_state is None:
- rnn_state = tf.concat([new_c, new_h], axis=1)
- else:
- rnn_state = tf.concat([rnn_state, tf.concat([new_c, new_h], 1)], axis=1)
- return rnn_state
-
diff --git a/research/learned_optimizer/optimizer/global_learning_rate.py b/research/learned_optimizer/optimizer/global_learning_rate.py
deleted file mode 100644
index bcf102fff054e9fe9e92d4379538f6394314fe1c..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/optimizer/global_learning_rate.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2017 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""A trainable optimizer that learns a single global learning rate."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-from learned_optimizer.optimizer import trainable_optimizer
-
-
-class GlobalLearningRate(trainable_optimizer.TrainableOptimizer):
- """Optimizes for a single global learning rate."""
-
- def __init__(self, initial_rate=1e-3, **kwargs):
- """Initializes the global learning rate."""
- with tf.variable_scope(trainable_optimizer.OPTIMIZER_SCOPE):
- initializer = tf.constant_initializer(initial_rate)
- self.learning_rate = tf.get_variable("global_learning_rate", shape=(),
- initializer=initializer)
- super(GlobalLearningRate, self).__init__("GLR", [], **kwargs)
-
- def _compute_update(self, param, grad, state):
- return param - tf.scalar_mul(self.learning_rate, grad), state
-
diff --git a/research/learned_optimizer/optimizer/hierarchical_rnn.py b/research/learned_optimizer/optimizer/hierarchical_rnn.py
deleted file mode 100644
index 953b72b5d04724a11a0e95385bbe0c6a0d91289d..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/optimizer/hierarchical_rnn.py
+++ /dev/null
@@ -1,792 +0,0 @@
-# Copyright 2017 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Collection of trainable optimizers for meta-optimization."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import math
-
-import numpy as np
-import tensorflow as tf
-
-from tensorflow.python.ops import state_ops
-from learned_optimizer.optimizer import rnn_cells
-from learned_optimizer.optimizer import trainable_optimizer as opt
-from learned_optimizer.optimizer import utils
-
-# Default was 0.1
-tf.app.flags.DEFINE_float("biasgrucell_scale", 0.5,
- """The scale for the internal BiasGRUCell vars.""")
-# Default was 0
-tf.app.flags.DEFINE_float("biasgrucell_gate_bias_init", 2.2,
- """The bias for the internal BiasGRUCell reset and
- update gate variables.""")
-# Default was 1e-3
-tf.app.flags.DEFINE_float("hrnn_rnn_readout_scale", 0.5,
- """The initialization scale for the RNN readouts.""")
-tf.app.flags.DEFINE_float("hrnn_default_decay_var_init", 2.2,
- """The default initializer value for any decay/
- momentum style variables and constants.
- sigmoid(2.2) ~ 0.9, sigmoid(-2.2) ~ 0.01.""")
-# Default was 2.2
-tf.app.flags.DEFINE_float("scale_decay_bias_init", 3.2,
- """The initialization for the scale decay bias. This
- is the initial bias for the timescale for the
- exponential avg of the mean square gradients.""")
-tf.app.flags.DEFINE_float("learning_rate_momentum_logit_init", 3.2,
- """Initialization for the learning rate momentum.""")
-# Default was 0.1
-tf.app.flags.DEFINE_float("hrnn_affine_scale", 0.5,
- """The initialization scale for the weight matrix of
- the bias variables in layer0 and 1 of the hrnn.""")
-
-FLAGS = tf.flags.FLAGS
-
-
-class HierarchicalRNN(opt.TrainableOptimizer):
- """3 level hierarchical RNN.
-
- Optionally uses second order gradient information and has decoupled evaluation
- and update locations.
- """
-
- def __init__(self, level_sizes, init_lr_range=(1e-6, 1e-2),
- learnable_decay=True, dynamic_output_scale=True,
- use_attention=False, use_log_objective=True,
- num_gradient_scales=4, zero_init_lr_weights=True,
- use_log_means_squared=True, use_relative_lr=True,
- use_extreme_indicator=False, max_log_lr=33,
- obj_train_max_multiplier=-1, use_problem_lr_mean=False,
- use_gradient_shortcut=False, use_lr_shortcut=False,
- use_grad_products=False, use_multiple_scale_decays=False,
- learnable_inp_decay=True, learnable_rnn_init=True,
- random_seed=None, **kwargs):
- """Initializes the RNN per-parameter optimizer.
-
- The hierarchy consists of up to three levels:
- Level 0: per parameter RNN
- Level 1: per tensor RNN
- Level 2: global RNN
-
- Args:
- level_sizes: list or tuple with 1, 2, or 3 integers, the number of units
- in each RNN in the hierarchy (level0, level1, level2).
- length 1: only coordinatewise rnn's will be used
- length 2: coordinatewise and tensor-level rnn's will be used
- length 3: a single global-level rnn will be used in addition to
- coordinatewise and tensor-level
- init_lr_range: the range in which to initialize the learning rates
- learnable_decay: whether to learn weights that dynamically modulate the
- input scale via RMS style decay
- dynamic_output_scale: whether to learn weights that dynamically modulate
- the output scale
- use_attention: whether to use attention to train the optimizer
- use_log_objective: whether to train on the log of the objective
- num_gradient_scales: the number of scales to use for gradient history
- zero_init_lr_weights: whether to initialize the lr weights to zero
- use_log_means_squared: whether to track the log of the means_squared,
- used as a measure of signal vs. noise in gradient.
- use_relative_lr: whether to use the relative learning rate as an
- input during training (requires learnable_decay=True)
- use_extreme_indicator: whether to use the extreme indicator for learning
- rates as an input during training (requires learnable_decay=True)
- max_log_lr: the maximum log learning rate allowed during train or test
- obj_train_max_multiplier: max objective increase during a training run
- use_problem_lr_mean: whether to use the mean over all learning rates in
- the problem when calculating the relative learning rate as opposed to
- the per-tensor mean
- use_gradient_shortcut: Whether to add a learned affine projection of the
- gradient to the update delta in addition to the gradient function
- computed by the RNN
- use_lr_shortcut: Whether to add as input the difference between the log lr
- and the desired log lr (1e-3)
- use_grad_products: Whether to use gradient products in the rnn input.
- Only applicable if num_gradient_scales > 1
- use_multiple_scale_decays: Whether to use multiple scales for the scale
- decay, as with input decay
- learnable_inp_decay: Whether to learn the input decay weights and bias.
- learnable_rnn_init: Whether to learn the RNN state initialization.
- random_seed: Random seed for random variable initializers. (Default: None)
- **kwargs: args passed to TrainableOptimizer's constructor
-
- Raises:
- ValueError: If level_sizes is not a length 1, 2, or 3 list.
- ValueError: If there are any non-integer sizes in level_sizes.
- ValueError: If the init lr range is not of length 2.
- ValueError: If the init lr range is not a valid range (min > max).
- """
- if len(level_sizes) not in [1, 2, 3]:
- raise ValueError("HierarchicalRNN only supports 1, 2, or 3 levels in the "
- "hierarchy, but {} were requested.".format(
- len(level_sizes)))
- if any(not isinstance(level, int) for level in level_sizes):
- raise ValueError("Level sizes must be integer values, were {}".format(
- level_sizes))
- if len(init_lr_range) != 2:
- raise ValueError(
- "Initial LR range must be len 2, was {}".format(len(init_lr_range)))
- if init_lr_range[0] > init_lr_range[1]:
- raise ValueError("Initial LR range min is greater than max.")
-
- self.learnable_decay = learnable_decay
- self.dynamic_output_scale = dynamic_output_scale
- self.use_attention = use_attention
- self.use_log_objective = use_log_objective
- self.num_gradient_scales = num_gradient_scales
- self.zero_init_lr_weights = zero_init_lr_weights
- self.use_log_means_squared = use_log_means_squared
- self.use_relative_lr = use_relative_lr
- self.use_extreme_indicator = use_extreme_indicator
- self.max_log_lr = max_log_lr
- self.use_problem_lr_mean = use_problem_lr_mean
- self.use_gradient_shortcut = use_gradient_shortcut
- self.use_lr_shortcut = use_lr_shortcut
- self.use_grad_products = use_grad_products
- self.use_multiple_scale_decays = use_multiple_scale_decays
- self.learnable_inp_decay = learnable_inp_decay
- self.learnable_rnn_init = learnable_rnn_init
-
- self.random_seed = random_seed
-
- self.num_layers = len(level_sizes)
- self.init_lr_range = init_lr_range
-
- self.reuse_vars = None
- self.reuse_global_state = None
- self.cells = []
- self.init_vectors = []
-
- with tf.variable_scope(opt.OPTIMIZER_SCOPE):
-
- self._initialize_rnn_cells(level_sizes)
-
- # get the cell size for the per-parameter RNN (Level 0)
- cell_size = level_sizes[0]
-
- # Random normal initialization scaled by the output size. This is the
- # scale for the RNN *readouts*. RNN internal weight scale is set in the
- # BiasGRUCell call.
- scale_factor = FLAGS.hrnn_rnn_readout_scale / math.sqrt(cell_size)
- scaled_init = tf.random_normal_initializer(0., scale_factor,
- seed=self.random_seed)
-
- # weights for projecting the hidden state to a parameter update
- self.update_weights = tf.get_variable("update_weights",
- shape=(cell_size, 1),
- initializer=scaled_init)
-
- if self.use_attention:
- # weights for projecting the hidden state to the location at which the
- # gradient is attended
- self.attention_weights = tf.get_variable(
- "attention_weights",
- initializer=self.update_weights.initialized_value())
-
- # weights for projecting the hidden state to the RMS decay term
- self._initialize_scale_decay((cell_size, 1), scaled_init)
- self._initialize_input_decay((cell_size, 1), scaled_init)
-
- self._initialize_lr((cell_size, 1), scaled_init)
-
- state_keys = ["parameter", "layer", "scl_decay", "inp_decay", "true_param"]
-
- if self.dynamic_output_scale:
- state_keys.append("log_learning_rate")
-
- for i in range(self.num_gradient_scales):
- state_keys.append("grad_accum{}".format(i + 1))
- state_keys.append("ms{}".format(i + 1))
-
- super(HierarchicalRNN, self).__init__(
- "hRNN", state_keys, use_attention=use_attention,
- use_log_objective=use_log_objective,
- obj_train_max_multiplier=obj_train_max_multiplier, **kwargs)
-
- def _initialize_rnn_cells(self, level_sizes):
- """Initializes the RNN cells to use in the hierarchical RNN."""
-
- # RNN Cell layers (0 -> lowest, 1 -> middle, 2 -> global)
- for level in range(self.num_layers):
- scope = "Level{}_RNN".format(level)
- with tf.variable_scope(scope):
- hcell = rnn_cells.BiasGRUCell(
- level_sizes[level],
- scale=FLAGS.biasgrucell_scale,
- gate_bias_init=FLAGS.biasgrucell_gate_bias_init,
- random_seed=self.random_seed)
- self.cells.append(hcell)
- if self.learnable_rnn_init:
- self.init_vectors.append(tf.Variable(
- tf.random_uniform([1, hcell.state_size], -1., 1.,
- seed=self.random_seed),
- name="init_vector"))
- else:
- self.init_vectors.append(
- tf.random_uniform([1, hcell.state_size], -1., 1.,
- seed=self.random_seed))
-
- def _initialize_scale_decay(self, weights_tensor_shape, scaled_init):
- """Initializes the scale decay weights and bias variables or tensors.
-
- Args:
- weights_tensor_shape: The shape the weight tensor should take.
- scaled_init: The scaled initialization for the weights tensor.
- """
- if self.learnable_decay:
- self.scl_decay_weights = tf.get_variable("scl_decay_weights",
- shape=weights_tensor_shape,
- initializer=scaled_init)
- scl_decay_bias_init = tf.constant_initializer(
- FLAGS.scale_decay_bias_init)
- self.scl_decay_bias = tf.get_variable("scl_decay_bias",
- shape=(1,),
- initializer=scl_decay_bias_init)
- else:
- self.scl_decay_weights = tf.zeros_like(self.update_weights)
- self.scl_decay_bias = tf.log(0.93 / (1. - 0.93))
-
- def _initialize_input_decay(self, weights_tensor_shape, scaled_init):
- """Initializes the input scale decay weights and bias variables or tensors.
-
- Args:
- weights_tensor_shape: The shape the weight tensor should take.
- scaled_init: The scaled initialization for the weights tensor.
- """
- if (self.learnable_decay and self.num_gradient_scales > 1 and
- self.learnable_inp_decay):
- self.inp_decay_weights = tf.get_variable("inp_decay_weights",
- shape=weights_tensor_shape,
- initializer=scaled_init)
- inp_decay_bias_init = tf.constant_initializer(
- FLAGS.hrnn_default_decay_var_init)
- self.inp_decay_bias = tf.get_variable("inp_decay_bias",
- shape=(1,),
- initializer=inp_decay_bias_init)
- else:
- self.inp_decay_weights = tf.zeros_like(self.update_weights)
- self.inp_decay_bias = tf.log(0.89 / (1. - 0.89))
-
- def _initialize_lr(self, weights_tensor_shape, scaled_init):
- """Initializes the learning rate weights and bias variables or tensors.
-
- Args:
- weights_tensor_shape: The shape the weight tensor should take.
- scaled_init: The scaled initialization for the weights tensor.
- """
- if self.dynamic_output_scale:
- zero_init = tf.constant_initializer(0.)
- wt_init = zero_init if self.zero_init_lr_weights else scaled_init
- self.lr_weights = tf.get_variable("learning_rate_weights",
- shape=weights_tensor_shape,
- initializer=wt_init)
- self.lr_bias = tf.get_variable("learning_rate_bias", shape=(1,),
- initializer=zero_init)
- else:
- self.lr_weights = tf.zeros_like(self.update_weights)
- self.lr_bias = tf.zeros([1, 1])
-
- def _initialize_state(self, var):
- """Return a dictionary mapping names of state variables to their values."""
- var_vectorized = tf.reshape(var, [-1, 1])
- ndim = var_vectorized.get_shape().as_list()[0]
-
- state = {
- # parameter init tensor is [var_ndim x layer0_cell_size]
- "parameter": tf.ones([ndim, 1]) * self.init_vectors[0],
- "scl_decay": tf.zeros_like(var_vectorized),
- "inp_decay": tf.zeros_like(var_vectorized),
- "true_param": var,
- }
-
- if self.num_layers > 1:
- # layer init tensor is [1 x layer1_cell_size]
- state["layer"] = tf.ones([1, 1]) * self.init_vectors[1]
-
- if self.dynamic_output_scale:
- min_lr = self.init_lr_range[0]
- max_lr = self.init_lr_range[1]
- if min_lr == max_lr:
- log_init_lr = tf.log(min_lr * tf.ones_like(var_vectorized))
- else:
- # Use a random offset to increase the likelihood that the average of the
- # LRs for this variable is different from the LRs for other variables.
- actual_vals = tf.random_uniform(var_vectorized.get_shape().as_list(),
- np.log(min_lr) / 2.,
- np.log(max_lr) / 2.,
- seed=self.random_seed)
- offset = tf.random_uniform((), np.log(min_lr) / 2., np.log(max_lr) / 2.,
- seed=self.random_seed)
- log_init_lr = actual_vals + offset
- # Clip the log learning rate to the flag at the top end, and to
- # (log(min int32) - 1) at the bottom
- clipped = tf.clip_by_value(log_init_lr, -33, self.max_log_lr)
- state["log_learning_rate"] = clipped
-
- for i in range(self.num_gradient_scales):
- state["grad_accum{}".format(i + 1)] = tf.zeros_like(var_vectorized)
- state["ms{}".format(i + 1)] = tf.zeros_like(var_vectorized)
-
- return state
-
- def _initialize_global_state(self):
- if self.num_layers < 3:
- return []
- rnn_global_init = tf.ones([1, 1]) * self.init_vectors[2]
- return [rnn_global_init]
-
- def _compute_updates(self, params, grads, states, global_state):
- # Store the updated parameters and states.
- updated_params = []
- updated_attention = []
- updated_states = []
-
- with tf.variable_scope(opt.OPTIMIZER_SCOPE):
-
- mean_log_lr = self._compute_mean_log_lr(states)
-
- # Iterate over the layers.
- for param, grad_unflat, state in zip(params, grads, states):
-
- with tf.variable_scope("PerTensor", reuse=self.reuse_vars):
- self.reuse_vars = True
- grad = tf.reshape(grad_unflat, [-1, 1])
-
- # Create the RNN input. We will optionally extend it with additional
- # features such as curvature and gradient signal vs. noise.
- (grads_scaled, mean_squared_gradients,
- grads_accum) = self._compute_scaled_and_ms_grads(grad, state)
- rnn_input = [g for g in grads_scaled]
-
- self._extend_rnn_input(rnn_input, state, grads_scaled,
- mean_squared_gradients, mean_log_lr)
-
- # Concatenate any features we've collected.
- rnn_input_tensor = tf.concat(rnn_input, 1)
-
- layer_state, new_param_state = self._update_rnn_cells(
- state, global_state, rnn_input_tensor,
- len(rnn_input) != len(grads_scaled))
-
- (scl_decay, inp_decay, new_log_lr, update_step, lr_attend,
- attention_delta) = self._compute_rnn_state_projections(
- state, new_param_state, grads_scaled)
-
- # Apply updates and store state variables.
- if self.use_attention:
- truth = state["true_param"]
- updated_param = truth - update_step
- attention_step = tf.reshape(lr_attend * attention_delta,
- truth.get_shape())
- updated_attention.append(truth - attention_step)
- else:
- updated_param = param - update_step
- updated_attention.append(updated_param)
- updated_params.append(updated_param)
-
- # Collect the new state.
- new_state = {
- "parameter": new_param_state,
- "scl_decay": scl_decay,
- "inp_decay": inp_decay,
- "true_param": updated_param,
- }
- if layer_state is not None:
- new_state["layer"] = layer_state
-
- if self.dynamic_output_scale:
- new_state["log_learning_rate"] = new_log_lr
-
- for i in range(self.num_gradient_scales):
- new_state["grad_accum{}".format(i + 1)] = grads_accum[i]
- new_state["ms{}".format(i + 1)] = mean_squared_gradients[i]
- updated_states.append(new_state)
-
- updated_global_state = self._compute_updated_global_state([layer_state],
- global_state)
-
- return (updated_params, updated_states, [updated_global_state],
- updated_attention)
-
- def _compute_mean_log_lr(self, states):
- """Computes the mean log learning rate across all variables."""
- if self.use_problem_lr_mean and self.use_relative_lr:
-
- sum_log_lr = 0.
- count_log_lr = 0.
- for state in states:
- sum_log_lr += tf.reduce_sum(state["log_learning_rate"])
- # Note: get_shape().num_elements()=num elements in the original tensor.
- count_log_lr += state["log_learning_rate"].get_shape().num_elements()
- return sum_log_lr / count_log_lr
-
- def _compute_scaled_and_ms_grads(self, grad, state):
- """Computes the scaled gradient and the mean squared gradients.
-
- Gradients are also accumulated across different timescales if appropriate.
-
- Args:
- grad: The gradient tensor for this layer.
- state: The optimizer state for this layer.
-
- Returns:
- The scaled gradients, mean squared gradients, and accumulated gradients.
- """
- input_decays = [state["inp_decay"]]
- scale_decays = [state["scl_decay"]]
- if self.use_multiple_scale_decays and self.num_gradient_scales > 1:
- for i in range(self.num_gradient_scales - 1):
- scale_decays.append(tf.sqrt(scale_decays[i]))
-
- for i in range(self.num_gradient_scales - 1):
- # Each accumulator on twice the timescale of the one before.
- input_decays.append(tf.sqrt(input_decays[i]))
- grads_accum = []
- grads_scaled = []
- mean_squared_gradients = []
-
- # populate the scaled gradients and associated mean_squared values
- if self.num_gradient_scales > 0:
- for i, decay in enumerate(input_decays):
- if self.num_gradient_scales == 1:
- # We don't accumulate if no scales, just take the current gradient.
- grad_accum = grad
- else:
- # The state vars are 1-indexed.
- old_accum = state["grad_accum{}".format(i + 1)]
- grad_accum = grad * (1. - decay) + old_accum * decay
-
- grads_accum.append(grad_accum)
-
- sd = scale_decays[i if self.use_multiple_scale_decays else 0]
- grad_scaled, ms = utils.rms_scaling(grad_accum, sd,
- state["ms{}".format(i + 1)],
- update_ms=True)
- grads_scaled.append(grad_scaled)
- mean_squared_gradients.append(ms)
-
- return grads_scaled, mean_squared_gradients, grads_accum
-
- def _extend_rnn_input(self, rnn_input, state, grads_scaled,
- mean_squared_gradients, mean_log_lr):
- """Computes additional rnn inputs and adds them to the rnn_input list."""
- if self.num_gradient_scales > 1 and self.use_grad_products:
- # This gives a measure of curvature relative to input averaging
- # lengthscale and to the learning rate
- grad_products = [a * b for a, b in
- zip(grads_scaled[:-1], grads_scaled[1:])]
- rnn_input.extend([g for g in grad_products])
-
- if self.use_log_means_squared:
- log_means_squared = [tf.log(ms + 1e-16)
- for ms in mean_squared_gradients]
-
- avg = tf.reduce_mean(log_means_squared, axis=0)
- # This gives a measure of the signal vs. noise contribution to the
- # gradient, at the current averaging lengthscale. If all the noise
- # is averaged out, and if updates are small, these will be 0.
- mean_log_means_squared = [m - avg for m in log_means_squared]
-
- rnn_input.extend([m for m in mean_log_means_squared])
-
- if self.use_relative_lr or self.use_extreme_indicator:
- if not self.dynamic_output_scale:
- raise Exception("Relative LR and Extreme Indicator features "
- "require dynamic_output_scale to be set to True.")
- log_lr_vec = tf.reshape(state["log_learning_rate"], [-1, 1])
- if self.use_relative_lr:
- if self.use_problem_lr_mean:
- # Learning rate of this dimension vs. rest of target problem.
- relative_lr = log_lr_vec - mean_log_lr
- else:
- # Learning rate of this dimension vs. rest of tensor.
- relative_lr = log_lr_vec - tf.reduce_mean(log_lr_vec)
- rnn_input.append(relative_lr)
- if self.use_extreme_indicator:
- # Indicator of extremely large or extremely small learning rate.
- extreme_indicator = (tf.nn.relu(log_lr_vec - tf.log(1.)) -
- tf.nn.relu(tf.log(1e-6) - log_lr_vec))
- rnn_input.append(extreme_indicator)
-
- if self.use_lr_shortcut:
- log_lr_vec = tf.reshape(state["log_learning_rate"], [-1, 1])
- rnn_input.append(log_lr_vec - tf.log(1e-3))
-
- def _update_rnn_cells(self, state, global_state, rnn_input_tensor,
- use_additional_features):
- """Updates the component RNN cells with the given state and tensor.
-
- Args:
- state: The current state of the optimizer.
- global_state: The current global RNN state.
- rnn_input_tensor: The input tensor to the RNN.
- use_additional_features: Whether the rnn input tensor contains additional
- features beyond the scaled gradients (affects whether the rnn input
- tensor is used as input to the RNN.)
-
- Returns:
- layer_state: The new state of the per-tensor RNN.
- new_param_state: The new state of the per-parameter RNN.
- """
- # lowest level (per parameter)
- # input -> gradient for this parameter
- # bias -> output from the layer RNN
- with tf.variable_scope("Layer0_RNN"):
- total_bias = None
- if self.num_layers > 1:
- sz = 3 * self.cells[0].state_size # size of the concatenated bias
- param_bias = utils.affine([state["layer"]], sz,
- scope="Param/Affine",
- scale=FLAGS.hrnn_affine_scale,
- random_seed=self.random_seed)
- total_bias = param_bias
- if self.num_layers == 3:
- global_bias = utils.affine(global_state, sz,
- scope="Global/Affine",
- scale=FLAGS.hrnn_affine_scale,
- random_seed=self.random_seed)
- total_bias += global_bias
-
- new_param_state, _ = self.cells[0](
- rnn_input_tensor, state["parameter"], bias=total_bias)
-
- if self.num_layers > 1:
- # middle level (per layer)
- # input -> average hidden state from each parameter in this layer
- # bias -> output from the RNN at the global level
- with tf.variable_scope("Layer1_RNN"):
- if not use_additional_features:
- # Restore old behavior and only add the mean of the new params.
- layer_input = tf.reduce_mean(new_param_state, 0, keep_dims=True)
- else:
- layer_input = tf.reduce_mean(
- tf.concat((new_param_state, rnn_input_tensor), 1), 0,
- keep_dims=True)
- if self.num_layers == 3:
- sz = 3 * self.cells[1].state_size
- layer_bias = utils.affine(global_state, sz,
- scale=FLAGS.hrnn_affine_scale,
- random_seed=self.random_seed)
- layer_state, _ = self.cells[1](
- layer_input, state["layer"], bias=layer_bias)
- else:
- layer_state, _ = self.cells[1](layer_input, state["layer"])
- else:
- layer_state = None
-
- return layer_state, new_param_state
-
- def _compute_rnn_state_projections(self, state, new_param_state,
- grads_scaled):
- """Computes the RNN state-based updates to parameters and update steps."""
- # Compute the update direction (a linear projection of the RNN output).
- update_weights = self.update_weights
-
- update_delta = utils.project(new_param_state, update_weights)
- if self.use_gradient_shortcut:
- # Include an affine projection of just the direction of the gradient
- # so that RNN hidden states are freed up to store more complex
- # functions of the gradient and other parameters.
- grads_scaled_tensor = tf.concat([g for g in grads_scaled], 1)
- update_delta += utils.affine(grads_scaled_tensor, 1,
- scope="GradsToDelta",
- include_bias=False,
- vec_mean=1. / len(grads_scaled),
- random_seed=self.random_seed)
- if self.dynamic_output_scale:
- denom = tf.sqrt(tf.reduce_mean(update_delta ** 2) + 1e-16)
-
- update_delta /= denom
-
- if self.use_attention:
- attention_weights = self.attention_weights
- attention_delta = utils.project(new_param_state,
- attention_weights)
- if self.use_gradient_shortcut:
- attention_delta += utils.affine(grads_scaled_tensor, 1,
- scope="GradsToAttnDelta",
- include_bias=False,
- vec_mean=1. / len(grads_scaled),
- random_seed=self.random_seed)
- if self.dynamic_output_scale:
- attention_delta /= tf.sqrt(
- tf.reduce_mean(attention_delta ** 2) + 1e-16)
- else:
- attention_delta = None
-
- # The updated decay is an affine projection of the hidden state.
- scl_decay = utils.project(new_param_state, self.scl_decay_weights,
- bias=self.scl_decay_bias,
- activation=tf.nn.sigmoid)
- # This is only used if learnable_decay and num_gradient_scales > 1
- inp_decay = utils.project(new_param_state, self.inp_decay_weights,
- bias=self.inp_decay_bias,
- activation=tf.nn.sigmoid)
-
- # Also update the learning rate.
- lr_param, lr_attend, new_log_lr = self._compute_new_learning_rate(
- state, new_param_state)
-
- update_step = tf.reshape(lr_param * update_delta,
- state["true_param"].get_shape())
-
- return (scl_decay, inp_decay, new_log_lr, update_step, lr_attend,
- attention_delta)
-
- def _compute_new_learning_rate(self, state, new_param_state):
- if self.dynamic_output_scale:
- # Compute the change in learning rate (an affine projection of the
- # RNN state, passed through a sigmoid or log depending on flags).
- # Update the learning rate, w/ momentum.
- lr_change = utils.project(new_param_state, self.lr_weights,
- bias=self.lr_bias)
- step_log_lr = state["log_learning_rate"] + lr_change
-
- # Clip the log learning rate to the flag at the top end, and to
- # (log(min int32) - 1) at the bottom
-
- # Check out this hack: we want to be able to compute the gradient
- # of the downstream result w.r.t lr weights and bias, even if the
- # value of step_log_lr is outside the clip range. So we clip,
- # subtract off step_log_lr, and wrap all that in a stop_gradient so
- # TF never tries to take the gradient of the clip... or the
- # subtraction. Then we add BACK step_log_lr so that downstream still
- # receives the clipped value. But the GRADIENT of step_log_lr will
- # be the gradient of the unclipped value, which we added back in
- # after stop_gradients.
- step_log_lr += tf.stop_gradient(
- tf.clip_by_value(step_log_lr, -33, self.max_log_lr)
- - step_log_lr)
-
- lr_momentum_logit = tf.get_variable(
- "learning_rate_momentum_logit",
- initializer=FLAGS.learning_rate_momentum_logit_init)
- lrm = tf.nn.sigmoid(lr_momentum_logit)
- new_log_lr = (lrm * state["log_learning_rate"] +
- (1. - lrm) * step_log_lr)
- param_stepsize_offset = tf.get_variable("param_stepsize_offset",
- initializer=-1.)
- lr_param = tf.exp(step_log_lr + param_stepsize_offset)
- lr_attend = tf.exp(step_log_lr) if self.use_attention else lr_param
- else:
- # Dynamic output scale is off, LR param is always 1.
- lr_param = 2. * utils.project(new_param_state, self.lr_weights,
- bias=self.lr_bias,
- activation=tf.nn.sigmoid)
- new_log_lr = None
- lr_attend = lr_param
-
- return lr_param, lr_attend, new_log_lr
-
- def _compute_updated_global_state(self, layer_states, global_state):
- """Computes the new global state gives the layers states and old state.
-
- Args:
- layer_states: The current layer states.
- global_state: The old global state.
-
- Returns:
- The updated global state.
- """
- updated_global_state = []
- if self.num_layers == 3:
- # highest (global) layer
- # input -> average hidden state from each layer-specific RNN
- # bias -> None
- with tf.variable_scope("Layer2_RNN", reuse=self.reuse_global_state):
- self.reuse_global_state = True
- global_input = tf.reduce_mean(tf.concat(layer_states, 0), 0,
- keep_dims=True)
- updated_global_state, _ = self.cells[2](global_input, global_state[0])
- return updated_global_state
-
- def apply_gradients(self, grads_and_vars, global_step=None, name=None):
- """Overwrites the tf.train.Optimizer interface for applying gradients."""
-
- # Pull out the variables.
- grads_and_vars = tuple(grads_and_vars) # Make sure repeat iteration works.
- for g, v in grads_and_vars:
- if not isinstance(g, (tf.Tensor, tf.IndexedSlices, type(None))):
- raise TypeError(
- "Gradient must be a Tensor, IndexedSlices, or None: %s" % g)
- if not isinstance(v, tf.Variable):
- raise TypeError(
- "Variable must be a tf.Variable: %s" % v)
- if g is not None:
- self._assert_valid_dtypes([g, v])
- var_list = [v for g, v in grads_and_vars if g is not None]
- if not var_list:
- raise ValueError("No gradients provided for any variable: %s" %
- (grads_and_vars,))
-
- # Create slots for the variables.
- with tf.control_dependencies(None):
- self._create_slots(var_list)
-
- # Store update ops in this list.
- with tf.op_scope([], name, self._name) as name:
-
- # Prepare the global state.
- with tf.variable_scope(self._name, reuse=self.reuse_global_state):
- gs = self._initialize_global_state()
- if gs:
- global_state = [tf.get_variable("global_state", initializer=gs[0])]
- else:
- global_state = []
-
- # Get the states for each variable in the list.
- states = [{key: self.get_slot(var, key) for key in self.get_slot_names()}
- for var in var_list]
-
- # Compute updated values.
- grads, params = zip(*grads_and_vars)
- args = (params, grads, states, global_state)
- updates = self._compute_updates(*args)
- new_params, new_states, new_global_state, new_attention = updates
- # Assign op for new global state.
- update_ops = [tf.assign(gs, ngs)
- for gs, ngs in zip(global_state, new_global_state)]
-
- # Create the assign ops for the params and state variables.
- args = (params, states, new_params, new_attention, new_states)
- for var, state, new_var, new_var_attend, new_state in zip(*args):
- # Assign updates to the state variables.
- state_assign_ops = [tf.assign(state_var, new_state[key])
- for key, state_var in state.items()]
-
- # Update the parameter.
- with tf.control_dependencies(state_assign_ops):
- if self.use_attention:
- # Assign to the attended location, rather than the actual location
- # so that the gradients are computed where attention is.
- param_update_op = var.assign(new_var_attend)
- else:
- param_update_op = var.assign(new_var)
-
- with tf.name_scope("update_" + var.op.name): #, tf.colocate_with(var):
- update_ops.append(param_update_op)
-
- real_params = [self.get_slot(var, "true_param") for var in var_list]
-
- if global_step is None:
- # NOTE: if using the optimizer in a non-test-optimizer setting (e.g.
- # on Inception), remove the real_params return value. Otherwise
- # the code will throw an error.
- return self._finish(update_ops, name), real_params
- else:
- with tf.control_dependencies([self._finish(update_ops, "update")]):
- return state_ops.assign_add(global_step, 1, name=name).op, real_params
diff --git a/research/learned_optimizer/optimizer/learning_rate_schedule.py b/research/learned_optimizer/optimizer/learning_rate_schedule.py
deleted file mode 100644
index 53db8addd3d152bfa02630ec6e37f0cc1776abc8..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/optimizer/learning_rate_schedule.py
+++ /dev/null
@@ -1,60 +0,0 @@
-# Copyright 2017 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""A trainable optimizer that learns a learning rate schedule."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-from learned_optimizer.optimizer import trainable_optimizer
-
-
-class LearningRateSchedule(trainable_optimizer.TrainableOptimizer):
- """Learns a learning rate schedule over a fixed number of iterations."""
-
- def __init__(self, initial_rate=0.0, n_steps=1000, **kwargs):
- """Initializes the learning rates."""
- self.max_index = tf.constant(n_steps-1, dtype=tf.int32)
-
- with tf.variable_scope(trainable_optimizer.OPTIMIZER_SCOPE):
- initializer = tf.constant_initializer(initial_rate)
- self.learning_rates = tf.get_variable("learning_rates",
- shape=([n_steps,]),
- initializer=initializer)
-
- super(LearningRateSchedule, self).__init__("LRS", ["itr"], **kwargs)
-
- def _initialize_state(self, var):
- """Return a dictionary mapping names of state variables to their values."""
- return {
- "itr": tf.constant(0, dtype=tf.int32),
- }
-
- def _compute_update(self, param, grad, state):
- """Compute updates of parameters."""
-
- # get the learning rate at the current index, if the index
- # is greater than the number of available learning rates,
- # use the last one
- index = tf.minimum(state["itr"], self.max_index)
- learning_rate = tf.gather(self.learning_rates, index)
-
- # update the parameters: parameter - learning_rate * gradient
- updated_param = param - tf.scalar_mul(learning_rate, grad)
-
- return updated_param, {"itr": state["itr"] + 1}
diff --git a/research/learned_optimizer/optimizer/rnn_cells.py b/research/learned_optimizer/optimizer/rnn_cells.py
deleted file mode 100644
index 3d68de04ca5318bb0f264d4f4647ddbc6fbe08e0..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/optimizer/rnn_cells.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright 2017 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Custom RNN cells for hierarchical RNNs."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-from learned_optimizer.optimizer import utils
-
-
-class BiasGRUCell(tf.contrib.rnn.RNNCell):
- """GRU cell (cf. http://arxiv.org/abs/1406.1078) with an additional bias."""
-
- def __init__(self, num_units, activation=tf.tanh, scale=0.1,
- gate_bias_init=0., random_seed=None):
- self._num_units = num_units
- self._activation = activation
- self._scale = scale
- self._gate_bias_init = gate_bias_init
- self._random_seed = random_seed
-
- @property
- def state_size(self):
- return self._num_units
-
- @property
- def output_size(self):
- return self._num_units
-
- def __call__(self, inputs, state, bias=None):
- # Split the injected bias vector into a bias for the r, u, and c updates.
- if bias is None:
- bias = tf.zeros((1, 3))
-
- r_bias, u_bias, c_bias = tf.split(bias, 3, 1)
-
- with tf.variable_scope(type(self).__name__): # "BiasGRUCell"
- with tf.variable_scope("gates"): # Reset gate and update gate.
- proj = utils.affine([inputs, state], 2 * self._num_units,
- scale=self._scale, bias_init=self._gate_bias_init,
- random_seed=self._random_seed)
- r_lin, u_lin = tf.split(proj, 2, 1)
- r, u = tf.nn.sigmoid(r_lin + r_bias), tf.nn.sigmoid(u_lin + u_bias)
-
- with tf.variable_scope("candidate"):
- proj = utils.affine([inputs, r * state], self._num_units,
- scale=self._scale, random_seed=self._random_seed)
- c = self._activation(proj + c_bias)
-
- new_h = u * state + (1 - u) * c
-
- return new_h, new_h
diff --git a/research/learned_optimizer/optimizer/trainable_adam.py b/research/learned_optimizer/optimizer/trainable_adam.py
deleted file mode 100644
index 638217f1b723da8633dc7a82623392eaaf190829..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/optimizer/trainable_adam.py
+++ /dev/null
@@ -1,210 +0,0 @@
-# Copyright 2017 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""A trainable ADAM optimizer that learns its internal variables."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import tensorflow as tf
-
-from learned_optimizer.optimizer import trainable_optimizer as opt
-from learned_optimizer.optimizer import utils
-
-
-class TrainableAdam(opt.TrainableOptimizer):
- """Adam optimizer with learnable scalar parameters.
-
- See Kingma et. al., 2014 for algorithm (http://arxiv.org/abs/1412.6980).
- """
-
- def __init__(self,
- learning_rate=1e-3,
- beta1=0.9,
- beta2=0.999,
- epsilon=1e-8,
- **kwargs):
- """Initializes the TrainableAdam optimizer with the given initial values.
-
- Args:
- learning_rate: The learning rate (default: 1e-3).
- beta1: The exponential decay rate for the 1st moment estimates.
- beta2: The exponential decay rate for the 2nd moment estimates.
- epsilon: A small constant for numerical stability.
- **kwargs: Any additional keyword arguments for TrainableOptimizer.
-
- Raises:
- ValueError: if the learning rate or epsilon is not positive
- ValueError: if beta1 or beta2 is not in (0, 1).
- """
- if learning_rate <= 0:
- raise ValueError("Learning rate must be positive.")
- if epsilon <= 0:
- raise ValueError("Epsilon must be positive.")
- if not 0 < beta1 < 1 or not 0 < beta2 < 1:
- raise ValueError("Beta values must be between 0 and 1, exclusive.")
-
- self._reuse_vars = False
-
- with tf.variable_scope(opt.OPTIMIZER_SCOPE):
- def inv_sigmoid(x):
- return np.log(x / (1.0 - x))
-
- self.log_learning_rate = tf.get_variable(
- "log_learning_rate",
- shape=[],
- initializer=tf.constant_initializer(np.log(learning_rate)))
- self.beta1_logit = tf.get_variable(
- "beta1_logit",
- shape=[],
- initializer=tf.constant_initializer(inv_sigmoid(beta1)))
- self.beta2_logit = tf.get_variable(
- "beta2_logit",
- shape=[],
- initializer=tf.constant_initializer(inv_sigmoid(beta2)))
- self.log_epsilon = tf.get_variable(
- "log_epsilon",
- shape=[],
- initializer=tf.constant_initializer(np.log(epsilon)))
-
- # Key names are derived from Algorithm 1 described in
- # https://arxiv.org/pdf/1412.6980.pdf
- state_keys = ["m", "v", "t"]
- super(TrainableAdam, self).__init__("Adam", state_keys, **kwargs)
-
- def _initialize_state(self, var):
- """Returns a dictionary mapping names of state variables to their values."""
- vectorized_shape = var.get_shape().num_elements(), 1
-
- return {key: tf.zeros(vectorized_shape) for key in self.state_keys}
-
- def _compute_update(self, param, grad, state):
- """Calculates the new internal state and parameters.
-
- If the gradient is sparse, updates the appropriate slices in the internal
- state and stacks the update tensor.
-
- Args:
- param: A tensor of parameters.
- grad: A tensor of gradients with the same shape as param.
- state: A dictionary containing any state for the optimizer.
-
- Returns:
- updated_param: The updated parameters.
- updated_state: The updated state variables in a dictionary.
- """
-
- with tf.variable_scope(opt.OPTIMIZER_SCOPE) as scope:
-
- if self._reuse_vars:
- scope.reuse_variables()
- else:
- self._reuse_vars = True
-
- (grad_values, first_moment, second_moment, timestep, grad_indices
- ) = self._extract_gradients_and_internal_state(
- grad, state, tf.shape(param))
-
- beta1 = tf.nn.sigmoid(self.beta1_logit)
- beta2 = tf.nn.sigmoid(self.beta2_logit)
- epsilon = tf.exp(self.log_epsilon) + 1e-10
- learning_rate = tf.exp(self.log_learning_rate)
-
- old_grad_shape = tf.shape(grad_values)
- grad_values = tf.reshape(grad_values, [-1, 1])
-
- new_timestep = timestep + 1
- new_first_moment = self._update_adam_estimate(
- first_moment, grad_values, beta1)
- new_second_moment = self._debias_adam_estimate(
- second_moment, tf.square(grad_values), beta2)
-
- debiased_first_moment = self._debias_adam_estimate(
- new_first_moment, beta1, new_timestep)
- debiased_second_moment = self._debias_adam_estimate(
- new_second_moment, beta2, new_timestep)
-
- # Propagating through the square root of 0 is very bad for stability.
- update = (learning_rate * debiased_first_moment /
- (tf.sqrt(debiased_second_moment + 1e-10) + epsilon))
-
- update = tf.reshape(update, old_grad_shape)
-
- if grad_indices is not None:
- param_shape = tf.shape(param)
- update = utils.stack_tensor(
- update, grad_indices, param, param_shape[:1])
- new_first_moment = utils.update_slices(
- new_first_moment, grad_indices, state["m"], param_shape)
- new_second_moment = utils.update_slices(
- new_second_moment, grad_indices, state["v"], param_shape)
- new_timestep = utils.update_slices(
- new_timestep, grad_indices, state["t"], param_shape)
-
- new_param = param - update
-
- # collect the update and new state
- new_state = {
- "m": new_first_moment,
- "v": new_second_moment,
- "t": new_timestep
- }
-
- return new_param, new_state
-
- def _update_adam_estimate(self, estimate, value, beta):
- """Returns a beta-weighted average of estimate and value."""
- return (beta * estimate) + ((1 - beta) * value)
-
- def _debias_adam_estimate(self, estimate, beta, t_step):
- """Returns a debiased estimate based on beta and the timestep."""
- return estimate / (1 - tf.pow(beta, t_step))
-
- def _extract_gradients_and_internal_state(self, grad, state, param_shape):
- """Extracts the gradients and relevant internal state.
-
- If the gradient is sparse, extracts the appropriate slices from the state.
-
- Args:
- grad: The current gradient.
- state: The current state.
- param_shape: The shape of the parameter (used if gradient is sparse).
-
- Returns:
- grad_values: The gradient value tensor.
- first_moment: The first moment tensor (internal state).
- second_moment: The second moment tensor (internal state).
- timestep: The current timestep (internal state).
- grad_indices: The indices for the gradient tensor, if sparse.
- None otherwise.
- """
- grad_values = grad
- grad_indices = None
- first_moment = state["m"]
- second_moment = state["v"]
- timestep = state["t"]
-
- if isinstance(grad, tf.IndexedSlices):
- grad_indices, grad_values = utils.accumulate_sparse_gradients(grad)
- first_moment = utils.slice_tensor(
- first_moment, grad_indices, param_shape)
- second_moment = utils.slice_tensor(
- second_moment, grad_indices, param_shape)
- timestep = utils.slice_tensor(timestep, grad_indices, param_shape)
-
- return grad_values, first_moment, second_moment, timestep, grad_indices
-
diff --git a/research/learned_optimizer/optimizer/trainable_optimizer.py b/research/learned_optimizer/optimizer/trainable_optimizer.py
deleted file mode 100644
index 955112a9dd1d3b0af5ae2f5f0fe8eff65d2dbfc7..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/optimizer/trainable_optimizer.py
+++ /dev/null
@@ -1,574 +0,0 @@
-# Copyright 2017 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""A base class definition for trainable optimizers."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-import itertools
-
-import tensorflow as tf
-
-from tensorflow.python.framework import tensor_shape
-
-OPTIMIZER_SCOPE = "LOL"
-_LOCAL_VARIABLE_PREFIX = "local_state_"
-_LOCAL_STATE_VARIABLE_COLLECTION = "local_state_collection"
-EPSILON = 1e-6
-
-
-class TrainableOptimizer(tf.train.Optimizer):
- """Base class for trainable optimizers.
-
- A trainable optimizer is an optimizer that has parameters that can themselves
- be learned (meta-optimized).
-
- Subclasses must implement:
- _compute_update(self, param, grad, state)
- """
-
- def __init__(self, name, state_keys, use_attention=False,
- use_log_objective=False, obj_train_max_multiplier=-1,
- use_second_derivatives=True, use_numerator_epsilon=False,
- **kwargs):
- """Initializes the optimizer with the given name and settings.
-
- Args:
- name: The name string for this optimizer.
- state_keys: The names of any required state variables (list)
- use_attention: Whether this optimizer uses attention (Default: True)
- use_log_objective: Whether this optimizer uses the logarithm of the
- objective when computing the loss (Default: False)
- obj_train_max_multiplier: The maximum multiplier for the increase in the
- objective before meta-training is stopped. If <= 0, meta-training is
- not stopped early. (Default: -1)
- use_second_derivatives: Whether this optimizer uses second derivatives in
- meta-training. This should be set to False if some second derivatives
- in the meta-training problem set are not defined in Tensorflow.
- (Default: True)
- use_numerator_epsilon: Whether to use epsilon in the numerator when
- scaling the problem objective during meta-training. (Default: False)
- **kwargs: Any additional keyword arguments.
- """
- self.use_second_derivatives = use_second_derivatives
- self.state_keys = sorted(state_keys)
- self.use_attention = use_attention
- self.use_log_objective = use_log_objective
- self.obj_train_max_multiplier = obj_train_max_multiplier
- self.use_numerator_epsilon = use_numerator_epsilon
-
- use_locking = False
- super(TrainableOptimizer, self).__init__(use_locking, name)
-
- def _create_slots(self, var_list):
- """Creates all slots needed by the variables.
-
- Args:
- var_list: A list of `Variable` objects.
- """
- for var in var_list:
- init_states = self._initialize_state(var)
- for slot_name in sorted(init_states):
- slot_var_name = "{}_{}".format(self.get_name(), slot_name)
- value = init_states[slot_name]
- self._get_or_make_slot(var, value, slot_name, slot_var_name)
-
- def _initialize_state(self, var):
- """Initializes any state required for this variable.
-
- Args:
- var: a tensor containing parameters to be optimized
-
- Returns:
- state: a dictionary mapping state keys to initial state values (tensors)
- """
- return {}
-
- def _initialize_global_state(self):
- """Initializes any global state values."""
- return []
-
- def _apply_common(self, grad, var):
- """Applies the optimizer updates to the variables.
-
- Note: this should only get called via _apply_dense or _apply_sparse when
- using the optimizer via optimizer.minimize or optimizer.apply_gradients.
- During meta-training, the optimizer.train function should be used to
- construct an optimization path that is differentiable.
-
- Args:
- grad: A tensor representing the gradient.
- var: A tf.Variable with the same shape as grad.
-
- Returns:
- update_op: A tensorflow op that assigns new values to the variable, and
- also defines dependencies that update the state variables for the
- optimizer.
- """
- state = {key: self.get_slot(var, key) for key in self.get_slot_names()}
- new_var, new_state = self._compute_update(var, grad, state)
- state_assign_ops = [tf.assign(state_var, new_state[key])
- for key, state_var in state.items()]
- with tf.control_dependencies(state_assign_ops):
- update_op = var.assign(new_var)
-
- return update_op
-
- def _apply_dense(self, grad, var):
- """Adds ops to apply dense gradients to 'var'."""
- return self._apply_common(grad, var)
-
- def _apply_sparse(self, grad, var):
- """Adds ops to apply sparse gradients to 'var'."""
- return self._apply_common(grad, var)
-
- def _compute_update(self, param, grad, state):
- """Computes the update step for optimization.
-
- Args:
- param: A tensor of parameters to optimize.
- grad: The gradient tensor of the objective with respect to the parameters.
- (It has the same shape as param.)
- state: A dictionary containing any extra state required by the optimizer.
-
- Returns:
- updated_params: The updated parameters.
- updated_state: The dictionary of updated state variable(s).
- """
- raise NotImplementedError
-
- def _compute_updates(self, params, grads, states, global_state):
- """Maps the compute update functions for each parameter.
-
- This function can be overriden by a subclass if the subclass wants to
- combine information across the different parameters in the list.
-
- Args:
- params: A list of parameter tensors.
- grads: A list of gradients corresponding to each parameter.
- states: A list of state variables corresponding to each parameter.
- global_state: A list of global state variables for the problem.
-
- Returns:
- new_params: The updated parameters.
- new_states: The updated states.
- new_global_state: The updated global state.
- attention_params: A list of attention parameters. This is the same as
- new_params if the optimizer does not use attention.
- """
- # Zip up the arguments to _compute_update.
- args = zip(params, grads, states)
-
- # Call compute_update on each set of parameter/gradient/state args.
- new_params, new_states = zip(*list(
- itertools.starmap(self._compute_update, args)))
-
- # Global state is unused in the basic case, just pass it through.
- return list(new_params), list(new_states), global_state, list(new_params)
-
- def train(self, problem, dataset):
- """Creates graph operations to train the optimizer.
-
- Args:
- problem: A problem_generator.Problem instance to train on.
- dataset: A datasets.Dataset tuple to use when training.
-
- Returns:
- meta_objective: A tensorflow operation for computing the meta-objective
- obj_weights: A tensor placeholder for feeding in the objective weights
- obj_values: The subproblem objective values during optimization
- batches: The batch indexes tensor for overriding with feed_dict
- first_unroll: A placeholder signifying if this is a first unroll
- (this will propagate the gradients slightly differently).
- reset_state: A placeholder signifying that the rnn state should be reset.
- output_state: The final state of the optimizer
- init_loop_vars_to_override: Local variables that can be assigned to
- propagate the optimizer and problem state for unrolling
- final_loop_vals: Final values of the loop variables that can be
- assigned to init_loop_vars_to_override.
- """
-
- # Placeholder for the objective weights
- obj_weights = tf.placeholder(tf.float32)
- num_iter = tf.shape(obj_weights)[0]
-
- # Unpack the dataset and generate the minibatches for training
- data, labels = dataset
- # Convert the ndarrays to tensors so we can pass them back in via feed_dict
- data = tf.constant(data)
- labels = tf.constant(labels)
- batches = tf.placeholder(tf.int32)
- first_unroll = tf.placeholder_with_default(False, [])
- reset_state = tf.placeholder_with_default(False, [])
-
- training_output = collections.namedtuple("TrainingOutput",
- ["metaobj",
- "obj_weights",
- "problem_objectives",
- "initial_obj",
- "batches",
- "first_unroll",
- "reset_state",
- "output_state",
- "init_loop_vars",
- "output_loop_vars"])
-
- def loop_body(itr, obj_accum, params, attend_params, flattened_states,
- global_state, all_obj, unused_init_obj, data,
- labels, batches):
- """Body of the meta-training while loop for optimizing a sub-problem.
-
- Args:
- itr: The current meta-training iteration.
- obj_accum: The accumulated objective over all training steps so far.
- params: The parameters of the sub-problem.
- attend_params: The parameters of the sub-problems at the attended
- location.
- flattened_states: The states of the trainable optimizer, sorted and
- flattened into a list (since a while loop can't handle nested lists
- or dictionaries).
- global_state: The global state of the optimizer.
- all_obj: The list of all objective values in the training process.
- unused_init_obj: The initial objective (unused here, but needed in the
- variable list because it's used in a stopping condition in the
- loop_cond.)
- data: The data for this problem.
- labels: The labels corresponding to the data.
- batches: The batch indexes needed for shuffled minibatch creation.
-
- Returns:
- itr: The updated meta-training iteration.
- obj_accum: The updated accumulated objective.
- params: The new parameters of the sub-problem.
- attend_params: The new parameters of the sub-problems at the attended
- location.
- flattened_states: The new states of the trainable optimizer.
- global_state: The updated global state.
- all_obj: The updates list of all objective values.
- unused_init_obj: The initial objective.
- data: The data for this problem.
- labels: The labels corresponding to the data.
- batches: The batch indexes needed for shuffled minibatch creation.
- """
- batch_indices = tf.gather(batches, itr)
- batch_data = tf.gather(data, batch_indices)
- batch_labels = tf.gather(labels, batch_indices)
-
- # Compute the objective over the entire dataset (full batch).
- obj = problem.objective(params, data, labels)
-
- # Compute the gradients on just the current batch
- if self.use_attention:
- current_obj = problem.objective(attend_params, batch_data, batch_labels)
- grads = problem.gradients(current_obj, attend_params)
- else:
- current_obj = problem.objective(params, batch_data, batch_labels)
- grads = problem.gradients(current_obj, params)
-
- if not self.use_second_derivatives:
- new_grads = []
- for grad in grads:
- if isinstance(grad, tf.IndexedSlices):
- new_grads.append(
- tf.IndexedSlices(tf.stop_gradient(grad.values), grad.indices))
- else:
- new_grads.append(tf.stop_gradient(grad))
- grads = new_grads
-
- # store the objective value for the entire problem at each iteration
- all_obj = tf.concat([all_obj, tf.reshape(obj, (1,))], 0)
-
- # accumulate the weighted objective for the entire dataset
- acc = tf.gather(obj_weights, itr) * obj
-
- obj_accum = tf.add(obj_accum, acc)
- # Set the shape to keep the shape invariant for obj_accum. Without this,
- # the graph builder thinks the tensor shape is unknown on the 2nd iter.
- obj_accum.set_shape([])
-
- # convert flattened_states to dictionaries
- dict_states = [dict(zip(self.state_keys, flat_state))
- for flat_state in flattened_states]
-
- # compute the new parameters and states
- args = (params, grads, dict_states, global_state)
- updates = self._compute_updates(*args)
- new_params, new_states, new_global_state, new_attend_params = updates
-
- # flatten the states
- new_flattened_states = map(flatten_and_sort, new_states)
-
- return [itr + 1, obj_accum, new_params, new_attend_params,
- new_flattened_states, new_global_state, all_obj, unused_init_obj,
- data, labels, batches]
-
- def loop_cond(itr, obj_accum, unused_params, unused_attend_params,
- unused_flattened_states, unused_global_state, all_obj,
- init_obj, *args):
- """Termination conditions of the sub-problem optimization loop."""
- del args # unused
-
- cond1 = tf.less(itr, num_iter) # We've run < num_iter times
- cond2 = tf.is_finite(obj_accum) # The objective is still finite
-
- if self.obj_train_max_multiplier > 0:
- current_obj = tf.gather(all_obj, itr)
- # Account for negative init_obj too
- max_diff = (self.obj_train_max_multiplier - 1) * tf.abs(init_obj)
- max_obj = init_obj + max_diff
- # The objective is a reasonable multiplier of the original objective
- cond3 = tf.less(current_obj, max_obj)
-
- return tf.logical_and(tf.logical_and(cond1, cond2), cond3,
- name="training_loop_cond")
- else:
- return tf.logical_and(cond1, cond2, name="training_loop_cond")
-
- init = self._initialize_training_loop_parameters(
- problem, data, labels, batches, first_unroll, reset_state)
- loop_vars, invariants, initial_obj, init_loop_vars_to_override = init
-
- loop_output = tf.while_loop(loop_cond, loop_body, loop_vars,
- swap_memory=True, shape_invariants=invariants)
- meta_obj, problem_objectives = loop_output[1], loop_output[6]
-
- # The meta objective is normalized by the initial objective at the start of
- # the series of partial unrolls.
- scaled_meta_objective = self.scale_objective(
- meta_obj, problem_objectives, initial_obj)
-
- final_loop_vals = (
- [initial_obj] + loop_output[2] + loop_output[3] + loop_output[5])
- final_loop_vals.extend(itertools.chain(*loop_output[4]))
-
- return training_output(scaled_meta_objective,
- obj_weights,
- problem_objectives,
- initial_obj,
- batches,
- first_unroll,
- reset_state,
- loop_output[4],
- init_loop_vars_to_override,
- final_loop_vals)
-
- def _initialize_training_loop_parameters(
- self, problem, data, labels, batches, first_unroll, reset_state):
- """Initializes the vars and params needed for the training process.
-
- Args:
- problem: The problem being optimized.
- data: The data for the problem.
- labels: The corresponding labels for the data.
- batches: The indexes needed to create shuffled batches of the data.
- first_unroll: Whether this is the first unroll in a partial unrolling.
- reset_state: Whether RNN state variables should be reset.
-
- Returns:
- loop_vars: The while loop variables for training.
- invariants: The corresponding variable shapes (required by while loop).
- initial_obj: The initial objective (used later for scaling).
- init_loop_vars_to_override: The loop vars that can be overridden when
- performing training via partial unrolls.
- """
- # Extract these separately so we don't have to make inter-variable
- # dependencies.
- initial_tensors = problem.init_tensors()
-
- return_initial_tensor_values = first_unroll
- initial_params_vars, initial_params = local_state_variables(
- initial_tensors, return_initial_tensor_values)
- initial_attend_params_vars, initial_attend_params = local_state_variables(
- initial_tensors, return_initial_tensor_values)
- # Recalculate the initial objective for the list on each partial unroll with
- # the new initial_params. initial_obj holds the value from the very first
- # unroll.
- initial_obj_init = problem.objective(initial_params, data, labels)
- return_initial_obj_init = first_unroll
- [initial_obj_var], [initial_obj] = local_state_variables(
- [initial_obj_init], return_initial_obj_init)
-
- # Initialize the loop variables.
- initial_itr = tf.constant(0, dtype=tf.int32)
- initial_meta_obj = tf.constant(0, dtype=tf.float32)
- # N.B. the use of initial_obj_init here rather than initial_obj
- initial_problem_objectives = tf.reshape(initial_obj_init, (1,))
-
- # Initialize the extra state.
- initial_state_vars = []
- initial_state = []
- state_shapes = []
- return_initial_state_values = reset_state
- for param in initial_tensors:
- param_state_vars, param_state = local_state_variables(
- flatten_and_sort(self._initialize_state(param)),
- return_initial_state_values)
-
- initial_state_vars.append(param_state_vars)
- initial_state.append(param_state)
- state_shapes.append([f.get_shape() for f in param_state])
-
- # Initialize any global (problem-level) state.
- initial_global_state_vars, initial_global_state = local_state_variables(
- self._initialize_global_state(), return_initial_state_values)
-
- global_shapes = []
- for item in initial_global_state:
- global_shapes.append(item.get_shape())
-
- # build the list of loop variables:
- loop_vars = [
- initial_itr,
- initial_meta_obj,
- initial_params, # Local variables.
- initial_attend_params, # Local variables.
- initial_state, # Local variables.
- initial_global_state, # Local variables.
- initial_problem_objectives,
- initial_obj, # Local variable.
- data,
- labels,
- batches,
- ]
-
- invariants = [
- initial_itr.get_shape(),
- initial_meta_obj.get_shape(),
- [t.get_shape() for t in initial_params],
- [t.get_shape() for t in initial_attend_params],
- state_shapes,
- global_shapes,
- tensor_shape.TensorShape([None]), # The problem objectives list grows
- initial_obj.get_shape(),
- tensor_shape.unknown_shape(), # Placeholder shapes are unknown
- tensor_shape.unknown_shape(),
- tensor_shape.unknown_shape(),
- ]
-
- # Initialize local variables that we will override with final tensors at the
- # next iter.
- init_loop_vars_to_override = (
- [initial_obj_var] + initial_params_vars + initial_attend_params_vars +
- initial_global_state_vars)
- init_loop_vars_to_override.extend(itertools.chain(*initial_state_vars))
-
- return loop_vars, invariants, initial_obj, init_loop_vars_to_override
-
- def scale_objective(self, total_obj, all_objs, initial_obj,
- obj_scale_eps=1e-6):
- """Normalizes the objective based on the initial objective value.
-
- Args:
- total_obj: The total accumulated objective over the training run.
- all_objs: A list of all the individual objectives over the training run.
- initial_obj: The initial objective value.
- obj_scale_eps: The epsilon value to use in computations for stability.
-
- Returns:
- The scaled objective as a single value.
- """
- if self.use_log_objective:
- if self.use_numerator_epsilon:
- scaled_problem_obj = ((all_objs + obj_scale_eps) /
- (initial_obj + obj_scale_eps))
- log_scaled_problem_obj = tf.log(scaled_problem_obj)
- else:
- scaled_problem_obj = all_objs / (initial_obj + obj_scale_eps)
- log_scaled_problem_obj = tf.log(scaled_problem_obj + obj_scale_eps)
- return tf.reduce_mean(log_scaled_problem_obj)
- else:
- return total_obj / (initial_obj + obj_scale_eps)
-
-
-def local_state_variables(init_values, return_init_values):
- """Create local variables initialized from init_values.
-
- This will create local variables from a list of init_values. Each variable
- will be named based on the value's shape and dtype.
-
- As a convenience, a boolean tensor allows you to return value from
- the created local variable or from the original init value.
-
- Args:
- init_values: iterable of tensors
- return_init_values: boolean tensor
-
- Returns:
- local_vars: list of the created local variables.
- vals: if return_init_values is true, then this returns the values of
- init_values. Otherwise it returns the values of the local_vars.
- """
- if not init_values:
- return [], []
-
- # This generates a harmless warning when saving the metagraph.
- variable_use_count = tf.get_collection_ref(_LOCAL_STATE_VARIABLE_COLLECTION)
- if not variable_use_count:
- variable_use_count.append(collections.defaultdict(int))
- variable_use_count = variable_use_count[0]
-
- local_vars = []
- with tf.variable_scope(OPTIMIZER_SCOPE):
- # We can't use the init_value as an initializer as init_value may
- # itself depend on some problem variables. This would produce
- # inter-variable initialization order dependence which TensorFlow
- # sucks at making easy.
- for init_value in init_values:
- name = create_local_state_variable_name(init_value)
- unique_name = name + "_" + str(variable_use_count[name])
- variable_use_count[name] += 1
- # The overarching idea here is to be able to reuse variables between
- # different sessions on the same TensorFlow master without errors. By
- # uniquifying based on the type and name we mirror the checks made inside
- # TensorFlow, while still allowing some memory reuse. Ultimately this is a
- # hack due to the broken Session.reset().
- local_vars.append(
- tf.get_local_variable(
- unique_name,
- initializer=tf.zeros(
- init_value.get_shape(), dtype=init_value.dtype)))
-
- # It makes things a lot simpler if we use the init_value the first
- # iteration, instead of the variable itself. It allows us to propagate
- # gradients through it as well as simplifying initialization. The variable
- # ends up assigned to after the first iteration.
- vals = tf.cond(return_init_values, lambda: init_values, lambda: local_vars)
- if len(init_values) == 1:
- # tf.cond extracts elements from singleton lists.
- vals = [vals]
- return local_vars, vals
-
-
-def create_local_state_variable_name(tensor):
- """Create a name of the variable based on its type and shape."""
- if not tensor.get_shape().is_fully_defined():
- raise ValueError("Need a fully specified shape to create a local variable.")
-
- return (_LOCAL_VARIABLE_PREFIX + "_".join(
- map(str, tensor.get_shape().as_list())) + "_" + tensor.dtype.name)
-
-
-def is_local_state_variable(op):
- """Returns if this op is a local state variable created for training."""
- return op.node_def.op in ["Variable", "VariableV2"] and op.name.startswith(
- OPTIMIZER_SCOPE + "/" + _LOCAL_VARIABLE_PREFIX)
-
-
-def flatten_and_sort(dictionary):
- """Flattens a dictionary into a list of values sorted by the keys."""
- return [dictionary[k] for k in sorted(dictionary.keys())]
diff --git a/research/learned_optimizer/optimizer/utils.py b/research/learned_optimizer/optimizer/utils.py
deleted file mode 100644
index 58744f4cb7919a84ecc8702ff1236e4c0a03f218..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/optimizer/utils.py
+++ /dev/null
@@ -1,278 +0,0 @@
-# Copyright 2017 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Utilities and helper functions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import tensorflow as tf
-
-
-def make_finite(t, replacement):
- """Replaces non-finite tensor values with the replacement value."""
- return tf.where(tf.is_finite(t), t, replacement)
-
-
-def asinh(x):
- """Computes the inverse hyperbolic sine function (in tensorflow)."""
- return tf.log(x + tf.sqrt(1. + x ** 2))
-
-
-def affine(inputs, output_size, scope="Affine", scale=0.1, vec_mean=0.,
- include_bias=True, bias_init=0., random_seed=None):
- """Computes an affine function of the inputs.
-
- Creates or recalls tensorflow variables "Matrix" and "Bias"
- to generate an affine operation on the input.
-
- If the inputs are a list of tensors, they are concatenated together.
-
- Initial weights for the matrix are drawn from a Gaussian with zero
- mean and standard deviation that is the given scale divided by the
- square root of the input dimension. Initial weights for the bias are
- set to zero.
-
- Args:
- inputs: List of tensors with shape (batch_size, input_size)
- output_size: Size (dimension) of the output
- scope: Variable scope for these parameters (default: "Affine")
- scale: Initial weight scale for the matrix parameters (default: 0.1),
- this constant is divided by the sqrt of the input size to get the
- std. deviation of the initial weights
- vec_mean: The mean for the random initializer
- include_bias: Whether to include the bias term
- bias_init: The initializer bias (default 0.)
- random_seed: Random seed for random initializers. (Default: None)
-
- Returns:
- output: Tensor with shape (batch_size, output_size)
- """
-
- # Concatenate the input arguments.
- x = tf.concat(inputs, 1)
-
- with tf.variable_scope(scope):
- input_size = x.get_shape().as_list()[1]
-
- sigma = scale / np.sqrt(input_size)
- rand_init = tf.random_normal_initializer(mean=vec_mean, stddev=sigma,
- seed=random_seed)
-
- matrix = tf.get_variable("Matrix", [input_size, output_size],
- dtype=tf.float32, initializer=rand_init)
-
- if include_bias:
- bias = tf.get_variable("Bias", [output_size], dtype=tf.float32,
- initializer=tf.constant_initializer(bias_init,
- tf.float32))
- else:
- bias = 0.
- output = tf.matmul(x, matrix) + bias
-
- return output
-
-
-def project(inputs, weights, bias=0., activation=tf.identity):
- """Computes an affine or linear projection of the inputs.
-
- Projects the inputs onto the given weight vector and (optionally)
- adds a bias and passes the result through an activation function.
-
- Args:
- inputs: matrix of inputs with shape [batch_size, dim]
- weights: weight matrix with shape [dim, output_dim]
- bias: bias vector with shape [output_dim] (default: 0)
- activation: nonlinear activation function (default: tf.identity)
-
- Returns:
- outputs: an op which computes activation(inputs @ weights + bias)
- """
- return activation(tf.matmul(inputs, weights) + bias)
-
-
-def new_mean_squared(grad_vec, decay, ms):
- """Calculates the new accumulated mean squared of the gradient.
-
- Args:
- grad_vec: the vector for the current gradient
- decay: the decay term
- ms: the previous mean_squared value
-
- Returns:
- the new mean_squared value
- """
- decay_size = decay.get_shape().num_elements()
- decay_check_ops = [
- tf.assert_less_equal(decay, 1., summarize=decay_size),
- tf.assert_greater_equal(decay, 0., summarize=decay_size)]
-
- with tf.control_dependencies(decay_check_ops):
- grad_squared = tf.square(grad_vec)
-
- # If the previous mean_squared is the 0 vector, don't use the decay and just
- # return the full grad_squared. This should only happen on the first timestep.
- decay = tf.cond(tf.reduce_all(tf.equal(ms, 0.)),
- lambda: tf.zeros_like(decay, dtype=tf.float32), lambda: decay)
-
- # Update the running average of squared gradients.
- epsilon = 1e-12
- return (1. - decay) * (grad_squared + epsilon) + decay * ms
-
-
-def rms_scaling(gradient, decay, ms, update_ms=True):
- """Vectorizes and scales a tensor of gradients.
-
- Args:
- gradient: the current gradient
- decay: the current decay value.
- ms: the previous mean squared value
- update_ms: Whether to update the mean squared value (default: True)
-
- Returns:
- The scaled gradient and the new ms value if update_ms is True,
- the old ms value otherwise.
- """
-
- # Vectorize the gradients and compute the squared gradients.
- grad_vec = tf.reshape(gradient, [-1, 1])
-
- if update_ms:
- ms = new_mean_squared(grad_vec, decay, ms)
-
- # Scale the current gradients by the RMS, squashed by the asinh function.
- scaled_gradient = asinh(grad_vec / tf.sqrt(ms + 1e-16))
-
- return scaled_gradient, ms
-
-
-def accumulate_sparse_gradients(grad):
- """Accumulates repeated indices of a sparse gradient update.
-
- Args:
- grad: a tf.IndexedSlices gradient
-
- Returns:
- grad_indices: unique indices
- grad_values: gradient values corresponding to the indices
- """
-
- grad_indices, grad_segments = tf.unique(grad.indices)
- grad_values = tf.unsorted_segment_sum(grad.values, grad_segments,
- tf.shape(grad_indices)[0])
- return grad_indices, grad_values
-
-
-def slice_tensor(dense_tensor, indices, head_dims):
- """Extracts slices from a partially flattened dense tensor.
-
- indices is assumed to index into the first dimension of head_dims.
- dense_tensor is assumed to have a shape [D_0, D_1, ...] such that
- prod(head_dims) == D_0. This function will extract slices along the
- first_dimension of head_dims.
-
- Example:
-
- Consider a tensor with shape head_dims = [100, 2] and a dense_tensor with
- shape [200, 3]. Note that the first dimension of dense_tensor equals the
- product of head_dims. This function will reshape dense_tensor such that
- its shape is now [100, 2, 3] (i.e. the first dimension became head-dims)
- and then slice it along the first dimension. After slicing, the slices will
- have their initial dimensions flattened just as they were in dense_tensor
- (e.g. if there are 4 indices, the return value will have a shape of [4, 3]).
-
- Args:
- dense_tensor: a N-D dense tensor. Shape: [D_0, D_1, ...]
- indices: a 1-D integer tensor. Shape: [K]
- head_dims: True dimensions of the dense_tensor's first dimension.
-
- Returns:
- Extracted slices. Shape [K, D_1, ...]
- """
-
- tail_dims = tf.shape(dense_tensor)[1:]
- dense_tensor = tf.reshape(dense_tensor,
- tf.concat([head_dims, tail_dims], 0))
-
- slices = tf.gather(dense_tensor, indices)
- # NOTE(siege): This kills the shape annotation.
- return tf.reshape(slices, tf.concat([[-1], tail_dims], 0))
-
-
-def stack_tensor(slices, indices, dense_tensor, head_dims):
- """Reconsititutes a tensor from slices and corresponding indices.
-
- This is an inverse operation to slice_tensor. Missing slices are set to 0.
-
- Args:
- slices: a tensor. Shape [K, D_1, ...]
- indices: a 1-D integer tensor. Shape: [K]
- dense_tensor: the original tensor the slices were taken
- from. Shape: [D_0, D_1, ...]
- head_dims: True dimensions of the dense_tensor's first dimension.
-
- Returns:
- Reconsituted tensor. Shape: [D_0, D_1, ...]
- """
- # NOTE(siege): This cast shouldn't be necessary.
- indices = tf.cast(indices, tf.int32)
-
- tail_dims = tf.shape(dense_tensor)[1:]
- dense_shape = tf.concat([head_dims, tail_dims], 0)
-
- slices = tf.reshape(slices, tf.concat([[-1], dense_shape[1:]], 0))
- indices = tf.expand_dims(indices, -1)
-
- return tf.reshape(tf.scatter_nd(indices, slices, dense_shape),
- tf.shape(dense_tensor))
-
-
-def update_slices(slices, indices, dense_tensor, head_dims):
- """Reconstitutes a tensor from slices and corresponding indices.
-
- Like _stack_tensor, but instead of setting missing slices to 0, sets them to
- what they were in the original tensor. The return value is reshaped to be
- the same as dense_tensor.
-
- Args:
- slices: a tensor. Shape [K, D_1, ...]
- indices: a 1-D integer tensor. Shape: [K]
- dense_tensor: the original tensor the slices were taken
- from. Shape: [D_0, D_1, ...]
- head_dims: True dimensions of the dense_tensor's first dimension.
-
- Returns:
- Reconsituted tensor. Shape: [D_0, D_1, ...]
- """
- # NOTE(siege): This cast shouldn't be necessary.
- indices = tf.cast(indices, tf.int32)
-
- tail_dims = tf.shape(dense_tensor)[1:]
- dense_shape = tf.concat([head_dims, tail_dims], 0)
-
- update_mask_vals = tf.fill(tf.shape(indices), 1)
- reshaped_indices = tf.expand_dims(indices, -1)
- update_mask = tf.equal(
- tf.scatter_nd(reshaped_indices, update_mask_vals, head_dims[:1]), 1)
-
- reshaped_dense_slices = tf.reshape(
- stack_tensor(slices, indices, dense_tensor, head_dims), dense_shape)
- reshaped_dense_tensor = tf.reshape(dense_tensor, dense_shape)
-
- return tf.reshape(
- tf.where(update_mask, reshaped_dense_slices, reshaped_dense_tensor),
- tf.shape(dense_tensor))
diff --git a/research/learned_optimizer/problems/BUILD b/research/learned_optimizer/problems/BUILD
deleted file mode 100644
index c704618821b36ca23f221f724888cde4e5d5a5ad..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/problems/BUILD
+++ /dev/null
@@ -1,43 +0,0 @@
-package(default_visibility = ["//visibility:public"])
-
-# Libraries
-# =====
-
-py_library(
- name = "datasets",
- srcs = ["datasets.py"],
- deps = [
- ],
-)
-
-py_library(
- name = "model_adapter",
- srcs = ["model_adapter.py"],
- deps = [
- ":problem_generator",
- ],
-)
-
-py_library(
- name = "problem_generator",
- srcs = ["problem_generator.py"],
- deps = [
- ":problem_spec",
- ],
-)
-
-py_library(
- name = "problem_sets",
- srcs = ["problem_sets.py"],
- deps = [
- ":datasets",
- ":model_adapter",
- ":problem_generator",
- ],
-)
-
-py_library(
- name = "problem_spec",
- srcs = ["problem_spec.py"],
- deps = [],
-)
diff --git a/research/learned_optimizer/problems/datasets.py b/research/learned_optimizer/problems/datasets.py
deleted file mode 100644
index edf3df6532178b0e60ab93c78611d2313798e639..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/problems/datasets.py
+++ /dev/null
@@ -1,218 +0,0 @@
-# Copyright 2017 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Functions to generate or load datasets for supervised learning."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from collections import namedtuple
-
-import numpy as np
-from sklearn.datasets import make_classification
-
-MAX_SEED = 4294967295
-
-
-class Dataset(namedtuple("Dataset", "data labels")):
- """Helper class for managing a supervised learning dataset.
-
- Args:
- data: an array of type float32 with N samples, each of which is the set
- of features for that sample. (Shape (N, D_i), where N is the number of
- samples and D_i is the number of features for that sample.)
- labels: an array of type int32 or int64 with N elements, indicating the
- class label for the corresponding set of features in data.
- """
- # Since this is an immutable object, we don't need to reserve slots.
- __slots__ = ()
-
- @property
- def size(self):
- """Dataset size (number of samples)."""
- return len(self.data)
-
- def batch_indices(self, num_batches, batch_size):
- """Creates indices of shuffled minibatches.
-
- Args:
- num_batches: the number of batches to generate
- batch_size: the size of each batch
-
- Returns:
- batch_indices: a list of minibatch indices, arranged so that the dataset
- is randomly shuffled.
-
- Raises:
- ValueError: if the data and labels have different lengths
- """
- if len(self.data) != len(self.labels):
- raise ValueError("Labels and data must have the same number of samples.")
-
- batch_indices = []
-
- # Follows logic in mnist.py to ensure we cover the entire dataset.
- index_in_epoch = 0
- dataset_size = len(self.data)
- dataset_indices = np.arange(dataset_size)
- np.random.shuffle(dataset_indices)
-
- for _ in range(num_batches):
- start = index_in_epoch
- index_in_epoch += batch_size
- if index_in_epoch > dataset_size:
-
- # Finished epoch, reshuffle.
- np.random.shuffle(dataset_indices)
-
- # Start next epoch.
- start = 0
- index_in_epoch = batch_size
-
- end = index_in_epoch
- batch_indices.append(dataset_indices[start:end].tolist())
-
- return batch_indices
-
-
-def noisy_parity_class(n_samples,
- n_classes=2,
- n_context_ids=5,
- noise_prob=0.25,
- random_seed=None):
- """Returns a randomly generated sparse-to-sparse dataset.
-
- The label is a parity class of a set of context classes.
-
- Args:
- n_samples: number of samples (data points)
- n_classes: number of class labels (default: 2)
- n_context_ids: how many classes to take the parity of (default: 5).
- noise_prob: how often to corrupt the label (default: 0.25)
- random_seed: seed used for drawing the random data (default: None)
- Returns:
- dataset: A Dataset namedtuple containing the generated data and labels
- """
- np.random.seed(random_seed)
- x = np.random.randint(0, n_classes, [n_samples, n_context_ids])
- noise = np.random.binomial(1, noise_prob, [n_samples])
- y = (np.sum(x, 1) + noise) % n_classes
- return Dataset(x.astype("float32"), y.astype("int32"))
-
-
-def random(n_features, n_samples, n_classes=2, sep=1.0, random_seed=None):
- """Returns a randomly generated classification dataset.
-
- Args:
- n_features: number of features (dependent variables)
- n_samples: number of samples (data points)
- n_classes: number of class labels (default: 2)
- sep: separation of the two classes, a higher value corresponds to
- an easier classification problem (default: 1.0)
- random_seed: seed used for drawing the random data (default: None)
-
- Returns:
- dataset: A Dataset namedtuple containing the generated data and labels
- """
- # Generate the problem data.
- x, y = make_classification(n_samples=n_samples,
- n_features=n_features,
- n_informative=n_features,
- n_redundant=0,
- n_classes=n_classes,
- class_sep=sep,
- random_state=random_seed)
-
- return Dataset(x.astype("float32"), y.astype("int32"))
-
-
-def random_binary(n_features, n_samples, random_seed=None):
- """Returns a randomly generated dataset of binary values.
-
- Args:
- n_features: number of features (dependent variables)
- n_samples: number of samples (data points)
- random_seed: seed used for drawing the random data (default: None)
-
- Returns:
- dataset: A Dataset namedtuple containing the generated data and labels
- """
- random_seed = (np.random.randint(MAX_SEED) if random_seed is None
- else random_seed)
- np.random.seed(random_seed)
-
- x = np.random.randint(2, size=(n_samples, n_features))
- y = np.zeros((n_samples, 1))
-
- return Dataset(x.astype("float32"), y.astype("int32"))
-
-
-def random_symmetric(n_features, n_samples, random_seed=None):
- """Returns a randomly generated dataset of values and their negatives.
-
- Args:
- n_features: number of features (dependent variables)
- n_samples: number of samples (data points)
- random_seed: seed used for drawing the random data (default: None)
-
- Returns:
- dataset: A Dataset namedtuple containing the generated data and labels
- """
- random_seed = (np.random.randint(MAX_SEED) if random_seed is None
- else random_seed)
- np.random.seed(random_seed)
-
- x1 = np.random.normal(size=(int(n_samples/2), n_features))
- x = np.concatenate((x1, -x1), axis=0)
- y = np.zeros((n_samples, 1))
-
- return Dataset(x.astype("float32"), y.astype("int32"))
-
-
-def random_mlp(n_features, n_samples, random_seed=None, n_layers=6, width=20):
- """Returns a generated output of an MLP with random weights.
-
- Args:
- n_features: number of features (dependent variables)
- n_samples: number of samples (data points)
- random_seed: seed used for drawing the random data (default: None)
- n_layers: number of layers in random MLP
- width: width of the layers in random MLP
-
- Returns:
- dataset: A Dataset namedtuple containing the generated data and labels
- """
- random_seed = (np.random.randint(MAX_SEED) if random_seed is None
- else random_seed)
- np.random.seed(random_seed)
-
- x = np.random.normal(size=(n_samples, n_features))
- y = x
- n_in = n_features
- scale_factor = np.sqrt(2.) / np.sqrt(n_features)
- for _ in range(n_layers):
- weights = np.random.normal(size=(n_in, width)) * scale_factor
- y = np.dot(y, weights).clip(min=0)
- n_in = width
-
- y = y[:, 0]
- y[y > 0] = 1
-
- return Dataset(x.astype("float32"), y.astype("int32"))
-
-
-EMPTY_DATASET = Dataset(np.array([], dtype="float32"),
- np.array([], dtype="int32"))
diff --git a/research/learned_optimizer/problems/model_adapter.py b/research/learned_optimizer/problems/model_adapter.py
deleted file mode 100644
index 8455992366dd46172e2a78471004779b1a4f091b..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/problems/model_adapter.py
+++ /dev/null
@@ -1,190 +0,0 @@
-# Copyright 2017 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Implementation of the ModelAdapter class."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import mock
-import tensorflow as tf
-
-from learned_optimizer.problems import problem_generator as pg
-
-
-class ModelAdapter(pg.Problem):
- """Adapts Tensorflow models/graphs into a form suitable for meta-training.
-
- This class adapts an existing TensorFlow graph into a form suitable for
- meta-training a learned optimizer.
- """
-
- def __init__(self, make_loss_and_init_fn):
- """Wraps a model in the Problem interface.
-
- make_loss_and_init argument is a callable that returns a tuple of
- two other callables as follows.
-
- The first will construct most of the graph and return the problem loss. It
- is essential that this graph contains the totality of the model's variables,
- but none of its queues.
-
- The second will return construct the model initialization graph given a list
- of parameters and return a callable that is passed an instance of
- tf.Session, and should initialize the models' parameters.
-
- An argument value function would look like this:
-
- ```python
- def make_loss_and_init_fn():
- inputs = queued_reader()
-
- def make_loss():
- return create_model_with_variables(inputs)
-
- def make_init_fn(parameters):
- saver = tf.Saver(parameters)
- def init_fn(sess):
- sess.restore(sess, ...)
- return init_fn
-
- return make_loss, make_init_fn
- ```
-
- Args:
- make_loss_and_init_fn: a callable, as described aboce
- """
- make_loss_fn, make_init_fn = make_loss_and_init_fn()
-
- self.make_loss_fn = make_loss_fn
- self.parameters, self.constants = _get_variables(make_loss_fn)
-
- if make_init_fn is not None:
- init_fn = make_init_fn(self.parameters + self.constants)
- else:
- init_op = tf.initialize_variables(self.parameters + self.constants)
- init_fn = lambda sess: sess.run(init_op)
-
- tf.logging.info("ModelAdapter parameters: %s",
- [op.name for op in self.parameters])
- tf.logging.info("ModelAdapter constants: %s",
- [op.name for op in self.constants])
-
- super(ModelAdapter, self).__init__(
- [], random_seed=None, noise_stdev=0.0, init_fn=init_fn)
-
- def init_tensors(self, seed=None):
- """Returns a list of tensors with the given shape."""
- return self.parameters
-
- def init_variables(self, seed=None):
- """Returns a list of variables with the given shape."""
- # NOTE(siege): This is awkward, as these are not set as trainable.
- return self.parameters
-
- def objective(self, parameters, data=None, labels=None):
- """Computes the objective given a list of parameters.
-
- Args:
- parameters: The parameters to optimize (as a list of tensors)
- data: An optional batch of data for calculating objectives
- labels: An optional batch of corresponding labels
-
- Returns:
- A scalar tensor representing the objective value
- """
- # We need to set up a mapping based on the original parameter names, because
- # the parameters passed can be arbitrary tensors.
- parameter_mapping = {
- old_p.name: p
- for old_p, p in zip(self.parameters, parameters)
- }
-
- with tf.variable_scope(tf.get_variable_scope(), reuse=True):
- return _make_with_custom_variables(self.make_loss_fn, parameter_mapping)
-
-
-def _get_variables(func):
- """Calls func, returning any variables created.
-
- The created variables are modified to not be trainable, and are placed into
- the LOCAL_VARIABLES collection.
-
- Args:
- func: Function to be called.
-
- Returns:
- A tuple (variables, constants) where the first element is a list of
- trainable variables and the second is the non-trainable variables.
- """
- variables = []
- constants = []
-
- # We need to create these variables like normal, so grab the original
- # constructor before we mock it.
- original_init = tf.Variable.__init__
-
- def custom_init(self, *args, **kwargs):
- trainable = kwargs["trainable"]
- kwargs["trainable"] = False
- # Making these variables local keeps them out of the optimizer's checkpoints
- # somehow.
- kwargs["collections"] = [tf.GraphKeys.LOCAL_VARIABLES]
- original_init(self, *args, **kwargs)
- if trainable:
- variables.append(self)
- else:
- constants.append(self)
-
- # This name-scope is just a nicety for TensorBoard.
- with tf.name_scope("unused_graph"):
- with mock.patch.object(tf.Variable, "__init__", custom_init):
- func()
-
- return variables, constants
-
-
-def _make_with_custom_variables(func, variable_mapping):
- """Calls func and replaces the value of some variables created in it.
-
- Args:
- func: Function to be called.
- variable_mapping: A mapping of variable name to the replacement tensor or
- tf.Variable.
-
- Returns:
- The return value of func is returned.
- """
- original_value = tf.Variable.value
-
- def custom_value(self):
- if self.name in variable_mapping:
- replacement = variable_mapping[self.name]
- tf.logging.info("Replaced %s with %s" % (self.name, replacement))
-
- # value() method needs to return a tensor, we need to call value on it.
- # This has to be done manually like this otherwise we'll get an infinite
- # loop.
- if isinstance(replacement, tf.Variable):
- replacement = original_value(replacement)
-
- return replacement
- else:
- return original_value(self)
-
- with mock.patch.object(tf.Variable, "value", custom_value):
- with mock.patch.object(tf.Variable, "_AsTensor", custom_value):
- return func()
diff --git a/research/learned_optimizer/problems/problem_generator.py b/research/learned_optimizer/problems/problem_generator.py
deleted file mode 100644
index abe1008faadbb04163bc27e0b991e3ec4ba9e6bc..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/problems/problem_generator.py
+++ /dev/null
@@ -1,1016 +0,0 @@
-# Copyright 2017 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Generates toy optimization problems.
-
-This module contains a base class, Problem, that defines a minimal interface
-for optimization problems, and a few specific problem types that subclass it.
-
-Test functions for optimization: http://www.sfu.ca/~ssurjano/optimization.html
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import tensorflow as tf
-
-from learned_optimizer.problems import problem_spec as prob_spec
-
-tf.app.flags.DEFINE_float("l2_reg_scale", 1e-3,
- """Scaling factor for parameter value regularization
- in softmax classifier problems.""")
-FLAGS = tf.app.flags.FLAGS
-
-EPSILON = 1e-6
-MAX_SEED = 4294967295
-PARAMETER_SCOPE = "parameters"
-
-_Spec = prob_spec.Spec
-
-
-class Problem(object):
- """Base class for optimization problems.
-
- This defines an interface for optimization problems, including objective and
- gradients functions and a feed_generator function that yields data to pass to
- feed_dict in tensorflow.
-
- Subclasses of Problem must (at the minimum) override the objective method,
- which computes the objective/loss/cost to minimize, and specify the desired
- shape of the parameters in a list in the param_shapes attribute.
- """
-
- def __init__(self, param_shapes, random_seed, noise_stdev, init_fn=None):
- """Initializes a global random seed for the problem.
-
- Args:
- param_shapes: A list of tuples defining the expected shapes of the
- parameters for this problem
- random_seed: Either an integer (or None, in which case the seed is
- randomly drawn)
- noise_stdev: Strength (standard deviation) of added gradient noise
- init_fn: A function taking a tf.Session object that is used to
- initialize the problem's variables.
-
- Raises:
- ValueError: If the random_seed is not an integer and not None
- """
- if random_seed is not None and not isinstance(random_seed, int):
- raise ValueError("random_seed must be an integer or None")
-
- # Pick a random seed.
- self.random_seed = (np.random.randint(MAX_SEED) if random_seed is None
- else random_seed)
-
- # Store the noise level.
- self.noise_stdev = noise_stdev
-
- # Set the random seed to ensure any random data in the problem is the same.
- np.random.seed(self.random_seed)
-
- # Store the parameter shapes.
- self.param_shapes = param_shapes
-
- if init_fn is not None:
- self.init_fn = init_fn
- else:
- self.init_fn = lambda _: None
-
- def init_tensors(self, seed=None):
- """Returns a list of tensors with the given shape."""
- return [tf.random_normal(shape, seed=seed) for shape in self.param_shapes]
-
- def init_variables(self, seed=None):
- """Returns a list of variables with the given shape."""
- with tf.variable_scope(PARAMETER_SCOPE):
- params = [tf.Variable(param) for param in self.init_tensors(seed)]
- return params
-
- def objective(self, parameters, data=None, labels=None):
- """Computes the objective given a list of parameters.
-
- Args:
- parameters: The parameters to optimize (as a list of tensors)
- data: An optional batch of data for calculating objectives
- labels: An optional batch of corresponding labels
-
- Returns:
- A scalar tensor representing the objective value
- """
- raise NotImplementedError
-
- def gradients(self, objective, parameters):
- """Compute gradients of the objective with respect to the parameters.
-
- Args:
- objective: The objective op (e.g. output of self.objective())
- parameters: A list of tensors (the parameters to optimize)
-
- Returns:
- A list of tensors representing the gradient for each parameter,
- returned in the same order as the given list
- """
- grads = tf.gradients(objective, list(parameters))
- noisy_grads = []
-
- for grad in grads:
- if isinstance(grad, tf.IndexedSlices):
- noise = self.noise_stdev * tf.random_normal(tf.shape(grad.values))
- new_grad = tf.IndexedSlices(grad.values + noise, grad.indices)
- else:
- new_grad = grad + self.noise_stdev * tf.random_normal(grad.get_shape())
- noisy_grads.append(new_grad)
-
- return noisy_grads
-
-
-class Quadratic(Problem):
- """Optimizes a random quadratic function.
-
- The objective is: f(x) = (1/2) ||Wx - y||_2^2
- where W is a random Gaussian matrix and y is a random Gaussian vector.
- """
-
- def __init__(self, ndim, random_seed=None, noise_stdev=0.0):
- """Initializes a random quadratic problem."""
- param_shapes = [(ndim, 1)]
- super(Quadratic, self).__init__(param_shapes, random_seed, noise_stdev)
-
- # Generate a random problem instance.
- self.w = np.random.randn(ndim, ndim).astype("float32")
- self.y = np.random.randn(ndim, 1).astype("float32")
-
- def objective(self, params, data=None, labels=None):
- """Quadratic objective (see base class for details)."""
- return tf.nn.l2_loss(tf.matmul(self.w, params[0]) - self.y)
-
-
-class SoftmaxClassifier(Problem):
- """Helper functions for supervised softmax classification problems."""
-
- def init_tensors(self, seed=None):
- """Returns a list of tensors with the given shape."""
- return [tf.random_normal(shape, seed=seed) * 1.2 / np.sqrt(shape[0])
- for shape in self.param_shapes]
-
- def inference(self, params, data):
- """Computes logits given parameters and data.
-
- Args:
- params: List of parameter tensors or variables
- data: Batch of features with samples along the first dimension
-
- Returns:
- logits: Un-normalized logits with shape (num_samples, num_classes)
- """
- raise NotImplementedError
-
- def objective(self, params, data, labels):
- """Computes the softmax cross entropy.
-
- Args:
- params: List of parameter tensors or variables
- data: Batch of features with samples along the first dimension
- labels: Vector of labels with the same number of samples as the data
-
- Returns:
- loss: Softmax cross entropy loss averaged over the samples in the batch
-
- Raises:
- ValueError: If the objective is to be computed over >2 classes, because
- this operation is broken in tensorflow at the moment.
- """
- # Forward pass.
- logits = self.inference(params, data)
-
- # Compute the loss.
- l2reg = [tf.reduce_sum(param ** 2) for param in params]
- if int(logits.get_shape()[1]) == 2:
- labels = tf.cast(labels, tf.float32)
- losses = tf.nn.sigmoid_cross_entropy_with_logits(
- labels=labels, logits=logits[:, 0])
- else:
- raise ValueError("Unable to compute softmax cross entropy for more than"
- " 2 classes.")
-
- return tf.reduce_mean(losses) + tf.reduce_mean(l2reg) * FLAGS.l2_reg_scale
-
- def argmax(self, logits):
- """Samples the most likely class label given the logits.
-
- Args:
- logits: Un-normalized logits with shape (num_samples, num_classes)
-
- Returns:
- predictions: Predicted class labels, has shape (num_samples,)
- """
- return tf.cast(tf.argmax(tf.nn.softmax(logits), 1), tf.int32)
-
- def accuracy(self, params, data, labels):
- """Computes the accuracy (fraction of correct classifications).
-
- Args:
- params: List of parameter tensors or variables
- data: Batch of features with samples along the first dimension
- labels: Vector of labels with the same number of samples as the data
-
- Returns:
- accuracy: Fraction of correct classifications across the batch
- """
- predictions = self.argmax(self.inference(params, data))
- return tf.contrib.metrics.accuracy(predictions, tf.cast(labels, tf.int32))
-
-
-class SoftmaxRegression(SoftmaxClassifier):
- """Builds a softmax regression problem."""
-
- def __init__(self, n_features, n_classes, activation=tf.identity,
- random_seed=None, noise_stdev=0.0):
- self.activation = activation
- self.n_features = n_features
- param_shapes = [(n_features, n_classes), (n_classes,)]
- super(SoftmaxRegression, self).__init__(param_shapes,
- random_seed,
- noise_stdev)
-
- def inference(self, params, data):
- features = tf.reshape(data, (-1, self.n_features))
- return tf.matmul(features, params[0]) + params[1]
-
-
-class SparseSoftmaxRegression(SoftmaxClassifier):
- """Builds a sparse input softmax regression problem."""
-
- def __init__(self,
- n_features,
- n_classes,
- activation=tf.identity,
- random_seed=None,
- noise_stdev=0.0):
- self.activation = activation
- self.n_features = n_features
- param_shapes = [(n_classes, n_features), (n_features, n_classes), (
- n_classes,)]
- super(SparseSoftmaxRegression, self).__init__(param_shapes, random_seed,
- noise_stdev)
-
- def inference(self, params, data):
- all_embeddings, softmax_weights, softmax_bias = params
- embeddings = tf.nn.embedding_lookup(all_embeddings, tf.cast(data, tf.int32))
- embeddings = tf.reduce_sum(embeddings, 1)
- return tf.matmul(embeddings, softmax_weights) + softmax_bias
-
-
-class OneHotSparseSoftmaxRegression(SoftmaxClassifier):
- """Builds a sparse input softmax regression problem.
-
- This is identical to SparseSoftmaxRegression, but without using embedding
- ops.
- """
-
- def __init__(self,
- n_features,
- n_classes,
- activation=tf.identity,
- random_seed=None,
- noise_stdev=0.0):
- self.activation = activation
- self.n_features = n_features
- self.n_classes = n_classes
- param_shapes = [(n_classes, n_features), (n_features, n_classes), (
- n_classes,)]
- super(OneHotSparseSoftmaxRegression, self).__init__(param_shapes,
- random_seed,
- noise_stdev)
-
- def inference(self, params, data):
- all_embeddings, softmax_weights, softmax_bias = params
- num_ids = tf.shape(data)[1]
- one_hot_embeddings = tf.one_hot(tf.cast(data, tf.int32), self.n_classes)
- one_hot_embeddings = tf.reshape(one_hot_embeddings, [-1, self.n_classes])
- embeddings = tf.matmul(one_hot_embeddings, all_embeddings)
- embeddings = tf.reshape(embeddings, [-1, num_ids, self.n_features])
- embeddings = tf.reduce_sum(embeddings, 1)
- return tf.matmul(embeddings, softmax_weights) + softmax_bias
-
-
-class FullyConnected(SoftmaxClassifier):
- """Builds a multi-layer perceptron classifier."""
-
- def __init__(self, n_features, n_classes, hidden_sizes=(32, 64),
- activation=tf.nn.sigmoid, random_seed=None, noise_stdev=0.0):
- """Initializes an multi-layer perceptron classification problem."""
- # Store the number of features and activation function.
- self.n_features = n_features
- self.activation = activation
-
- # Define the network as a list of weight + bias shapes for each layer.
- param_shapes = []
- for ix, sz in enumerate(hidden_sizes + (n_classes,)):
-
- # The previous layer"s size (n_features if input).
- prev_size = n_features if ix == 0 else hidden_sizes[ix - 1]
-
- # Weight shape for this layer.
- param_shapes.append((prev_size, sz))
-
- # Bias shape for this layer.
- param_shapes.append((sz,))
-
- super(FullyConnected, self).__init__(param_shapes, random_seed, noise_stdev)
-
- def inference(self, params, data):
- # Flatten the features into a vector.
- features = tf.reshape(data, (-1, self.n_features))
-
- # Pass the data through the network.
- preactivations = tf.matmul(features, params[0]) + params[1]
-
- for layer in range(2, len(self.param_shapes), 2):
- net = self.activation(preactivations)
- preactivations = tf.matmul(net, params[layer]) + params[layer + 1]
-
- return preactivations
-
- def accuracy(self, params, data, labels):
- """Computes the accuracy (fraction of correct classifications).
-
- Args:
- params: List of parameter tensors or variables
- data: Batch of features with samples along the first dimension
- labels: Vector of labels with the same number of samples as the data
-
- Returns:
- accuracy: Fraction of correct classifications across the batch
- """
- predictions = self.argmax(self.activation(self.inference(params, data)))
- return tf.contrib.metrics.accuracy(predictions, tf.cast(labels, tf.int32))
-
-
-class ConvNet(SoftmaxClassifier):
- """Builds an N-layer convnet for image classification."""
-
- def __init__(self,
- image_shape,
- n_classes,
- filter_list,
- activation=tf.nn.relu,
- random_seed=None,
- noise_stdev=0.0):
- # Number of channels, number of pixels in x- and y- dimensions.
- n_channels, px, py = image_shape
-
- # Store the activation.
- self.activation = activation
-
- param_shapes = []
- input_size = n_channels
- for fltr in filter_list:
- # Add conv2d filters.
- param_shapes.append((fltr[0], fltr[1], input_size, fltr[2]))
- input_size = fltr[2]
-
- # Number of units in the final (dense) layer.
- self.affine_size = input_size * px * py
-
- param_shapes.append((self.affine_size, n_classes)) # affine weights
- param_shapes.append((n_classes,)) # affine bias
-
- super(ConvNet, self).__init__(param_shapes, random_seed, noise_stdev)
-
- def init_tensors(self, seed=None):
- """Returns a list of tensors with the given shape."""
- return [tf.random_normal(shape, mean=0., stddev=0.01, seed=seed)
- for shape in self.param_shapes]
-
- def inference(self, params, data):
-
- # Unpack.
- w_conv_list = params[:-2]
- output_w, output_b = params[-2:]
-
- conv_input = data
- for w_conv in w_conv_list:
- layer = tf.nn.conv2d(conv_input, w_conv, strides=[1] * 4, padding="SAME")
- output = self.activation(layer)
- conv_input = output
-
- # Flatten.
- flattened = tf.reshape(conv_input, (-1, self.affine_size))
-
- # Fully connected layer.
- return tf.matmul(flattened, output_w) + output_b
-
-
-class Bowl(Problem):
- """A 2D quadratic bowl."""
-
- def __init__(self, condition_number, angle=0.0,
- random_seed=None, noise_stdev=0.0):
- assert condition_number > 0, "Condition number must be positive."
-
- # Define parameter shapes.
- param_shapes = [(2, 1)]
- super(Bowl, self).__init__(param_shapes, random_seed, noise_stdev)
-
- self.condition_number = condition_number
- self.angle = angle
- self._build_matrix(condition_number, angle)
-
- def _build_matrix(self, condition_number, angle):
- """Builds the Hessian matrix."""
- hessian = np.array([[condition_number, 0.], [0., 1.]], dtype="float32")
-
- # Build the rotation matrix.
- rotation_matrix = np.array([
- [np.cos(angle), -np.sin(angle)],
- [np.sin(angle), np.cos(angle)]
- ])
-
- # The objective is 0.5 * || Ax ||_2^2
- # where the data matrix (A) is: sqrt(Hessian).dot(rotation_matrix).
- self.matrix = np.sqrt(hessian).dot(rotation_matrix)
-
- def objective(self, params, data=None, labels=None):
- mtx = tf.constant(self.matrix, dtype=tf.float32)
- return tf.nn.l2_loss(tf.matmul(mtx, params[0]))
-
- def surface(self, xlim=5, ylim=5, n=50):
- xm, ym = _mesh(xlim, ylim, n)
- pts = np.vstack([xm.ravel(), ym.ravel()])
- zm = 0.5 * np.linalg.norm(self.matrix.dot(pts), axis=0) ** 2
- return xm, ym, zm.reshape(n, n)
-
-
-class Problem2D(Problem):
-
- def __init__(self, random_seed=None, noise_stdev=0.0):
- param_shapes = [(2,)]
- super(Problem2D, self).__init__(param_shapes, random_seed, noise_stdev)
-
- def surface(self, n=50, xlim=5, ylim=5):
- """Computes the objective surface over a 2d mesh."""
-
- # Create a mesh over the given coordinate ranges.
- xm, ym = _mesh(xlim, ylim, n)
-
- with tf.Graph().as_default(), tf.Session() as sess:
-
- # Ops to compute the objective at every (x, y) point.
- x = tf.placeholder(tf.float32, shape=xm.shape)
- y = tf.placeholder(tf.float32, shape=ym.shape)
- obj = self.objective([[x, y]])
-
- # Run the computation.
- zm = sess.run(obj, feed_dict={x: xm, y: ym})
-
- return xm, ym, zm
-
-
-class Rosenbrock(Problem2D):
- """See https://en.wikipedia.org/wiki/Rosenbrock_function.
-
- This function has a single global minima at [1, 1]
- The objective value at this point is zero.
- """
-
- def init_tensors(self, seed=None):
- """Returns a list of tensors with the given shape."""
- return [tf.random_uniform(shape, minval=-5., maxval=10., seed=seed)
- for shape in self.param_shapes]
-
- def objective(self, params, data=None, labels=None):
- x, y = tf.split(params[0], 2, axis=0)
- obj = (1 - x)**2 + 100 * (y - x**2)**2
- return tf.squeeze(obj)
-
-
-def make_rosenbrock_loss_and_init(device=None):
- """A variable-backed version of Rosenbrock problem.
-
- See the Rosenbrock class for details.
-
- Args:
- device: Where to place the ops of this problem.
-
- Returns:
- A tuple of two callables, first of which creates the loss and the second
- creates the parameter initializer function.
- """
- def make_rosenbrock_loss():
- with tf.name_scope("optimizee"):
- with tf.device(device):
- x = tf.get_variable("x", [1])
- y = tf.get_variable("y", [1])
- c = tf.get_variable(
- "c", [1],
- initializer=tf.constant_initializer(100.0),
- trainable=False)
- obj = (1 - x)**2 + c * (y - x**2)**2
- return tf.squeeze(obj)
-
- def make_init_fn(parameters):
- with tf.device(device):
- init_op = tf.variables_initializer(parameters)
- def init_fn(sess):
- tf.logging.info("Initializing model parameters.")
- sess.run(init_op)
- return init_fn
-
- return make_rosenbrock_loss, make_init_fn
-
-
-class Saddle(Problem2D):
- """Loss surface around a saddle point."""
-
- def objective(self, params, data=None, labels=None):
- x, y = tf.split(params[0], 2, axis=0)
- obj = x ** 2 - y ** 2
- return tf.squeeze(obj)
-
-
-class LogSumExp(Problem2D):
- """2D function defined by the log of the sum of exponentials."""
-
- def objective(self, params, data=None, labels=None):
- x, y = tf.split(params[0], 2, axis=0)
- obj = tf.log(tf.exp(x + 3. * y - 0.1) +
- tf.exp(x - 3. * y - 0.1) +
- tf.exp(-x - 0.1) + 1.0)
- return tf.squeeze(obj)
-
-
-class Ackley(Problem2D):
- """Ackley's function (contains many local minima)."""
-
- def init_tensors(self, seed=None):
- """Returns a list of tensors with the given shape."""
- return [tf.random_uniform(shape, minval=-32.768, maxval=32.768, seed=seed)
- for shape in self.param_shapes]
-
- def objective(self, params, data=None, labels=None):
- x, y = tf.split(params[0], 2, axis=0)
- obj = (-20 * tf.exp(-0.2 * tf.sqrt(0.5 * (x ** 2 + y ** 2))) -
- tf.exp(0.5 * (tf.cos(2 * np.pi * x) + tf.cos(2 * np.pi * y))) +
- tf.exp(1.0) + 20.)
- return tf.squeeze(obj)
-
-
-class Beale(Problem2D):
- """Beale function (a multimodal function with sharp peaks)."""
-
- def init_tensors(self, seed=None):
- """Returns a list of tensors with the given shape."""
- return [tf.random_uniform(shape, minval=-4.5, maxval=4.5, seed=seed)
- for shape in self.param_shapes]
-
- def objective(self, params, data=None, labels=None):
- x, y = tf.split(params[0], 2, axis=0)
- obj = ((1.5 - x + x * y) ** 2 +
- (2.25 - x + x * y ** 2) ** 2 +
- (2.625 - x + x * y ** 3) ** 2)
- return tf.squeeze(obj)
-
-
-class Booth(Problem2D):
- """Booth's function (has a long valley along one dimension)."""
-
- def init_tensors(self, seed=None):
- """Returns a list of tensors with the given shape."""
- return [tf.random_uniform(shape, minval=-10., maxval=10., seed=seed)
- for shape in self.param_shapes]
-
- def objective(self, params, data=None, labels=None):
- x, y = tf.split(params[0], 2, axis=0)
- obj = (x + 2 * y - 7) ** 2 + (2 * x + y - 5) ** 2
- return tf.squeeze(obj)
-
-
-class StyblinskiTang(Problem2D):
- """Styblinski-Tang function (a bumpy function in two dimensions)."""
-
- def init_tensors(self, seed=None):
- """Returns a list of tensors with the given shape."""
- return [tf.random_uniform(shape, minval=-5., maxval=5., seed=seed)
- for shape in self.param_shapes]
-
- def objective(self, params, data=None, labels=None):
- params = tf.split(params[0], 2, axis=0)
- obj = 0.5 * tf.reduce_sum([x ** 4 - 16 * x ** 2 + 5 * x
- for x in params], 0) + 80.
- return tf.squeeze(obj)
-
-
-class Matyas(Problem2D):
- """Matyas function (a function with a single global minimum in a valley)."""
-
- def init_tensors(self, seed=None):
- """Returns a list of tensors with the given shape."""
- return [tf.random_uniform(shape, minval=-10, maxval=10, seed=seed)
- for shape in self.param_shapes]
-
- def objective(self, params, data=None, labels=None):
- x, y = tf.split(params[0], 2, axis=0)
- obj = 0.26 * (x ** 2 + y ** 2) - 0.48 * x * y
- return tf.squeeze(obj)
-
-
-class Branin(Problem2D):
- """Branin function (a function with three global minima)."""
-
- def init_tensors(self, seed=None):
- """Returns a list of tensors with the given shape."""
- x1 = tf.random_uniform((1,), minval=-5., maxval=10.,
- seed=seed)
- x2 = tf.random_uniform((1,), minval=0., maxval=15.,
- seed=seed)
- return [tf.concat([x1, x2], 0)]
-
- def objective(self, params, data=None, labels=None):
- x, y = tf.split(params[0], 2, axis=0)
-
- # Define some constants.
- a = 1.
- b = 5.1 / (4. * np.pi ** 2)
- c = 5 / np.pi
- r = 6.
- s = 10.
- t = 1 / (8. * np.pi)
-
- # Evaluate the function.
- obj = a * (y - b * x ** 2 + c * x - r) ** 2 + s * (1 - t) * tf.cos(x) + s
- return tf.squeeze(obj)
-
-
-class Michalewicz(Problem2D):
- """Michalewicz function (has steep ridges and valleys)."""
-
- def init_tensors(self, seed=None):
- """Returns a list of tensors with the given shape."""
- return [tf.random_uniform(shape, minval=0., maxval=np.pi, seed=seed)
- for shape in self.param_shapes]
-
- def objective(self, params, data=None, labels=None):
- x, y = tf.split(params[0], 2, axis=0)
- m = 5 # Defines how steep the ridges are (larger m => steeper ridges).
- obj = 2. - (tf.sin(x) * tf.sin(x ** 2 / np.pi) ** (2 * m) +
- tf.sin(y) * tf.sin(2 * y ** 2 / np.pi) ** (2 * m))
- return tf.squeeze(obj)
-
-
-class Rescale(Problem):
- """Takes an existing problem, and rescales all the parameters."""
-
- def __init__(self, problem_spec, scale=10., noise_stdev=0.0):
- self.problem = problem_spec.build()
- self.param_shapes = self.problem.param_shapes
- self.scale = scale
-
- super(Rescale, self).__init__(self.param_shapes, random_seed=None,
- noise_stdev=noise_stdev)
-
- def init_tensors(self, seed=None):
- params_raw = self.problem.init_tensors(seed=seed)
- params = [t * self.scale for t in params_raw]
- return params
-
- def objective(self, params, data=None, labels=None):
- params_raw = [t/self.scale for t in params]
-
- problem_obj = self.problem.objective(params_raw, data, labels)
- return problem_obj
-
-
-class SumTask(Problem):
- """Takes a list of problems and modifies the objective to be their sum."""
-
- def __init__(self, problem_specs, noise_stdev=0.0):
- self.problems = [ps.build() for ps in problem_specs]
- self.param_shapes = []
- for prob in self.problems:
- self.param_shapes += prob.param_shapes
-
- super(SumTask, self).__init__(self.param_shapes, random_seed=None,
- noise_stdev=noise_stdev)
-
- def init_tensors(self, seed=None):
- tensors = []
- for prob in self.problems:
- tensors += prob.init_tensors(seed=seed)
- return tensors
-
- def objective(self, params, data=None, labels=None):
- obj = 0.
- index = 0
- for prob in self.problems:
- num_params = len(prob.param_shapes)
- obj += prob.objective(params[index:index + num_params])
- index += num_params
- return obj
-
-
-class IsotropicQuadratic(Problem):
- """An isotropic quadratic problem."""
-
- def objective(self, params, data=None, labels=None):
- return sum([tf.reduce_sum(param ** 2) for param in params])
-
-
-class Norm(Problem):
- """Takes an existing problem and modifies the objective to be its N-norm."""
-
- def __init__(self, ndim, random_seed=None, noise_stdev=0.0, norm_power=2.):
- param_shapes = [(ndim, 1)]
- super(Norm, self).__init__(param_shapes, random_seed, noise_stdev)
-
- # Generate a random problem instance.
- self.w = np.random.randn(ndim, ndim).astype("float32")
- self.y = np.random.randn(ndim, 1).astype("float32")
- self.norm_power = norm_power
-
- def objective(self, params, data=None, labels=None):
- diff = tf.matmul(self.w, params[0]) - self.y
- exp = 1. / self.norm_power
- loss = tf.reduce_sum((tf.abs(diff) + EPSILON) ** self.norm_power) ** exp
- return loss
-
-
-class LogObjective(Problem):
- """Takes an existing problem and modifies the objective to be its log."""
-
- def __init__(self, problem_spec):
- self.problem = problem_spec.build()
- self.param_shapes = self.problem.param_shapes
-
- super(LogObjective, self).__init__(self.param_shapes,
- random_seed=None,
- noise_stdev=0.0)
-
- def objective(self, params, data=None, labels=None):
- problem_obj = self.problem.objective(params, data, labels)
- return tf.log(problem_obj + EPSILON) - tf.log(EPSILON)
-
-
-class SparseProblem(Problem):
- """Takes a problem and sets gradients to 0 with the given probability."""
-
- def __init__(self,
- problem_spec,
- zero_probability=0.99,
- random_seed=None,
- noise_stdev=0.0):
- self.problem = problem_spec.build()
- self.param_shapes = self.problem.param_shapes
- self.zero_prob = zero_probability
-
- super(SparseProblem, self).__init__(self.param_shapes,
- random_seed=random_seed,
- noise_stdev=noise_stdev)
-
- def objective(self, parameters, data=None, labels=None):
- return self.problem.objective(parameters, data, labels)
-
- def gradients(self, objective, parameters):
- grads = tf.gradients(objective, list(parameters))
-
- new_grads = []
- for grad in grads:
- mask = tf.greater(self.zero_prob, tf.random_uniform(grad.get_shape()))
- zero_grad = tf.zeros_like(grad, dtype=tf.float32)
- noisy_grad = grad + self.noise_stdev * tf.random_normal(grad.get_shape())
- new_grads.append(tf.where(mask, zero_grad, noisy_grad))
- return new_grads
-
-
-class DependencyChain(Problem):
- """A problem in which parameters must be optimized in order.
-
- A sequence of parameters which all need to be brought to 0, but where each
- parameter in the sequence can't be brought to 0 until the preceding one
- has been. This should take a long time to optimize, with steady
- (or accelerating) progress throughout the entire process.
- """
-
- def __init__(self, ndim, random_seed=None, noise_stdev=0.):
- param_shapes = [(ndim + 1,)]
- self.ndim = ndim
- super(DependencyChain, self).__init__(
- param_shapes, random_seed, noise_stdev)
-
- def objective(self, params, data=None, labels=None):
- terms = params[0][0]**2 + params[0][1:]**2 / (params[0][:-1]**2 + EPSILON)
- return tf.reduce_sum(terms)
-
-
-class MinMaxWell(Problem):
- """Problem with global min when both the min and max (absolute) params are 1.
-
- The gradient for all but two parameters (the min and max) is zero. This
- should therefore encourage the optimizer to behave sensible even when
- parameters have zero gradients, as is common eg for some deep neural nets.
- """
-
- def __init__(self, ndim, random_seed=None, noise_stdev=0.):
- param_shapes = [(ndim,)]
- self.ndim = ndim
- super(MinMaxWell, self).__init__(param_shapes, random_seed, noise_stdev)
-
- def objective(self, params, data=None, labels=None):
- params_sqr = params[0]**2
- min_sqr = tf.reduce_min(params_sqr)
- max_sqr = tf.reduce_max(params_sqr)
- epsilon = 1e-12
-
- return max_sqr + 1./min_sqr - 2. + epsilon
-
-
-class OutwardSnake(Problem):
- """A winding path out to infinity.
-
- Ideal step length stays constant along the entire path.
- """
-
- def __init__(self, ndim, random_seed=None, noise_stdev=0.):
- param_shapes = [(ndim,)]
- self.ndim = ndim
- super(OutwardSnake, self).__init__(param_shapes, random_seed, noise_stdev)
-
- def objective(self, params, data, labels=None):
- radius = tf.sqrt(tf.reduce_sum(params[0]**2))
- rad_loss = tf.reduce_sum(1. / (radius + 1e-6) * data[:, 0])
-
- sin_dist = params[0][1:] - tf.cos(params[0][:-1]) * np.pi
- sin_loss = tf.reduce_sum((sin_dist * data[:, 1:])**2)
-
- return rad_loss + sin_loss
-
-
-class ProjectionQuadratic(Problem):
- """Dataset consists of different directions to probe. Global min is at 0."""
-
- def __init__(self, ndim, random_seed=None, noise_stdev=0.):
- param_shapes = [(1, ndim)]
- super(ProjectionQuadratic, self).__init__(
- param_shapes, random_seed, noise_stdev)
-
- def objective(self, params, data, labels=None):
- return tf.reduce_sum((params[0] * data)**2)
-
-
-class SumOfQuadratics(Problem):
-
- def __init__(self, ndim, random_seed=None, noise_stdev=0.):
- param_shapes = [(1, ndim)]
- super(SumOfQuadratics, self).__init__(
- param_shapes, random_seed, noise_stdev)
-
- def objective(self, params, data, labels=None):
- epsilon = 1e-12
- # Assume dataset is designed so that the global minimum is at params=0.
- # Subtract loss at params=0, so that global minimum has objective value
- # epsilon (added to avoid floating point issues).
- return (tf.reduce_sum((params[0] - data)**2) - tf.reduce_sum(data**2) +
- epsilon)
-
-
-class MatMulAlgorithm(Problem):
- """A 6-th order polynomial optimization problem.
-
- This problem is parametrized by n and k. A solution to this problem with
- objective value exactly zero defines a matrix multiplication algorithm of
- n x n matrices using k multiplications between matrices. When applied
- recursively, such an algorithm has complexity O(n^(log_n(k))).
-
- Given n, it is not known in general which values of k in [n^2, n^3] have a
- solution. There is always a solution with k = n^3 (this is the naive
- algorithm).
-
- In the special case n = 2, it is known that there are solutions for k = {7, 8}
- but not for k <= 6. For n = 3, it is known that there are exact solutions for
- 23 <= k <= 27, and there are asymptotic solutions for k = {21, 22}, but the
- other cases are unknown.
-
- For a given n and k, if one solution exists then infinitely many solutions
- exist due to permutation and scaling symmetries in the parameters.
-
- This is a very hard problem for some values of n and k (e.g. n = 3, k = 21),
- but very easy for other values (e.g. n = 2, k = 7).
-
- For a given n and k, the specific formulation of this problem is as follows.
- Let theta_a, theta_b, theta_c be parameter matrices with respective dimensions
- [n**2, k], [n**2, k], [k, n**2]. Then for any matrices a, b with shape [n, n],
- we can form the matrix c with shape [n, n] via the operation:
- ((vec(a) * theta_a) .* (vec(b) * theta_b)) * theta_c = vec(c), (#)
- where vec(x) is the operator that flattens a matrix with shape [n, n] into a
- row vector with shape [1, n**2], * denotes matrix multiplication and .*
- denotes elementwise multiplication.
-
- This operation, parameterized by theta_a, theta_b, theta_c, is a matrix
- multiplication algorithm iff c = a*b for all [n, n] matrices a and b. But
- actually it suffices to verify all combinations of one-hot matrices a and b,
- of which there are n**4 such combinations. This gives a batch of n**4 matrix
- triplets (a, b, c) such that equation (#) must hold for each triplet. We solve
- for theta_a, theta_b, theta_c by minimizing the sum of squares of errors
- across this batch.
-
- Finally, theta_c can be computed from theta_a and theta_b. Therefore it
- suffices to learn theta_a and theta_b, from which theta_c and therefore the
- objective value can be computed.
- """
-
- def __init__(self, n, k):
- assert isinstance(n, int), "n must be an integer"
- assert isinstance(k, int), "k must be an integer"
- assert n >= 2, "Must have n >= 2"
- assert k >= n**2 and k <= n**3, "Must have n**2 <= k <= n**3"
-
- param_shapes = [(n**2, k), (n**2, k)] # theta_a, theta_b
- super(MatMulAlgorithm, self).__init__(
- param_shapes, random_seed=None, noise_stdev=0.0)
-
- self.n = n
- self.k = k
-
- # Build a batch of all combinations of one-hot matrices a, b, and their
- # respective products c. Correctness on this batch is a necessary and
- # sufficient condition for the algorithm to be valid. The number of matrices
- # in {a, b, c}_3d is n**4 and each matrix is n x n.
- onehots = np.identity(n**2).reshape(n**2, n, n)
- a_3d = np.repeat(onehots, n**2, axis=0)
- b_3d = np.tile(onehots, [n**2, 1, 1])
- c_3d = np.matmul(a_3d, b_3d)
-
- # Convert the batch to 2D Tensors.
- self.a = tf.constant(a_3d.reshape(n**4, n**2), tf.float32, name="a")
- self.b = tf.constant(b_3d.reshape(n**4, n**2), tf.float32, name="b")
- self.c = tf.constant(c_3d.reshape(n**4, n**2), tf.float32, name="c")
-
- def init_tensors(self, seed=None):
- # Initialize params such that the columns of theta_a and theta_b have L2
- # norm 1.
- def _param_initializer(shape, seed=None):
- x = tf.random_normal(shape, dtype=tf.float32, seed=seed)
- return tf.transpose(tf.nn.l2_normalize(tf.transpose(x), 1))
-
- return [_param_initializer(shape, seed) for shape in self.param_shapes]
-
- def objective(self, parameters, data=None, labels=None):
- theta_a = parameters[0]
- theta_b = parameters[1]
-
- # Compute theta_c from theta_a and theta_b.
- p = tf.matmul(self.a, theta_a) * tf.matmul(self.b, theta_b)
- p_trans = tf.transpose(p, name="p_trans")
- p_inv = tf.matmul(
- tf.matrix_inverse(tf.matmul(p_trans, p)), p_trans, name="p_inv")
- theta_c = tf.matmul(p_inv, self.c, name="theta_c")
-
- # Compute the "predicted" value of c.
- c_hat = tf.matmul(p, theta_c, name="c_hat")
-
- # Compute the loss (sum of squared errors).
- loss = tf.reduce_sum((c_hat - self.c)**2, name="loss")
-
- return loss
-
-
-def matmul_problem_sequence(n, k_min, k_max):
- """Helper to generate a sequence of matrix multiplication problems."""
- return [(_Spec(MatMulAlgorithm, (n, k), {}), None, None)
- for k in range(k_min, k_max + 1)]
-
-
-def init_fixed_variables(arrays):
- with tf.variable_scope(PARAMETER_SCOPE):
- params = [tf.Variable(arr.astype("float32")) for arr in arrays]
- return params
-
-
-def _mesh(xlim, ylim, n):
- """Creates a 2D meshgrid covering the given ranges.
-
- Args:
- xlim: int that defines the desired x-range (-xlim, xlim)
- ylim: int that defines the desired y-range (-ylim, ylim)
- n: number of points in each dimension of the mesh
-
- Returns:
- xm: 2D array of x-values in the mesh
- ym: 2D array of y-values in the mesh
- """
- return np.meshgrid(np.linspace(-xlim, xlim, n),
- np.linspace(-ylim, ylim, n))
diff --git a/research/learned_optimizer/problems/problem_sets.py b/research/learned_optimizer/problems/problem_sets.py
deleted file mode 100644
index eaf9273b87ef69c6b3087330bdf46c8de7107a15..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/problems/problem_sets.py
+++ /dev/null
@@ -1,561 +0,0 @@
-# Copyright 2017 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Groups of problems of different types for optimizer training."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import tensorflow as tf
-
-from learned_optimizer.problems import datasets
-from learned_optimizer.problems import model_adapter
-from learned_optimizer.problems import problem_generator as pg
-from learned_optimizer.problems import problem_spec
-
-_Spec = problem_spec.Spec
-
-
-def quadratic_problems():
- return [
- (_Spec(pg.Quadratic, (20,), {}), None, None),
- (_Spec(pg.Quadratic, (25,), {}), None, None),
- (_Spec(pg.Quadratic, (50,), {}), None, None),
- (_Spec(pg.Quadratic, (100,), {}), None, None),
- ]
-
-
-# Note: this group contains one non-noisy problem for historical reasons. The
-# original training set before the refactor included this set of quadratics.
-def quadratic_problems_noisy():
- return [
- (_Spec(pg.Quadratic, (20,), {"noise_stdev": 0.5}), None, None),
- (_Spec(pg.Quadratic, (25,), {"noise_stdev": 0.0}), None, None),
- (_Spec(pg.Quadratic, (50,), {"noise_stdev": 1.0}), None, None),
- (_Spec(pg.Quadratic, (100,), {"noise_stdev": 2.0}), None, None),
- ]
-
-
-def quadratic_problems_large():
- return [
- (_Spec(pg.Quadratic, (784,), {}), None, None),
- (_Spec(pg.Quadratic, (1024,), {}), None, None),
- (_Spec(pg.Quadratic, (2048,), {}), None, None),
- ]
-
-
-def bowl_problems():
- return [
- (_Spec(pg.Bowl, (0.1,), {"noise_stdev": 0.0}), None, None),
- (_Spec(pg.Bowl, (1.0,), {"noise_stdev": 0.0}), None, None),
- (_Spec(pg.Bowl, (5.0,), {"noise_stdev": 0.0}), None, None),
- (_Spec(pg.Bowl, (5.0,), {"noise_stdev": 0.0, "angle": np.pi / 4.}),
- None, None),
- ]
-
-
-def bowl_problems_noisy():
- return [
- (_Spec(pg.Bowl, (0.1,), {"noise_stdev": 0.1}), None, None),
- (_Spec(pg.Bowl, (1.0,), {"noise_stdev": 0.1}), None, None),
- (_Spec(pg.Bowl, (5.0,), {"noise_stdev": 0.1}), None, None),
- (_Spec(pg.Bowl, (5.0,), {"noise_stdev": 0.1, "angle": np.pi / 4.}),
- None, None),
- ]
-
-
-def sparse_softmax_2_class_sparse_problems():
- return [(_Spec(pg.SparseSoftmaxRegression, (5, 2), {"noise_stdev": 0.0}),
- datasets.noisy_parity_class(5, random_seed=123), 23),]
-
-
-def one_hot_sparse_softmax_2_class_sparse_problems():
- return [
- (_Spec(pg.OneHotSparseSoftmaxRegression, (5, 2), {"noise_stdev": 0.0}),
- datasets.noisy_parity_class(5, random_seed=123), 23),
- ]
-
-
-def softmax_2_class_problems():
- return [
- (_Spec(pg.SoftmaxRegression, (10, 2), {}), datasets.random(
- 10, 1000, random_seed=123, sep=2.0), 100),
- (_Spec(pg.SoftmaxRegression, (100, 2), {}), datasets.random(
- 100, 1000, random_seed=123), 50),
- (_Spec(pg.SoftmaxRegression, (200, 2), {}), datasets.random(
- 200, 1000, random_seed=123, sep=1.5), 20),
- (_Spec(pg.SoftmaxRegression, (256, 2), {}), datasets.random(
- 256, 1000, random_seed=123, sep=1.5), 100),
- ]
-
-
-def softmax_2_class_problems_noisy():
- return [
- (_Spec(pg.SoftmaxRegression, (10, 2), {"noise_stdev": 0.5}),
- datasets.random(10, 1000, random_seed=123, sep=2.0), 100),
- (_Spec(pg.SoftmaxRegression, (100, 2), {"noise_stdev": 0.1}),
- datasets.random(100, 1000, random_seed=123), 50),
- (_Spec(pg.SoftmaxRegression, (200, 2), {"noise_stdev": 0.1}),
- datasets.random(200, 1000, random_seed=123, sep=1.5), 20),
- (_Spec(pg.SoftmaxRegression, (256, 2), {"noise_stdev": 0.5}),
- datasets.random(256, 1000, random_seed=123, sep=1.5), 100),
- ]
-
-
-def optimization_test_problems():
- return [
- (_Spec(pg.Ackley, (), {}), None, None),
- (_Spec(pg.Beale, (), {}), None, None),
- (_Spec(pg.Booth, (), {}), None, None),
- (_Spec(pg.Branin, (), {}), None, None),
- (_Spec(pg.LogSumExp, (), {}), None, None),
- (_Spec(pg.Matyas, (), {}), None, None),
- (_Spec(pg.Michalewicz, (), {}), None, None),
- (_Spec(pg.Rosenbrock, (), {}), None, None),
- (_Spec(pg.StyblinskiTang, (), {}), None, None),
- ]
-
-
-def optimization_test_problems_noisy():
- return [
- (_Spec(pg.Ackley, (), {"noise_stdev": 1.}), None, None),
- (_Spec(pg.Beale, (), {"noise_stdev": 1.}), None, None),
- (_Spec(pg.Booth, (), {"noise_stdev": 1.}), None, None),
- (_Spec(pg.Branin, (), {"noise_stdev": 1.}), None, None),
- (_Spec(pg.LogSumExp, (), {"noise_stdev": 1.}), None, None),
- (_Spec(pg.Matyas, (), {"noise_stdev": 1.}), None, None),
- (_Spec(pg.Michalewicz, (), {"noise_stdev": 1.}), None, None),
- (_Spec(pg.Rosenbrock, (), {"noise_stdev": 1.}), None, None),
- (_Spec(pg.StyblinskiTang, (), {"noise_stdev": 1.}), None, None),
- ]
-
-
-def fully_connected_random_2_class_problems():
- return [
- (_Spec(pg.FullyConnected, (8, 2),
- {"hidden_sizes": (8, 5,), "activation": tf.nn.sigmoid}),
- datasets.random_mlp(8, 1000), 10),
- (_Spec(pg.FullyConnected, (12, 2),
- {"hidden_sizes": (8, 5, 3), "activation": tf.nn.sigmoid}),
- datasets.random_mlp(12, 1000), 200),
- (_Spec(pg.FullyConnected, (5, 2),
- {"hidden_sizes": (4, 4, 4, 4,), "activation": tf.nn.sigmoid}),
- datasets.random_mlp(5, 1000), 100),
- (_Spec(pg.FullyConnected, (11, 2),
- {"hidden_sizes": (4, 5, 6,), "activation": tf.nn.sigmoid}),
- datasets.random_mlp(11, 1000), 64),
- (_Spec(pg.FullyConnected, (9, 2),
- {"hidden_sizes": (8,), "activation": tf.nn.sigmoid}),
- datasets.random_mlp(9, 1000), 128),
- (_Spec(pg.FullyConnected, (7, 2),
- {"hidden_sizes": (8, 5,), "activation": tf.nn.sigmoid}),
- datasets.random_mlp(7, 1000), 16),
- (_Spec(pg.FullyConnected, (8, 2),
- {"hidden_sizes": (32, 64,), "activation": tf.nn.sigmoid}),
- datasets.random_mlp(8, 1000), 10),
- (_Spec(pg.FullyConnected, (12, 2),
- {"hidden_sizes": (16, 8, 3), "activation": tf.nn.sigmoid}),
- datasets.random_mlp(12, 1000), 200),
- (_Spec(pg.FullyConnected, (5, 2),
- {"hidden_sizes": (8, 8, 8, 8,), "activation": tf.nn.sigmoid}),
- datasets.random_mlp(5, 1000), 100),
- (_Spec(pg.FullyConnected, (11, 2),
- {"hidden_sizes": (10, 12, 12,), "activation": tf.nn.sigmoid}),
- datasets.random_mlp(11, 1000), 64),
- (_Spec(pg.FullyConnected, (9, 2),
- {"hidden_sizes": (32,), "activation": tf.nn.sigmoid}),
- datasets.random_mlp(9, 1000), 128),
- (_Spec(pg.FullyConnected, (7, 2),
- {"hidden_sizes": (32, 64,), "activation": tf.nn.sigmoid}),
- datasets.random_mlp(7, 1000), 16),
- ]
-
-
-def matmul_problems():
- return sum([
- pg.matmul_problem_sequence(2, 5, 8),
- pg.matmul_problem_sequence(3, 19, 24)], [])
-
-
-def log_objective_problems():
- return [
- (_Spec(pg.LogObjective, [_Spec(pg.Quadratic, (20,), {})], {}),
- None, None),
- (_Spec(pg.LogObjective, [_Spec(pg.Quadratic, (50,), {})], {}),
- None, None),
- (_Spec(pg.LogObjective, [_Spec(pg.Quadratic, (100,), {})], {}),
- None, None),
- (_Spec(pg.LogObjective, [_Spec(pg.Bowl, (0.1,), {})], {}), None, None),
- (_Spec(pg.LogObjective, [_Spec(pg.Bowl, (1.0,), {})], {}), None, None),
- (_Spec(pg.LogObjective, [_Spec(pg.Bowl, (5.0,), {})], {}), None, None),
- ]
-
-
-def sparse_gradient_problems():
- return [
- (_Spec(pg.SparseProblem, [_Spec(pg.Quadratic, (20,), {})], {}),
- None, None),
- (_Spec(pg.SparseProblem, [_Spec(pg.Quadratic, (50,), {})], {}),
- None, None),
- (_Spec(pg.SparseProblem, [_Spec(pg.Quadratic, (100,), {})], {}),
- None, None),
- (_Spec(pg.SparseProblem, [_Spec(pg.Bowl, (0.1,), {})], {}), None, None),
- (_Spec(pg.SparseProblem, [_Spec(pg.Bowl, (1.0,), {})], {}), None, None),
- (_Spec(pg.SparseProblem, [_Spec(pg.Bowl, (5.0,), {})], {}), None, None),
- ]
-
-
-def sparse_gradient_problems_mlp():
- return [
- (_Spec(pg.SparseProblem, [
- _Spec(pg.FullyConnected, (8, 2), {
- "hidden_sizes": (8, 5,),
- "activation": tf.nn.sigmoid
- })
- ], {}), datasets.random_mlp(8, 1000), 10),
- (_Spec(pg.SparseProblem, [
- _Spec(pg.FullyConnected, (12, 2), {
- "hidden_sizes": (8, 5, 3),
- "activation": tf.nn.sigmoid
- })
- ], {}), datasets.random_mlp(12, 1000), 200),
- (_Spec(pg.SparseProblem, [
- _Spec(pg.FullyConnected, (5, 2), {
- "hidden_sizes": (4, 4, 4, 4,),
- "activation": tf.nn.sigmoid
- })
- ], {}), datasets.random_mlp(5, 1000), 100),
- ]
-
-
-def rescale_problems():
- return [
- (_Spec(pg.Rescale, [_Spec(pg.Norm, (18,), {"norm_power": 2.5})],
- {"scale": 0.123}), None, None),
- (_Spec(pg.Rescale, [_Spec(pg.Norm, (18,), {"norm_power": 1.5})],
- {"scale": 8}), None, None),
- (_Spec(pg.Rescale, [_Spec(pg.Norm, (18,), {"norm_power": 2.})],
- {"scale": 50}), None, None),
- (_Spec(pg.Rescale, [_Spec(pg.Norm, (18,), {"norm_power": 3.})],
- {"scale": 200}), None, None),
- (_Spec(pg.Rescale, [_Spec(pg.Norm, (18,), {"norm_power": 1.})],
- {"scale": 1000}), None, None),
- (_Spec(pg.Rescale, [_Spec(pg.Quadratic, (20,), {})], {"scale": 0.1}),
- None, None),
- (_Spec(pg.Rescale, [_Spec(pg.Quadratic, (25,), {})], {"scale": 10.}),
- None, None),
- (_Spec(pg.Rescale, [_Spec(pg.Quadratic, (50,), {})], {"scale": 350.}),
- None, None),
- (_Spec(pg.Rescale, [_Spec(pg.Quadratic, (100,), {})], {"scale": 132}),
- None, None),
- ]
-
-
-def norm_problems():
- return [
- # < 1 Norm causes NaN gradients early in training.
- (_Spec(pg.Norm, (27,), {"norm_power": 1.}), None, None),
- (_Spec(pg.Norm, (25,), {"norm_power": 2.}), None, None),
- (_Spec(pg.Norm, (22,), {"norm_power": 3.}), None, None),
- ]
-
-
-def norm_problems_noisy():
- return [
- # < 1 Norm causes NaN gradients early in training.
- (_Spec(pg.Norm, (19,), {"noise_stdev": .1, "norm_power": 1.}),
- None, None),
- (_Spec(pg.Norm, (26,), {"noise_stdev": .1, "norm_power": 2.}),
- None, None),
- (_Spec(pg.Norm, (23,), {"noise_stdev": .1, "norm_power": 3.}),
- None, None),
- ]
-
-
-def sum_problems():
- return [
- (_Spec(pg.SumTask, [[
- _Spec(pg.Quadratic, (11,), {}),
- _Spec(pg.Quadratic, (3,), {}),
- _Spec(pg.Quadratic, (9,), {}),
- _Spec(pg.Quadratic, (7,), {}),
- _Spec(pg.Quadratic, (5,), {}),
- _Spec(pg.Quadratic, (13,), {}),
- _Spec(pg.Quadratic, (12,), {})
- ]], {}), None, None),
- (_Spec(pg.SumTask, [[
- _Spec(pg.Norm, (18,), {"norm_power": 3}),
- _Spec(pg.Quadratic, (25,), {}),
- _Spec(pg.Rosenbrock, (), {})
- ]], {}), None, None),
- (_Spec(pg.SumTask, [[
- _Spec(pg.Rosenbrock, (), {}),
- _Spec(pg.LogSumExp, (), {}),
- _Spec(pg.Ackley, (), {}),
- _Spec(pg.Beale, (), {}),
- _Spec(pg.Booth, (), {}),
- _Spec(pg.StyblinskiTang, (), {}),
- _Spec(pg.Matyas, (), {}),
- _Spec(pg.Branin, (), {}),
- _Spec(pg.Michalewicz, (), {})
- ]], {}), None, None),
- (_Spec(pg.SumTask, [[
- _Spec(pg.Rosenbrock, (), {}),
- _Spec(pg.LogSumExp, (), {}),
- _Spec(pg.Ackley, (), {}),
- _Spec(pg.Beale, (), {}),
- _Spec(pg.Booth, (), {}),
- _Spec(pg.StyblinskiTang, (), {}),
- _Spec(pg.Matyas, (), {}),
- _Spec(pg.Branin, (), {}),
- _Spec(pg.Michalewicz, (), {}),
- _Spec(pg.Quadratic, (5,), {}),
- _Spec(pg.Quadratic, (13,), {})
- ]], {}), None, None),
- (_Spec(pg.SumTask, [[
- _Spec(pg.Quadratic, (11,), {}),
- _Spec(pg.Quadratic, (3,), {})
- ]], {}), None, None),
- (_Spec(pg.SumTask, [[
- _Spec(pg.Rosenbrock, (), {}),
- _Spec(pg.LogSumExp, (), {}),
- _Spec(pg.Ackley, (), {})
- ]], {}), None, None),
- ]
-
-
-def sum_problems_noisy():
- return [
- (_Spec(pg.SumTask, [[
- _Spec(pg.Quadratic, (11,), {"noise_stdev": 0.1}),
- _Spec(pg.Quadratic, (3,), {"noise_stdev": 0.1}),
- _Spec(pg.Quadratic, (9,), {"noise_stdev": 0.1}),
- _Spec(pg.Quadratic, (7,), {"noise_stdev": 0.1}),
- _Spec(pg.Quadratic, (5,), {"noise_stdev": 0.1}),
- _Spec(pg.Quadratic, (13,), {"noise_stdev": 0.1}),
- _Spec(pg.Quadratic, (12,), {"noise_stdev": 0.1})
- ]], {}), None, None),
- (_Spec(pg.SumTask, [[
- _Spec(pg.Rosenbrock, (), {}),
- _Spec(pg.LogSumExp, (), {}),
- _Spec(pg.Ackley, (), {}),
- _Spec(pg.Beale, (), {}),
- _Spec(pg.Booth, (), {}),
- _Spec(pg.StyblinskiTang, (), {}),
- _Spec(pg.Matyas, (), {}),
- _Spec(pg.Branin, (), {}),
- _Spec(pg.Michalewicz, (), {}),
- _Spec(pg.Quadratic, (5,), {}),
- _Spec(pg.Quadratic, (13,), {"noise_stdev": 0.5})
- ]], {}), None, None),
- ]
-
-
-def dependency_chain_problems():
- return [
- (_Spec(pg.DependencyChain, (20,), {}), datasets.random_binary(
- 20, 1000), 100),
- (_Spec(pg.DependencyChain, (12,), {}), datasets.random_binary(
- 12, 200), 10),
- (_Spec(pg.DependencyChain, (56,), {}), datasets.random_binary(
- 56, 5000), 100),
- (_Spec(pg.DependencyChain, (64,), {}), datasets.random_binary(
- 64, 1000), 50),
- (_Spec(pg.DependencyChain, (13,), {}), datasets.random_binary(
- 13, 10000), 50),
- (_Spec(pg.DependencyChain, (20,), {}), datasets.random_binary(
- 20, 1000), 128),
- (_Spec(pg.DependencyChain, (12,), {}), datasets.random_binary(
- 12, 300), 16),
- (_Spec(pg.DependencyChain, (56,), {}), datasets.random_binary(
- 56, 5000), 128),
- (_Spec(pg.DependencyChain, (64,), {}), datasets.random_binary(
- 64, 1000), 64),
- (_Spec(pg.DependencyChain, (13,), {}), datasets.random_binary(
- 13, 10000), 32),
- ]
-
-
-def outward_snake_problems():
- return [
- (_Spec(pg.OutwardSnake, (20,), {}), datasets.random_binary(
- 20, 1000), 100),
- (_Spec(pg.OutwardSnake, (12,), {}), datasets.random_binary(
- 12, 200), 10),
- (_Spec(pg.OutwardSnake, (56,), {}), datasets.random_binary(
- 56, 5000), 100),
- (_Spec(pg.OutwardSnake, (64,), {}), datasets.random_binary(
- 64, 1000), 50),
- (_Spec(pg.OutwardSnake, (13,), {}), datasets.random_binary(
- 13, 10000), 50),
- (_Spec(pg.OutwardSnake, (20,), {}), datasets.random_binary(
- 20, 1000), 128),
- (_Spec(pg.OutwardSnake, (12,), {}), datasets.random_binary(
- 12, 300), 16),
- (_Spec(pg.OutwardSnake, (56,), {}), datasets.random_binary(
- 56, 5000), 128),
- (_Spec(pg.OutwardSnake, (64,), {}), datasets.random_binary(
- 64, 1000), 64),
- (_Spec(pg.OutwardSnake, (13,), {}), datasets.random_binary(
- 13, 10000), 32),
- ]
-
-
-def min_max_well_problems():
- return [
- (_Spec(pg.MinMaxWell, (20,), {}), None, None),
- (_Spec(pg.MinMaxWell, (12,), {}), None, None),
- (_Spec(pg.MinMaxWell, (56,), {}), None, None),
- (_Spec(pg.MinMaxWell, (64,), {}), None, None),
- (_Spec(pg.MinMaxWell, (13,), {}), None, None),
- ]
-
-
-def sum_of_quadratics_problems():
- return [
- (_Spec(pg.SumOfQuadratics, (20,), {}),
- datasets.random_symmetric(20, 1000), 100),
- (_Spec(pg.SumOfQuadratics, (12,), {}),
- datasets.random_symmetric(12, 100), 10),
- (_Spec(pg.SumOfQuadratics, (56,), {}),
- datasets.random_symmetric(56, 5000), 100),
- (_Spec(pg.SumOfQuadratics, (64,), {}),
- datasets.random_symmetric(64, 1000), 50),
- (_Spec(pg.SumOfQuadratics, (13,), {}),
- datasets.random_symmetric(13, 10000), 50),
- (_Spec(pg.SumOfQuadratics, (20,), {}),
- datasets.random_symmetric(20, 1000), 128),
- (_Spec(pg.SumOfQuadratics, (12,), {}),
- datasets.random_symmetric(12, 100), 16),
- (_Spec(pg.SumOfQuadratics, (56,), {}),
- datasets.random_symmetric(56, 5000), 128),
- (_Spec(pg.SumOfQuadratics, (64,), {}),
- datasets.random_symmetric(64, 1000), 64),
- (_Spec(pg.SumOfQuadratics, (13,), {}),
- datasets.random_symmetric(13, 10000), 32),
- ]
-
-
-def projection_quadratic_problems():
- return [
- (_Spec(pg.ProjectionQuadratic, (20,), {}),
- datasets.random_symmetric(20, 1000), 100),
- (_Spec(pg.ProjectionQuadratic, (12,), {}),
- datasets.random_symmetric(12, 100), 10),
- (_Spec(pg.ProjectionQuadratic, (56,), {}),
- datasets.random_symmetric(56, 5000), 100),
- (_Spec(pg.ProjectionQuadratic, (64,), {}),
- datasets.random_symmetric(64, 1000), 50),
- (_Spec(pg.ProjectionQuadratic, (13,), {}),
- datasets.random_symmetric(13, 10000), 50),
- (_Spec(pg.ProjectionQuadratic, (20,), {}),
- datasets.random_symmetric(20, 1000), 128),
- (_Spec(pg.ProjectionQuadratic, (12,), {}),
- datasets.random_symmetric(12, 100), 16),
- (_Spec(pg.ProjectionQuadratic, (56,), {}),
- datasets.random_symmetric(56, 5000), 128),
- (_Spec(pg.ProjectionQuadratic, (64,), {}),
- datasets.random_symmetric(64, 1000), 64),
- (_Spec(pg.ProjectionQuadratic, (13,), {}),
- datasets.random_symmetric(13, 10000), 32),
- ]
-
-
-def adapter_rosenbrock_local():
- return [(_Spec(model_adapter.ModelAdapter,
- (pg.make_rosenbrock_loss_and_init,), {}), None, None),]
-
-
-def adapter_rosenbrock_worker():
- return [(_Spec(model_adapter.ModelAdapter,
- (pg.make_rosenbrock_loss_and_init,),
- {"device": "/job:worker"}), None, None),]
-
-
-def _test_problem_mlp_scaled_init_small():
- return [
- np.random.randn(10, 32) * np.sqrt(2./10),
- np.random.randn(32,) * 0.1,
- np.random.randn(32, 64) * np.sqrt(2./32.),
- np.random.randn(64,) * 0.1,
- np.random.randn(64, 2) * np.sqrt(2./64.),
- np.random.randn(2,) * 0.1
- ]
-
-
-def _test_problem_mlp_scaled_init_large():
- return [
- np.random.randn(20, 32) * np.sqrt(2./20),
- np.random.randn(32,) * 0.1,
- np.random.randn(32, 64) * np.sqrt(2./32.),
- np.random.randn(64,) * 0.1,
- np.random.randn(64, 10) * np.sqrt(2./64.),
- np.random.randn(10,) * 0.1
- ]
-
-
-def _test_problem_mlp_scaled_init_mnist():
- return [
- np.random.randn(784, 64) * np.sqrt(2./784.),
- np.random.randn(64,) * 0.1,
- np.random.randn(64, 10) * np.sqrt(2./ 64.),
- np.random.randn(10,) * 0.1,
- ]
-
-
-# Wrap this construction in a function to avoid UnparsedFlagAccessError
-def test_problems():
- """Test problems for visualizations."""
- # Unlike the training problem sets, these test problems are made up of
- # length-5 tuples. The final items in the tuple are the name of the problem
- # and the initialization random_seed for testing consistency.
- tp = [
- (_Spec(pg.Quadratic, (20,), {"random_seed": 1234}), None, None,
- "quad_problem", 5678),
- (_Spec(pg.Quadratic, (20,), {"noise_stdev": 1.0, "random_seed": 1234}),
- None, None, "quad_problem_noise", 5678),
- (_Spec(pg.Rosenbrock, (), {"random_seed": 1234}), None, None,
- "rosenbrock", 5678),
- (_Spec(pg.Rosenbrock, (), {"random_seed": 1234, "noise_stdev": 1.0}),
- None, None, "rosenbrock_noise", 5678),
- (_Spec(pg.SoftmaxRegression, (10, 2), {}), datasets.random(
- 10, 10000, random_seed=1234), 100, "softmax", 5678),
- (_Spec(pg.SoftmaxRegression, (10, 2), {"noise_stdev": 1.0}),
- datasets.random(10, 10000, random_seed=1234), 100, "softmax_noise",
- 5678),
- (_Spec(pg.FullyConnected, (10, 2), {}), datasets.random(
- 10, 10000, random_seed=1234), 100, "mlp_small",
- _test_problem_mlp_scaled_init_small()),
- (_Spec(pg.FullyConnected, (20, 10), {}), datasets.random(
- 20, 10000, n_classes=10, random_seed=1234), 100, "mlp_large",
- _test_problem_mlp_scaled_init_large()),
- (_Spec(pg.FullyConnected, (784, 10),
- {"hidden_sizes": (64,), "activation": tf.nn.sigmoid}),
- datasets.mnist(), 64, "mlp_mnist_sigmoid",
- _test_problem_mlp_scaled_init_mnist()),
- (_Spec(pg.FullyConnected, (784, 10),
- {"hidden_sizes": (64,), "activation": tf.nn.relu}),
- datasets.mnist(), 64, "mlp_mnist_relu",
- _test_problem_mlp_scaled_init_mnist()),
- (_Spec(pg.ConvNet, ((1, 28, 28), 10, [(3, 3, 8), (5, 5, 8)]),
- {"activation": tf.nn.sigmoid}), datasets.mnist(), 64,
- "convnet_mnist_sigmoid", None),
- (_Spec(pg.ConvNet, ((1, 28, 28), 10, [(3, 3, 8), (5, 5, 8)]),
- {"activation": tf.nn.relu}), datasets.mnist(), 64,
- "convnet_mnist_relu", None),
- ]
- return tp
diff --git a/research/learned_optimizer/problems/problem_spec.py b/research/learned_optimizer/problems/problem_spec.py
deleted file mode 100644
index e30c47b277e5c8b3b8aba3b8d691a2af3a595ef6..0000000000000000000000000000000000000000
--- a/research/learned_optimizer/problems/problem_spec.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright 2017 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Wrapper around a training problem."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from collections import namedtuple
-
-
-class Spec(namedtuple("Spec", "callable args kwargs")):
- """Syntactic sugar for keeping track of a function/class + args."""
-
- # Since this is an immutable object, we don't need to reserve slots.
- __slots__ = ()
-
- def build(self):
- """Returns the output of the callable."""
- return self.callable(*self.args, **self.kwargs)
diff --git a/research/learning_to_remember_rare_events/README.md b/research/learning_to_remember_rare_events/README.md
deleted file mode 100644
index 2eeadea784d4d22efc88c56e482c5d5374c90e24..0000000000000000000000000000000000000000
--- a/research/learning_to_remember_rare_events/README.md
+++ /dev/null
@@ -1,61 +0,0 @@
-
-
-
-
----
-
-Code for the Memory Module as described
-in "Learning to Remember Rare Events" by
-Lukasz Kaiser, Ofir Nachum, Aurko Roy, and Samy Bengio
-published as a conference paper at ICLR 2017.
-
-Requirements:
-* TensorFlow (see tensorflow.org for how to install)
-* Some basic command-line utilities (git, unzip).
-
-Description:
-
-The general memory module is located in memory.py.
-Some code is provided to see the memory module in
-action on the standard Omniglot dataset.
-Download and setup the dataset using data_utils.py
-and then run the training script train.py
-(see example commands below).
-
-Note that the structure and parameters of the model
-are optimized for the data preparation as provided.
-
-Quick Start:
-
-First download and set-up Omniglot data by running
-
-```
-python data_utils.py
-```
-
-Then run the training script:
-
-```
-python train.py --memory_size=8192 \
- --batch_size=16 --validation_length=50 \
- --episode_width=5 --episode_length=30
-```
-
-The first validation batch may look like this (although it is noisy):
-```
-0-shot: 0.040, 1-shot: 0.404, 2-shot: 0.516, 3-shot: 0.604,
- 4-shot: 0.656, 5-shot: 0.684
-```
-At step 500 you may see something like this:
-```
-0-shot: 0.036, 1-shot: 0.836, 2-shot: 0.900, 3-shot: 0.940,
- 4-shot: 0.944, 5-shot: 0.916
-```
-At step 4000 you may see something like this:
-```
-0-shot: 0.044, 1-shot: 0.960, 2-shot: 1.000, 3-shot: 0.988,
- 4-shot: 0.972, 5-shot: 0.992
-```
-
-Maintained by Ofir Nachum (ofirnachum) and
-Lukasz Kaiser (lukaszkaiser).
diff --git a/research/learning_to_remember_rare_events/data_utils.py b/research/learning_to_remember_rare_events/data_utils.py
deleted file mode 100644
index 03d5dafb251d4e058a6780b447aabdcd1a84a1d4..0000000000000000000000000000000000000000
--- a/research/learning_to_remember_rare_events/data_utils.py
+++ /dev/null
@@ -1,243 +0,0 @@
-# Copyright 2017 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# ==============================================================================
-"""Data loading and other utilities.
-
-Use this file to first copy over and pre-process the Omniglot dataset.
-Simply call
- python data_utils.py
-"""
-
-import logging
-import os
-import subprocess
-from six.moves import cPickle as pickle
-
-import numpy as np
-from scipy.misc import imresize
-from scipy.misc import imrotate
-from scipy.ndimage import imread
-from six.moves import xrange
-import tensorflow as tf
-
-
-MAIN_DIR = ''
-REPO_LOCATION = 'https://github.com/brendenlake/omniglot.git'
-REPO_DIR = os.path.join(MAIN_DIR, 'omniglot')
-DATA_DIR = os.path.join(REPO_DIR, 'python')
-TRAIN_DIR = os.path.join(DATA_DIR, 'images_background')
-TEST_DIR = os.path.join(DATA_DIR, 'images_evaluation')
-DATA_FILE_FORMAT = os.path.join(MAIN_DIR, '%s_omni.pkl')
-
-TRAIN_ROTATIONS = True # augment training data with rotations
-TEST_ROTATIONS = False # augment testing data with rotations
-IMAGE_ORIGINAL_SIZE = 105
-IMAGE_NEW_SIZE = 28
-
-
-def get_data():
- """Get data in form suitable for episodic training.
-
- Returns:
- Train and test data as dictionaries mapping
- label to list of examples.
- """
- with tf.gfile.GFile(DATA_FILE_FORMAT % 'train', 'rb') as f:
- processed_train_data = pickle.load(f)
- with tf.gfile.GFile(DATA_FILE_FORMAT % 'test', 'rb') as f:
- processed_test_data = pickle.load(f)
-
- train_data = {}
- test_data = {}
-
- for data, processed_data in zip([train_data, test_data],
- [processed_train_data, processed_test_data]):
- for image, label in zip(processed_data['images'],
- processed_data['labels']):
- if label not in data:
- data[label] = []
- data[label].append(image.reshape([-1]).astype('float32'))
-
- intersection = set(train_data.keys()) & set(test_data.keys())
- assert not intersection, 'Train and test data intersect.'
- ok_num_examples = [len(ll) == 20 for _, ll in train_data.items()]
- assert all(ok_num_examples), 'Bad number of examples in train data.'
- ok_num_examples = [len(ll) == 20 for _, ll in test_data.items()]
- assert all(ok_num_examples), 'Bad number of examples in test data.'
-
- logging.info('Number of labels in train data: %d.', len(train_data))
- logging.info('Number of labels in test data: %d.', len(test_data))
-
- return train_data, test_data
-
-
-def crawl_directory(directory, augment_with_rotations=False,
- first_label=0):
- """Crawls data directory and returns stuff."""
- label_idx = first_label
- images = []
- labels = []
- info = []
-
- # traverse root directory
- for root, _, files in os.walk(directory):
- logging.info('Reading files from %s', root)
- fileflag = 0
- for file_name in files:
- full_file_name = os.path.join(root, file_name)
- img = imread(full_file_name, flatten=True)
- for i, angle in enumerate([0, 90, 180, 270]):
- if not augment_with_rotations and i > 0:
- break
-
- images.append(imrotate(img, angle))
- labels.append(label_idx + i)
- info.append(full_file_name)
-
- fileflag = 1
-
- if fileflag:
- label_idx += 4 if augment_with_rotations else 1
-
- return images, labels, info
-
-
-def resize_images(images, new_width, new_height):
- """Resize images to new dimensions."""
- resized_images = np.zeros([images.shape[0], new_width, new_height],
- dtype=np.float32)
-
- for i in range(images.shape[0]):
- resized_images[i, :, :] = imresize(images[i, :, :],
- [new_width, new_height],
- interp='bilinear',
- mode=None)
- return resized_images
-
-
-def write_datafiles(directory, write_file,
- resize=True, rotate=False,
- new_width=IMAGE_NEW_SIZE, new_height=IMAGE_NEW_SIZE,
- first_label=0):
- """Load and preprocess images from a directory and write them to a file.
-
- Args:
- directory: Directory of alphabet sub-directories.
- write_file: Filename to write to.
- resize: Whether to resize the images.
- rotate: Whether to augment the dataset with rotations.
- new_width: New resize width.
- new_height: New resize height.
- first_label: Label to start with.
-
- Returns:
- Number of new labels created.
- """
-
- # these are the default sizes for Omniglot:
- imgwidth = IMAGE_ORIGINAL_SIZE
- imgheight = IMAGE_ORIGINAL_SIZE
-
- logging.info('Reading the data.')
- images, labels, info = crawl_directory(directory,
- augment_with_rotations=rotate,
- first_label=first_label)
-
- images_np = np.zeros([len(images), imgwidth, imgheight], dtype=np.bool)
- labels_np = np.zeros([len(labels)], dtype=np.uint32)
- for i in xrange(len(images)):
- images_np[i, :, :] = images[i]
- labels_np[i] = labels[i]
-
- if resize:
- logging.info('Resizing images.')
- resized_images = resize_images(images_np, new_width, new_height)
-
- logging.info('Writing resized data in float32 format.')
- data = {'images': resized_images,
- 'labels': labels_np,
- 'info': info}
- with tf.gfile.GFile(write_file, 'w') as f:
- pickle.dump(data, f)
- else:
- logging.info('Writing original sized data in boolean format.')
- data = {'images': images_np,
- 'labels': labels_np,
- 'info': info}
- with tf.gfile.GFile(write_file, 'w') as f:
- pickle.dump(data, f)
-
- return len(np.unique(labels_np))
-
-
-def maybe_download_data():
- """Download Omniglot repo if it does not exist."""
- if os.path.exists(REPO_DIR):
- logging.info('It appears that Git repo already exists.')
- else:
- logging.info('It appears that Git repo does not exist.')
- logging.info('Cloning now.')
-
- subprocess.check_output('git clone %s' % REPO_LOCATION, shell=True)
-
- if os.path.exists(TRAIN_DIR):
- logging.info('It appears that train data has already been unzipped.')
- else:
- logging.info('It appears that train data has not been unzipped.')
- logging.info('Unzipping now.')
-
- subprocess.check_output('unzip %s.zip -d %s' % (TRAIN_DIR, DATA_DIR),
- shell=True)
-
- if os.path.exists(TEST_DIR):
- logging.info('It appears that test data has already been unzipped.')
- else:
- logging.info('It appears that test data has not been unzipped.')
- logging.info('Unzipping now.')
-
- subprocess.check_output('unzip %s.zip -d %s' % (TEST_DIR, DATA_DIR),
- shell=True)
-
-
-def preprocess_omniglot():
- """Download and prepare raw Omniglot data.
-
- Downloads the data from GitHub if it does not exist.
- Then load the images, augment with rotations if desired.
- Resize the images and write them to a pickle file.
- """
-
- maybe_download_data()
-
- directory = TRAIN_DIR
- write_file = DATA_FILE_FORMAT % 'train'
- num_labels = write_datafiles(
- directory, write_file, resize=True, rotate=TRAIN_ROTATIONS,
- new_width=IMAGE_NEW_SIZE, new_height=IMAGE_NEW_SIZE)
-
- directory = TEST_DIR
- write_file = DATA_FILE_FORMAT % 'test'
- write_datafiles(directory, write_file, resize=True, rotate=TEST_ROTATIONS,
- new_width=IMAGE_NEW_SIZE, new_height=IMAGE_NEW_SIZE,
- first_label=num_labels)
-
-
-def main(unused_argv):
- logging.basicConfig(level=logging.INFO)
- preprocess_omniglot()
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/learning_to_remember_rare_events/memory.py b/research/learning_to_remember_rare_events/memory.py
deleted file mode 100644
index 2f40ff57f9434994f08b1ad97dc23142bb23daaa..0000000000000000000000000000000000000000
--- a/research/learning_to_remember_rare_events/memory.py
+++ /dev/null
@@ -1,392 +0,0 @@
-# Copyright 2017 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# ==============================================================================
-"""Memory module for storing "nearest neighbors".
-
-Implements a key-value memory for generalized one-shot learning
-as described in the paper
-"Learning to Remember Rare Events"
-by Lukasz Kaiser, Ofir Nachum, Aurko Roy, Samy Bengio,
-published as a conference paper at ICLR 2017.
-"""
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-
-class Memory(object):
- """Memory module."""
-
- def __init__(self, key_dim, memory_size, vocab_size,
- choose_k=256, alpha=0.1, correct_in_top=1, age_noise=8.0,
- var_cache_device='', nn_device=''):
- self.key_dim = key_dim
- self.memory_size = memory_size
- self.vocab_size = vocab_size
- self.choose_k = min(choose_k, memory_size)
- self.alpha = alpha
- self.correct_in_top = correct_in_top
- self.age_noise = age_noise
- self.var_cache_device = var_cache_device # Variables are cached here.
- self.nn_device = nn_device # Device to perform nearest neighbour matmul.
-
- caching_device = var_cache_device if var_cache_device else None
- self.update_memory = tf.constant(True) # Can be fed "false" if needed.
- self.mem_keys = tf.get_variable(
- 'memkeys', [self.memory_size, self.key_dim], trainable=False,
- initializer=tf.random_uniform_initializer(-0.0, 0.0),
- caching_device=caching_device)
- self.mem_vals = tf.get_variable(
- 'memvals', [self.memory_size], dtype=tf.int32, trainable=False,
- initializer=tf.constant_initializer(0, tf.int32),
- caching_device=caching_device)
- self.mem_age = tf.get_variable(
- 'memage', [self.memory_size], dtype=tf.float32, trainable=False,
- initializer=tf.constant_initializer(0.0), caching_device=caching_device)
- self.recent_idx = tf.get_variable(
- 'recent_idx', [self.vocab_size], dtype=tf.int32, trainable=False,
- initializer=tf.constant_initializer(0, tf.int32))
-
- # variable for projecting query vector into memory key
- self.query_proj = tf.get_variable(
- 'memory_query_proj', [self.key_dim, self.key_dim], dtype=tf.float32,
- initializer=tf.truncated_normal_initializer(0, 0.01),
- caching_device=caching_device)
-
- def get(self):
- return self.mem_keys, self.mem_vals, self.mem_age, self.recent_idx
-
- def set(self, k, v, a, r=None):
- return tf.group(
- self.mem_keys.assign(k),
- self.mem_vals.assign(v),
- self.mem_age.assign(a),
- (self.recent_idx.assign(r) if r is not None else tf.group()))
-
- def clear(self):
- return tf.variables_initializer([self.mem_keys, self.mem_vals, self.mem_age,
- self.recent_idx])
-
- def get_hint_pool_idxs(self, normalized_query):
- """Get small set of idxs to compute nearest neighbor queries on.
-
- This is an expensive look-up on the whole memory that is used to
- avoid more expensive operations later on.
-
- Args:
- normalized_query: A Tensor of shape [None, key_dim].
-
- Returns:
- A Tensor of shape [None, choose_k] of indices in memory
- that are closest to the queries.
-
- """
- # look up in large memory, no gradients
- with tf.device(self.nn_device):
- similarities = tf.matmul(tf.stop_gradient(normalized_query),
- self.mem_keys, transpose_b=True, name='nn_mmul')
- _, hint_pool_idxs = tf.nn.top_k(
- tf.stop_gradient(similarities), k=self.choose_k, name='nn_topk')
- return hint_pool_idxs
-
- def make_update_op(self, upd_idxs, upd_keys, upd_vals,
- batch_size, use_recent_idx, intended_output):
- """Function that creates all the update ops."""
- mem_age_incr = self.mem_age.assign_add(tf.ones([self.memory_size],
- dtype=tf.float32))
- with tf.control_dependencies([mem_age_incr]):
- mem_age_upd = tf.scatter_update(
- self.mem_age, upd_idxs, tf.zeros([batch_size], dtype=tf.float32))
-
- mem_key_upd = tf.scatter_update(
- self.mem_keys, upd_idxs, upd_keys)
- mem_val_upd = tf.scatter_update(
- self.mem_vals, upd_idxs, upd_vals)
-
- if use_recent_idx:
- recent_idx_upd = tf.scatter_update(
- self.recent_idx, intended_output, upd_idxs)
- else:
- recent_idx_upd = tf.group()
-
- return tf.group(mem_age_upd, mem_key_upd, mem_val_upd, recent_idx_upd)
-
- def query(self, query_vec, intended_output, use_recent_idx=True):
- """Queries memory for nearest neighbor.
-
- Args:
- query_vec: A batch of vectors to query (embedding of input to model).
- intended_output: The values that would be the correct output of the
- memory.
- use_recent_idx: Whether to always insert at least one instance of a
- correct memory fetch.
-
- Returns:
- A tuple (result, mask, teacher_loss).
- result: The result of the memory look up.
- mask: The affinity of the query to the result.
- teacher_loss: The loss for training the memory module.
- """
-
- batch_size = tf.shape(query_vec)[0]
- output_given = intended_output is not None
-
- # prepare query for memory lookup
- query_vec = tf.matmul(query_vec, self.query_proj)
- normalized_query = tf.nn.l2_normalize(query_vec, dim=1)
-
- hint_pool_idxs = self.get_hint_pool_idxs(normalized_query)
-
- if output_given and use_recent_idx: # add at least one correct memory
- most_recent_hint_idx = tf.gather(self.recent_idx, intended_output)
- hint_pool_idxs = tf.concat(
- axis=1,
- values=[hint_pool_idxs, tf.expand_dims(most_recent_hint_idx, 1)])
- choose_k = tf.shape(hint_pool_idxs)[1]
-
- with tf.device(self.var_cache_device):
- # create small memory and look up with gradients
- my_mem_keys = tf.stop_gradient(tf.gather(self.mem_keys, hint_pool_idxs,
- name='my_mem_keys_gather'))
- similarities = tf.matmul(tf.expand_dims(normalized_query, 1),
- my_mem_keys, adjoint_b=True, name='batch_mmul')
- hint_pool_sims = tf.squeeze(similarities, [1], name='hint_pool_sims')
- hint_pool_mem_vals = tf.gather(self.mem_vals, hint_pool_idxs,
- name='hint_pool_mem_vals')
- # Calculate softmax mask on the top-k if requested.
- # Softmax temperature. Say we have K elements at dist x and one at (x+a).
- # Softmax of the last is e^tm(x+a)/Ke^tm*x + e^tm(x+a) = e^tm*a/K+e^tm*a.
- # To make that 20% we'd need to have e^tm*a ~= 0.2K, so tm = log(0.2K)/a.
- softmax_temp = max(1.0, np.log(0.2 * self.choose_k) / self.alpha)
- mask = tf.nn.softmax(hint_pool_sims[:, :choose_k - 1] * softmax_temp)
-
- # prepare returned values
- nearest_neighbor = tf.to_int32(
- tf.argmax(hint_pool_sims[:, :choose_k - 1], 1))
-
- no_teacher_idxs = tf.gather(
- tf.reshape(hint_pool_idxs, [-1]),
- nearest_neighbor + choose_k * tf.range(batch_size))
-
- with tf.device(self.var_cache_device):
- result = tf.gather(self.mem_vals, tf.reshape(no_teacher_idxs, [-1]))
-
- if not output_given:
- teacher_loss = None
- return result, mask, teacher_loss
-
- # prepare hints from the teacher on hint pool
- teacher_hints = tf.to_float(
- tf.abs(tf.expand_dims(intended_output, 1) - hint_pool_mem_vals))
- teacher_hints = 1.0 - tf.minimum(1.0, teacher_hints)
-
- teacher_vals, teacher_hint_idxs = tf.nn.top_k(
- hint_pool_sims * teacher_hints, k=1)
- neg_teacher_vals, _ = tf.nn.top_k(
- hint_pool_sims * (1 - teacher_hints), k=1)
-
- # bring back idxs to full memory
- teacher_idxs = tf.gather(
- tf.reshape(hint_pool_idxs, [-1]),
- teacher_hint_idxs[:, 0] + choose_k * tf.range(batch_size))
-
- # zero-out teacher_vals if there are no hints
- teacher_vals *= (
- 1 - tf.to_float(tf.equal(0.0, tf.reduce_sum(teacher_hints, 1))))
-
- # we'll determine whether to do an update to memory based on whether
- # memory was queried correctly
- sliced_hints = tf.slice(teacher_hints, [0, 0], [-1, self.correct_in_top])
- incorrect_memory_lookup = tf.equal(0.0, tf.reduce_sum(sliced_hints, 1))
-
- # loss based on triplet loss
- teacher_loss = (tf.nn.relu(neg_teacher_vals - teacher_vals + self.alpha)
- - self.alpha)
-
- # prepare memory updates
- update_keys = normalized_query
- update_vals = intended_output
-
- fetched_idxs = teacher_idxs # correctly fetched from memory
- with tf.device(self.var_cache_device):
- fetched_keys = tf.gather(self.mem_keys, fetched_idxs, name='fetched_keys')
- fetched_vals = tf.gather(self.mem_vals, fetched_idxs, name='fetched_vals')
-
- # do memory updates here
- fetched_keys_upd = update_keys + fetched_keys # Momentum-like update
- fetched_keys_upd = tf.nn.l2_normalize(fetched_keys_upd, dim=1)
- # Randomize age a bit, e.g., to select different ones in parallel workers.
- mem_age_with_noise = self.mem_age + tf.random_uniform(
- [self.memory_size], - self.age_noise, self.age_noise)
-
- _, oldest_idxs = tf.nn.top_k(mem_age_with_noise, k=batch_size, sorted=False)
-
- with tf.control_dependencies([result]):
- upd_idxs = tf.where(incorrect_memory_lookup,
- oldest_idxs,
- fetched_idxs)
- # upd_idxs = tf.Print(upd_idxs, [upd_idxs], "UPD IDX", summarize=8)
- upd_keys = tf.where(incorrect_memory_lookup,
- update_keys,
- fetched_keys_upd)
- upd_vals = tf.where(incorrect_memory_lookup,
- update_vals,
- fetched_vals)
-
- def make_update_op():
- return self.make_update_op(upd_idxs, upd_keys, upd_vals,
- batch_size, use_recent_idx, intended_output)
-
- update_op = tf.cond(self.update_memory, make_update_op, tf.no_op)
-
- with tf.control_dependencies([update_op]):
- result = tf.identity(result)
- mask = tf.identity(mask)
- teacher_loss = tf.identity(teacher_loss)
-
- return result, mask, tf.reduce_mean(teacher_loss)
-
-
-class LSHMemory(Memory):
- """Memory employing locality sensitive hashing.
-
- Note: Not fully tested.
- """
-
- def __init__(self, key_dim, memory_size, vocab_size,
- choose_k=256, alpha=0.1, correct_in_top=1, age_noise=8.0,
- var_cache_device='', nn_device='',
- num_hashes=None, num_libraries=None):
- super(LSHMemory, self).__init__(
- key_dim, memory_size, vocab_size,
- choose_k=choose_k, alpha=alpha, correct_in_top=1, age_noise=age_noise,
- var_cache_device=var_cache_device, nn_device=nn_device)
-
- self.num_libraries = num_libraries or int(self.choose_k ** 0.5)
- self.num_per_hash_slot = max(1, self.choose_k // self.num_libraries)
- self.num_hashes = (num_hashes or
- int(np.log2(self.memory_size / self.num_per_hash_slot)))
- self.num_hashes = min(max(self.num_hashes, 1), 20)
- self.num_hash_slots = 2 ** self.num_hashes
-
- # hashing vectors
- self.hash_vecs = [
- tf.get_variable(
- 'hash_vecs%d' % i, [self.num_hashes, self.key_dim],
- dtype=tf.float32, trainable=False,
- initializer=tf.truncated_normal_initializer(0, 1))
- for i in xrange(self.num_libraries)]
-
- # map representing which hash slots map to which mem keys
- self.hash_slots = [
- tf.get_variable(
- 'hash_slots%d' % i, [self.num_hash_slots, self.num_per_hash_slot],
- dtype=tf.int32, trainable=False,
- initializer=tf.random_uniform_initializer(maxval=self.memory_size,
- dtype=tf.int32))
- for i in xrange(self.num_libraries)]
-
- def get(self): # not implemented
- return self.mem_keys, self.mem_vals, self.mem_age, self.recent_idx
-
- def set(self, k, v, a, r=None): # not implemented
- return tf.group(
- self.mem_keys.assign(k),
- self.mem_vals.assign(v),
- self.mem_age.assign(a),
- (self.recent_idx.assign(r) if r is not None else tf.group()))
-
- def clear(self):
- return tf.variables_initializer([self.mem_keys, self.mem_vals, self.mem_age,
- self.recent_idx] + self.hash_slots)
-
- def get_hash_slots(self, query):
- """Gets hashed-to buckets for batch of queries.
-
- Args:
- query: 2-d Tensor of query vectors.
-
- Returns:
- A list of hashed-to buckets for each hash function.
- """
-
- binary_hash = [
- tf.less(tf.matmul(query, self.hash_vecs[i], transpose_b=True), 0)
- for i in xrange(self.num_libraries)]
- hash_slot_idxs = [
- tf.reduce_sum(
- tf.to_int32(binary_hash[i]) *
- tf.constant([[2 ** i for i in xrange(self.num_hashes)]],
- dtype=tf.int32), 1)
- for i in xrange(self.num_libraries)]
- return hash_slot_idxs
-
- def get_hint_pool_idxs(self, normalized_query):
- """Get small set of idxs to compute nearest neighbor queries on.
-
- This is an expensive look-up on the whole memory that is used to
- avoid more expensive operations later on.
-
- Args:
- normalized_query: A Tensor of shape [None, key_dim].
-
- Returns:
- A Tensor of shape [None, choose_k] of indices in memory
- that are closest to the queries.
-
- """
- # get hash of query vecs
- hash_slot_idxs = self.get_hash_slots(normalized_query)
-
- # grab mem idxs in the hash slots
- hint_pool_idxs = [
- tf.maximum(tf.minimum(
- tf.gather(self.hash_slots[i], idxs),
- self.memory_size - 1), 0)
- for i, idxs in enumerate(hash_slot_idxs)]
-
- return tf.concat(axis=1, values=hint_pool_idxs)
-
- def make_update_op(self, upd_idxs, upd_keys, upd_vals,
- batch_size, use_recent_idx, intended_output):
- """Function that creates all the update ops."""
- base_update_op = super(LSHMemory, self).make_update_op(
- upd_idxs, upd_keys, upd_vals,
- batch_size, use_recent_idx, intended_output)
-
- # compute hash slots to be updated
- hash_slot_idxs = self.get_hash_slots(upd_keys)
-
- # make updates
- update_ops = []
- with tf.control_dependencies([base_update_op]):
- for i, slot_idxs in enumerate(hash_slot_idxs):
- # for each slot, choose which entry to replace
- entry_idx = tf.random_uniform([batch_size],
- maxval=self.num_per_hash_slot,
- dtype=tf.int32)
- entry_mul = 1 - tf.one_hot(entry_idx, self.num_per_hash_slot,
- dtype=tf.int32)
- entry_add = (tf.expand_dims(upd_idxs, 1) *
- tf.one_hot(entry_idx, self.num_per_hash_slot,
- dtype=tf.int32))
-
- mul_op = tf.scatter_mul(self.hash_slots[i], slot_idxs, entry_mul)
- with tf.control_dependencies([mul_op]):
- add_op = tf.scatter_add(self.hash_slots[i], slot_idxs, entry_add)
- update_ops.append(add_op)
-
- return tf.group(*update_ops)
diff --git a/research/learning_to_remember_rare_events/model.py b/research/learning_to_remember_rare_events/model.py
deleted file mode 100644
index 7a6b460047fda3349c04d0e024c035f69a300461..0000000000000000000000000000000000000000
--- a/research/learning_to_remember_rare_events/model.py
+++ /dev/null
@@ -1,302 +0,0 @@
-# Copyright 2017 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# ==============================================================================
-"""Model using memory component.
-
-The model embeds images using a standard CNN architecture.
-These embeddings are used as keys to the memory component,
-which returns nearest neighbors.
-"""
-
-import tensorflow as tf
-
-import memory
-
-FLAGS = tf.flags.FLAGS
-
-
-class BasicClassifier(object):
-
- def __init__(self, output_dim):
- self.output_dim = output_dim
-
- def core_builder(self, memory_val, x, y):
- del x, y
- y_pred = memory_val
- loss = 0.0
-
- return loss, y_pred
-
-
-class LeNet(object):
- """Standard CNN architecture."""
-
- def __init__(self, image_size, num_channels, hidden_dim):
- self.image_size = image_size
- self.num_channels = num_channels
- self.hidden_dim = hidden_dim
- self.matrix_init = tf.truncated_normal_initializer(stddev=0.1)
- self.vector_init = tf.constant_initializer(0.0)
-
- def core_builder(self, x):
- """Embeds x using standard CNN architecture.
-
- Args:
- x: Batch of images as a 2-d Tensor [batch_size, -1].
-
- Returns:
- A 2-d Tensor [batch_size, hidden_dim] of embedded images.
- """
-
- ch1 = 32 * 2 # number of channels in 1st layer
- ch2 = 64 * 2 # number of channels in 2nd layer
- conv1_weights = tf.get_variable('conv1_w',
- [3, 3, self.num_channels, ch1],
- initializer=self.matrix_init)
- conv1_biases = tf.get_variable('conv1_b', [ch1],
- initializer=self.vector_init)
- conv1a_weights = tf.get_variable('conv1a_w',
- [3, 3, ch1, ch1],
- initializer=self.matrix_init)
- conv1a_biases = tf.get_variable('conv1a_b', [ch1],
- initializer=self.vector_init)
-
- conv2_weights = tf.get_variable('conv2_w', [3, 3, ch1, ch2],
- initializer=self.matrix_init)
- conv2_biases = tf.get_variable('conv2_b', [ch2],
- initializer=self.vector_init)
- conv2a_weights = tf.get_variable('conv2a_w', [3, 3, ch2, ch2],
- initializer=self.matrix_init)
- conv2a_biases = tf.get_variable('conv2a_b', [ch2],
- initializer=self.vector_init)
-
- # fully connected
- fc1_weights = tf.get_variable(
- 'fc1_w', [self.image_size // 4 * self.image_size // 4 * ch2,
- self.hidden_dim], initializer=self.matrix_init)
- fc1_biases = tf.get_variable('fc1_b', [self.hidden_dim],
- initializer=self.vector_init)
-
- # define model
- x = tf.reshape(x,
- [-1, self.image_size, self.image_size, self.num_channels])
- batch_size = tf.shape(x)[0]
-
- conv1 = tf.nn.conv2d(x, conv1_weights,
- strides=[1, 1, 1, 1], padding='SAME')
- relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_biases))
- conv1 = tf.nn.conv2d(relu1, conv1a_weights,
- strides=[1, 1, 1, 1], padding='SAME')
- relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1a_biases))
-
- pool1 = tf.nn.max_pool(relu1, ksize=[1, 2, 2, 1],
- strides=[1, 2, 2, 1], padding='SAME')
-
- conv2 = tf.nn.conv2d(pool1, conv2_weights,
- strides=[1, 1, 1, 1], padding='SAME')
- relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2_biases))
- conv2 = tf.nn.conv2d(relu2, conv2a_weights,
- strides=[1, 1, 1, 1], padding='SAME')
- relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2a_biases))
-
- pool2 = tf.nn.max_pool(relu2, ksize=[1, 2, 2, 1],
- strides=[1, 2, 2, 1], padding='SAME')
-
- reshape = tf.reshape(pool2, [batch_size, -1])
- hidden = tf.matmul(reshape, fc1_weights) + fc1_biases
-
- return hidden
-
-
-class Model(object):
- """Model for coordinating between CNN embedder and Memory module."""
-
- def __init__(self, input_dim, output_dim, rep_dim, memory_size, vocab_size,
- learning_rate=0.0001, use_lsh=False):
- self.input_dim = input_dim
- self.output_dim = output_dim
- self.rep_dim = rep_dim
- self.memory_size = memory_size
- self.vocab_size = vocab_size
- self.learning_rate = learning_rate
- self.use_lsh = use_lsh
-
- self.embedder = self.get_embedder()
- self.memory = self.get_memory()
- self.classifier = self.get_classifier()
-
- self.global_step = tf.train.get_or_create_global_step()
-
- def get_embedder(self):
- return LeNet(int(self.input_dim ** 0.5), 1, self.rep_dim)
-
- def get_memory(self):
- cls = memory.LSHMemory if self.use_lsh else memory.Memory
- return cls(self.rep_dim, self.memory_size, self.vocab_size)
-
- def get_classifier(self):
- return BasicClassifier(self.output_dim)
-
- def core_builder(self, x, y, keep_prob, use_recent_idx=True):
- embeddings = self.embedder.core_builder(x)
- if keep_prob < 1.0:
- embeddings = tf.nn.dropout(embeddings, keep_prob)
- memory_val, _, teacher_loss = self.memory.query(
- embeddings, y, use_recent_idx=use_recent_idx)
- loss, y_pred = self.classifier.core_builder(memory_val, x, y)
-
- return loss + teacher_loss, y_pred
-
- def train(self, x, y):
- loss, _ = self.core_builder(x, y, keep_prob=0.3)
- gradient_ops = self.training_ops(loss)
- return loss, gradient_ops
-
- def eval(self, x, y):
- _, y_preds = self.core_builder(x, y, keep_prob=1.0,
- use_recent_idx=False)
- return y_preds
-
- def get_xy_placeholders(self):
- return (tf.placeholder(tf.float32, [None, self.input_dim]),
- tf.placeholder(tf.int32, [None]))
-
- def setup(self):
- """Sets up all components of the computation graph."""
-
- self.x, self.y = self.get_xy_placeholders()
-
- # This context creates variables
- with tf.variable_scope('core', reuse=None):
- self.loss, self.gradient_ops = self.train(self.x, self.y)
- # And this one re-uses them (thus the `reuse=True`)
- with tf.variable_scope('core', reuse=True):
- self.y_preds = self.eval(self.x, self.y)
-
- def training_ops(self, loss):
- opt = self.get_optimizer()
- params = tf.trainable_variables()
- gradients = tf.gradients(loss, params)
- clipped_gradients, _ = tf.clip_by_global_norm(gradients, 5.0)
- return opt.apply_gradients(zip(clipped_gradients, params),
- global_step=self.global_step)
-
- def get_optimizer(self):
- return tf.train.AdamOptimizer(learning_rate=self.learning_rate,
- epsilon=1e-4)
-
- def one_step(self, sess, x, y):
- outputs = [self.loss, self.gradient_ops]
- return sess.run(outputs, feed_dict={self.x: x, self.y: y})
-
- def episode_step(self, sess, x, y, clear_memory=False):
- """Performs training steps on episodic input.
-
- Args:
- sess: A Tensorflow Session.
- x: A list of batches of images defining the episode.
- y: A list of batches of labels corresponding to x.
- clear_memory: Whether to clear the memory before the episode.
-
- Returns:
- List of losses the same length as the episode.
- """
-
- outputs = [self.loss, self.gradient_ops]
-
- if clear_memory:
- self.clear_memory(sess)
-
- losses = []
- for xx, yy in zip(x, y):
- out = sess.run(outputs, feed_dict={self.x: xx, self.y: yy})
- loss = out[0]
- losses.append(loss)
-
- return losses
-
- def predict(self, sess, x, y=None):
- """Predict the labels on a single batch of examples.
-
- Args:
- sess: A Tensorflow Session.
- x: A batch of images.
- y: The labels for the images in x.
- This allows for updating the memory.
-
- Returns:
- Predicted y.
- """
-
- # Storing current memory state to restore it after prediction
- mem_keys, mem_vals, mem_age, _ = self.memory.get()
- cur_memory = (
- tf.identity(mem_keys),
- tf.identity(mem_vals),
- tf.identity(mem_age),
- None,
- )
-
- outputs = [self.y_preds]
- if y is None:
- ret = sess.run(outputs, feed_dict={self.x: x})
- else:
- ret = sess.run(outputs, feed_dict={self.x: x, self.y: y})
-
- # Restoring memory state
- self.memory.set(*cur_memory)
-
- return ret
-
- def episode_predict(self, sess, x, y, clear_memory=False):
- """Predict the labels on an episode of examples.
-
- Args:
- sess: A Tensorflow Session.
- x: A list of batches of images.
- y: A list of labels for the images in x.
- This allows for updating the memory.
- clear_memory: Whether to clear the memory before the episode.
-
- Returns:
- List of predicted y.
- """
-
- # Storing current memory state to restore it after prediction
- mem_keys, mem_vals, mem_age, _ = self.memory.get()
- cur_memory = (
- tf.identity(mem_keys),
- tf.identity(mem_vals),
- tf.identity(mem_age),
- None,
- )
-
- if clear_memory:
- self.clear_memory(sess)
-
- outputs = [self.y_preds]
- y_preds = []
- for xx, yy in zip(x, y):
- out = sess.run(outputs, feed_dict={self.x: xx, self.y: yy})
- y_pred = out[0]
- y_preds.append(y_pred)
-
- # Restoring memory state
- self.memory.set(*cur_memory)
-
- return y_preds
-
- def clear_memory(self, sess):
- sess.run([self.memory.clear()])
diff --git a/research/learning_to_remember_rare_events/train.py b/research/learning_to_remember_rare_events/train.py
deleted file mode 100644
index c5c6d06b5ee02e73128ee2b23f3b399d29b1e212..0000000000000000000000000000000000000000
--- a/research/learning_to_remember_rare_events/train.py
+++ /dev/null
@@ -1,242 +0,0 @@
-# Copyright 2017 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-# ==============================================================================
-r"""Script for training model.
-
-Simple command to get up and running:
- python train.py --memory_size=8192 \
- --batch_size=16 --validation_length=50 \
- --episode_width=5 --episode_length=30
-"""
-
-import logging
-import os
-import random
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-import data_utils
-import model
-
-FLAGS = tf.flags.FLAGS
-
-tf.flags.DEFINE_integer('rep_dim', 128,
- 'dimension of keys to use in memory')
-tf.flags.DEFINE_integer('episode_length', 100, 'length of episode')
-tf.flags.DEFINE_integer('episode_width', 5,
- 'number of distinct labels in a single episode')
-tf.flags.DEFINE_integer('memory_size', None, 'number of slots in memory. '
- 'Leave as None to default to episode length')
-tf.flags.DEFINE_integer('batch_size', 16, 'batch size')
-tf.flags.DEFINE_integer('num_episodes', 100000, 'number of training episodes')
-tf.flags.DEFINE_integer('validation_frequency', 20,
- 'every so many training episodes, '
- 'assess validation accuracy')
-tf.flags.DEFINE_integer('validation_length', 10,
- 'number of episodes to use to compute '
- 'validation accuracy')
-tf.flags.DEFINE_integer('seed', 888, 'random seed for training sampling')
-tf.flags.DEFINE_string('save_dir', '', 'directory to save model to')
-tf.flags.DEFINE_bool('use_lsh', False,
- 'use locality-sensitive hashing '
- '(NOTE: not fully tested)')
-
-
-class Trainer(object):
- """Class that takes care of training, validating, and checkpointing model."""
-
- def __init__(self, train_data, valid_data, input_dim, output_dim=None):
- self.train_data = train_data
- self.valid_data = valid_data
- self.input_dim = input_dim
-
- self.rep_dim = FLAGS.rep_dim
- self.episode_length = FLAGS.episode_length
- self.episode_width = FLAGS.episode_width
- self.batch_size = FLAGS.batch_size
- self.memory_size = (self.episode_length * self.batch_size
- if FLAGS.memory_size is None else FLAGS.memory_size)
- self.use_lsh = FLAGS.use_lsh
-
- self.output_dim = (output_dim if output_dim is not None
- else self.episode_width)
-
- def get_model(self):
- # vocab size is the number of distinct values that
- # could go into the memory key-value storage
- vocab_size = self.episode_width * self.batch_size
- return model.Model(
- self.input_dim, self.output_dim, self.rep_dim, self.memory_size,
- vocab_size, use_lsh=self.use_lsh)
-
- def sample_episode_batch(self, data,
- episode_length, episode_width, batch_size):
- """Generates a random batch for training or validation.
-
- Structures each element of the batch as an 'episode'.
- Each episode contains episode_length examples and
- episode_width distinct labels.
-
- Args:
- data: A dictionary mapping label to list of examples.
- episode_length: Number of examples in each episode.
- episode_width: Distinct number of labels in each episode.
- batch_size: Batch size (number of episodes).
-
- Returns:
- A tuple (x, y) where x is a list of batches of examples
- with size episode_length and y is a list of batches of labels.
- """
-
- episodes_x = [[] for _ in xrange(episode_length)]
- episodes_y = [[] for _ in xrange(episode_length)]
- assert len(data) >= episode_width
- keys = data.keys()
- for b in xrange(batch_size):
- episode_labels = random.sample(keys, episode_width)
- remainder = episode_length % episode_width
- remainders = [0] * (episode_width - remainder) + [1] * remainder
- episode_x = [
- random.sample(data[lab],
- r + (episode_length - remainder) // episode_width)
- for lab, r in zip(episode_labels, remainders)]
- episode = sum([[(x, i, ii) for ii, x in enumerate(xx)]
- for i, xx in enumerate(episode_x)], [])
- random.shuffle(episode)
- # Arrange episode so that each distinct label is seen before moving to
- # 2nd showing
- episode.sort(key=lambda elem: elem[2])
- assert len(episode) == episode_length
- for i in xrange(episode_length):
- episodes_x[i].append(episode[i][0])
- episodes_y[i].append(episode[i][1] + b * episode_width)
-
- return ([np.array(xx).astype('float32') for xx in episodes_x],
- [np.array(yy).astype('int32') for yy in episodes_y])
-
- def compute_correct(self, ys, y_preds):
- return np.mean(np.equal(y_preds, np.array(ys)))
-
- def individual_compute_correct(self, y, y_pred):
- return y_pred == y
-
- def run(self):
- """Performs training.
-
- Trains a model using episodic training.
- Every so often, runs some evaluations on validation data.
- """
-
- train_data, valid_data = self.train_data, self.valid_data
- input_dim, output_dim = self.input_dim, self.output_dim
- rep_dim, episode_length = self.rep_dim, self.episode_length
- episode_width, memory_size = self.episode_width, self.memory_size
- batch_size = self.batch_size
-
- train_size = len(train_data)
- valid_size = len(valid_data)
- logging.info('train_size (number of labels) %d', train_size)
- logging.info('valid_size (number of labels) %d', valid_size)
- logging.info('input_dim %d', input_dim)
- logging.info('output_dim %d', output_dim)
- logging.info('rep_dim %d', rep_dim)
- logging.info('episode_length %d', episode_length)
- logging.info('episode_width %d', episode_width)
- logging.info('memory_size %d', memory_size)
- logging.info('batch_size %d', batch_size)
-
- assert all(len(v) >= float(episode_length) / episode_width
- for v in train_data.values())
- assert all(len(v) >= float(episode_length) / episode_width
- for v in valid_data.values())
-
- output_dim = episode_width
- self.model = self.get_model()
- self.model.setup()
-
- sess = tf.Session()
- sess.run(tf.global_variables_initializer())
-
- saver = tf.train.Saver(max_to_keep=10)
- ckpt = None
- if FLAGS.save_dir:
- ckpt = tf.train.get_checkpoint_state(FLAGS.save_dir)
- if ckpt and ckpt.model_checkpoint_path:
- logging.info('restoring from %s', ckpt.model_checkpoint_path)
- saver.restore(sess, ckpt.model_checkpoint_path)
-
- logging.info('starting now')
- losses = []
- random.seed(FLAGS.seed)
- np.random.seed(FLAGS.seed)
- for i in xrange(FLAGS.num_episodes):
- x, y = self.sample_episode_batch(
- train_data, episode_length, episode_width, batch_size)
- outputs = self.model.episode_step(sess, x, y, clear_memory=True)
- loss = outputs
- losses.append(loss)
-
- if i % FLAGS.validation_frequency == 0:
- logging.info('episode batch %d, avg train loss %f',
- i, np.mean(losses))
- losses = []
-
- # validation
- correct = []
- num_shots = episode_length // episode_width
- correct_by_shot = dict((k, []) for k in xrange(num_shots))
- for _ in xrange(FLAGS.validation_length):
- x, y = self.sample_episode_batch(
- valid_data, episode_length, episode_width, 1)
- outputs = self.model.episode_predict(
- sess, x, y, clear_memory=True)
- y_preds = outputs
- correct.append(self.compute_correct(np.array(y), y_preds))
-
- # compute per-shot accuracies
- seen_counts = [0] * episode_width
- # loop over episode steps
- for yy, yy_preds in zip(y, y_preds):
- # loop over batch examples
- yyy, yyy_preds = int(yy[0]), int(yy_preds[0])
- count = seen_counts[yyy % episode_width]
- if count in correct_by_shot:
- correct_by_shot[count].append(
- self.individual_compute_correct(yyy, yyy_preds))
- seen_counts[yyy % episode_width] = count + 1
-
- logging.info('validation overall accuracy %f', np.mean(correct))
- logging.info('%d-shot: %.3f, ' * num_shots,
- *sum([[k, np.mean(correct_by_shot[k])]
- for k in xrange(num_shots)], []))
-
- if saver and FLAGS.save_dir:
- saved_file = saver.save(sess,
- os.path.join(FLAGS.save_dir, 'model.ckpt'),
- global_step=self.model.global_step)
- logging.info('saved model to %s', saved_file)
-
-
-def main(unused_argv):
- train_data, valid_data = data_utils.get_data()
- trainer = Trainer(train_data, valid_data, data_utils.IMAGE_NEW_SIZE ** 2)
- trainer.run()
-
-
-if __name__ == '__main__':
- logging.basicConfig(level=logging.INFO)
- tf.app.run()
diff --git a/research/learning_unsupervised_learning/.gitignore b/research/learning_unsupervised_learning/.gitignore
deleted file mode 100644
index 0d20b6487c61e7d1bde93acf4a14b7a89083a16d..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.pyc
diff --git a/research/learning_unsupervised_learning/README.md b/research/learning_unsupervised_learning/README.md
deleted file mode 100644
index 0e38717f5de29df28959062889abeb1ce578feea..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/README.md
+++ /dev/null
@@ -1,40 +0,0 @@
-
-
-
-
-# Learning Unsupervised Learning Rules
-This repository contains code and weights for the learned update rule
-presented in "Learning Unsupervised Learning Rules." At this time, this
-code can not meta-train the update rule.
-
-### Structure
-`run_eval.py` contains the main training loop. This constructs an op
-that runs one iteration of the learned update rule and assigns the
-results to variables. Additionally, it loads the weights from our
-pre-trained model.
-
-The base model and the update rule architecture definition can be found in
-`architectures/more_local_weight_update.py`. For a complete description
-of the model, see our [paper](https://arxiv.org/abs/1804.00222).
-
-### Dependencies
-[absl]([https://github.com/abseil/abseil-py), [tensorflow](https://tensorflow.org), [sonnet](https://github.com/deepmind/sonnet)
-
-### Usage
-
-First, download the [pre-trained optimizer model weights](https://storage.googleapis.com/learning_unsupervised_learning/200_tf_graph.zip) and extract it.
-
-```bash
-# move to the folder above this folder
-cd path_to/research/learning_unsupervised_learning/../
-
-# launch the eval script
-python -m learning_unsupervised_learning.run_eval \
---train_log_dir="/tmp/learning_unsupervised_learning" \
---checkpoint_dir="/path/to/downloaded/model/tf_graph_data.ckpt"
-```
-
-### Contact
-Luke Metz, Niru Maheswaranathan, Github: @lukemetz, @nirum. Email: {lmetz, nirum}@google.com
-
-
diff --git a/research/learning_unsupervised_learning/__init__.py b/research/learning_unsupervised_learning/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/learning_unsupervised_learning/architectures/__init__.py b/research/learning_unsupervised_learning/architectures/__init__.py
deleted file mode 100644
index af9545f26da538aa986b19a96b6cfa2bc7459227..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/architectures/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-
-import more_local_weight_update
diff --git a/research/learning_unsupervised_learning/architectures/common.py b/research/learning_unsupervised_learning/architectures/common.py
deleted file mode 100644
index 43a2d4f8965ecd337abd3a072a7ecb789df21910..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/architectures/common.py
+++ /dev/null
@@ -1,153 +0,0 @@
-# Copyright 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import sonnet as snt
-import tensorflow as tf
-import numpy as np
-import collections
-from learning_unsupervised_learning import utils
-
-from tensorflow.python.util import nest
-
-from learning_unsupervised_learning import variable_replace
-
-
-class LinearBatchNorm(snt.AbstractModule):
- """Module that does a Linear layer then a BatchNorm followed by an activation fn"""
- def __init__(self, size, activation_fn=tf.nn.relu, name="LinearBatchNorm"):
- self.size = size
- self.activation_fn = activation_fn
- super(LinearBatchNorm, self).__init__(name=name)
-
- def _build(self, x):
- x = tf.to_float(x)
- initializers={"w": tf.truncated_normal_initializer(stddev=0.01)}
- lin = snt.Linear(self.size, use_bias=False, initializers=initializers)
- z = lin(x)
-
- scale = tf.constant(1., dtype=tf.float32)
- offset = tf.get_variable(
- "b",
- shape=[1, z.shape.as_list()[1]],
- initializer=tf.truncated_normal_initializer(stddev=0.1),
- dtype=tf.float32
- )
-
- mean, var = tf.nn.moments(z, [0], keep_dims=True)
- z = ((z - mean) * tf.rsqrt(var + 1e-6)) * scale + offset
-
- x_p = self.activation_fn(z)
-
- return z, x_p
-
- # This needs to work by string name sadly due to how the variable replace
- # works and would also work even if the custom getter approuch was used.
- # This is verbose, but it should atleast be clear as to what is going on.
- # TODO(lmetz) a better way to do this (the next 3 functions:
- # _raw_name, w(), b() )
- def _raw_name(self, var_name):
- """Return just the name of the variable, not the scopes."""
- return var_name.split("/")[-1].split(":")[0]
-
-
- @property
- def w(self):
- var_list = snt.get_variables_in_module(self)
- w = [x for x in var_list if self._raw_name(x.name) == "w"]
- assert len(w) == 1
- return w[0]
-
- @property
- def b(self):
- var_list = snt.get_variables_in_module(self)
- b = [x for x in var_list if self._raw_name(x.name) == "b"]
- assert len(b) == 1
- return b[0]
-
-
-
-class Linear(snt.AbstractModule):
- def __init__(self, size, use_bias=True, init_const_mag=True):
- self.size = size
- self.use_bias = use_bias
- self.init_const_mag = init_const_mag
- super(Linear, self).__init__(name="commonLinear")
-
- def _build(self, x):
- if self.init_const_mag:
- initializers={"w": tf.truncated_normal_initializer(stddev=0.01)}
- else:
- initializers={}
- lin = snt.Linear(self.size, use_bias=self.use_bias, initializers=initializers)
- z = lin(x)
- return z
-
- # This needs to work by string name sadly due to how the variable replace
- # works and would also work even if the custom getter approuch was used.
- # This is verbose, but it should atleast be clear as to what is going on.
- # TODO(lmetz) a better way to do this (the next 3 functions:
- # _raw_name, w(), b() )
- def _raw_name(self, var_name):
- """Return just the name of the variable, not the scopes."""
- return var_name.split("/")[-1].split(":")[0]
-
- @property
- def w(self):
- var_list = snt.get_variables_in_module(self)
- if self.use_bias:
- assert len(var_list) == 2, "Found not 2 but %d" % len(var_list)
- else:
- assert len(var_list) == 1, "Found not 1 but %d" % len(var_list)
- w = [x for x in var_list if self._raw_name(x.name) == "w"]
- assert len(w) == 1
- return w[0]
-
- @property
- def b(self):
- var_list = snt.get_variables_in_module(self)
- assert len(var_list) == 2, "Found not 2 but %d" % len(var_list)
- b = [x for x in var_list if self._raw_name(x.name) == "b"]
- assert len(b) == 1
- return b[0]
-
-
-def transformer_at_state(base_model, new_variables):
- """Get the base_model that has been transformed to use the variables
- in final_state.
- Args:
- base_model: snt.Module
- Goes from batch to features
- new_variables: list
- New list of variables to use
- Returns:
- func: callable of same api as base_model.
- """
- assert not variable_replace.in_variable_replace_scope()
-
- def _feature_transformer(input_data):
- """Feature transformer at the end of training."""
- initial_variables = base_model.get_variables()
- replacement = collections.OrderedDict(
- utils.eqzip(initial_variables, new_variables))
- with variable_replace.variable_replace(replacement):
- features = base_model(input_data)
- return features
-
- return _feature_transformer
diff --git a/research/learning_unsupervised_learning/architectures/more_local_weight_update.py b/research/learning_unsupervised_learning/architectures/more_local_weight_update.py
deleted file mode 100644
index 117549af0f21f9e5148435b73f664a08013f8786..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/architectures/more_local_weight_update.py
+++ /dev/null
@@ -1,861 +0,0 @@
-# Copyright 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-import numpy as np
-import sonnet as snt
-import tensorflow as tf
-
-from learning_unsupervised_learning.architectures import common
-from learning_unsupervised_learning import optimizers
-from learning_unsupervised_learning import utils
-from learning_unsupervised_learning import summary_utils
-
-OptState = collections.namedtuple('OptState',
- ['variables', 'opt_state', 'index'])
-
-BaseModelOutputs = collections.namedtuple(
- 'BaseModelOutputs', ['xs', 'zs', 'mods', 'batch', 'backward_mods'])
-
-
-class GradChannelReadout(snt.AbstractModule):
- """Perform a linear readout and reshape from input 3 tensor."""
-
- def __init__(self,
- num_grad_channels,
- device,
- perm=(2, 0, 1),
- name='GradChannelReadout'):
- """Args:
-
- num_grad_channels: int
- number of channels to readout to.
- device: str or callable
- devicwe to place weights.
- perm: list or tuple
- transpose applied.
- """
-
- self.num_grad_channels = num_grad_channels
- self.device = device
- self.perm = perm
- super(GradChannelReadout, self).__init__(name=name)
-
- def _build(self, h):
- with tf.device(self.device):
- mod = snt.Linear(self.num_grad_channels)
- ret = snt.BatchApply(mod)(h)
- # return as [num_grad_channels] x [bs] x [num units]
- return tf.transpose(ret, perm=self.perm)
-
-
-def get_weight_stats(x, axis):
- """ Compute weight statistics over the given axis.
-
- Args:
- x: tf.Tensor
- a batch of activations.
- axis: int
- axis to perform statistics over.
- Returns:
- tf.Tensor
- a 3-D tensor with statistics.
- """
- if x is None:
- return []
-
- stats = []
- l1 = tf.reduce_mean(tf.abs(x), axis=axis)
- l2 = tf.sqrt(tf.reduce_mean(x**2, axis=axis) + 1e-6)
-
- mean, var = tf.nn.moments(x, [axis])
- stats.extend([l1, l2, mean, tf.sqrt(var + 1e-8)])
-
- stats = [tf.reshape(s, [-1, 1, 1]) for s in stats]
-
- return stats
-
-
-class AddUnitBatchStatistics(snt.AbstractModule):
- """Compute some number of statistics over units and concat them on."""
-
- def __init__(self, name='AddUnitBatchStatistics'):
- super(AddUnitBatchStatistics, self).__init__(name=name)
-
- def _build(self, x):
- # [channel, bs, 1]
- output = x
- for d in [0, 1]:
- stats = []
- l1 = tf.reduce_mean(tf.abs(x), axis=d, keepdims=True)
- l2 = tf.sqrt(tf.reduce_mean(x**2, axis=d, keepdims=True) + 1e-6)
-
- mean, var = tf.nn.moments(x, [d], keepdims=True)
- stats.extend([l1, l2, mean, tf.sqrt(var + 1e-8)])
-
- to_add = tf.concat(stats, axis=2) # [channels/1, units/1, stats]
- output += snt.BatchApply(snt.Linear(x.shape.as_list()[2]))(to_add)
- return output
-
-
-class ConcatUnitConv(snt.AbstractModule):
- """Do a small number of convolutions over units and concat / add them on."""
-
- def __init__(self, add=True):
- self.add = add
- super(ConcatUnitConv, self).__init__(name='ConcatUnitConv')
-
- def _build(self, x):
- # x is [units, bs, 1]
- net = tf.transpose(x, [1, 0, 2]) # now [bs x units x 1]
- channels = x.shape.as_list()[2]
- mod = snt.Conv1D(output_channels=channels, kernel_shape=[3])
- net = mod(net)
- net = snt.BatchNorm(axis=[0, 1])(net, is_training=False)
- net = tf.nn.relu(net)
- mod = snt.Conv1D(output_channels=channels, kernel_shape=[3])
- net = mod(net)
- net = snt.BatchNorm(axis=[0, 1])(net, is_training=False)
- net = tf.nn.relu(net)
- to_concat = tf.transpose(net, [1, 0, 2])
- if self.add:
- return x + to_concat
- else:
- return tf.concat([x, to_concat], 2)
-
-
-class MoreLocalWeightUpdateProcess(snt.AbstractModule):
-
- def __init__(
- self,
- remote_device,
- local_device,
- top_delta_size=64,
- top_delta_layers=2,
- compute_h_size=64,
- compute_h_layers=1,
- delta_dim=32,
- num_grad_channels=4,
- normalize_epsilon=1.,
- ):
- self.local_device = local_device
- self.remote_device = remote_device
- self.top_delta_size = top_delta_size
- self.top_delta_layers = top_delta_layers
- self.compute_h_size = compute_h_size
- self.compute_h_layers = compute_h_layers
- self.delta_dim = delta_dim
- self.num_grad_channels = num_grad_channels
- self.normalize_epsilon = normalize_epsilon,
-
- with tf.device(local_device):
- self.opt = optimizers.UnrollableGradientDescentRollingOptimizer(
- learning_rate=1e-4)
-
- # lazily initialized for readouts
- self.readout_mods = {}
-
- super(MoreLocalWeightUpdateProcess,
- self).__init__(name='MoreLocalWeightUpdateProcess')
-
- with tf.device(remote_device):
- self()
-
- def normalize(self, change_w, normalize_epsilon=None):
- if normalize_epsilon is None:
- normalize_epsilon = self.normalize_epsilon
-
- # normalize the weights per receptive-field, rather than per-matrix
- var = tf.reduce_mean(tf.square(change_w), axis=0, keepdims=True)
- change_w = (change_w) / tf.sqrt(normalize_epsilon + var)
- return change_w
-
- def _build(self):
- pass
-
- @snt.reuse_variables
- def compute_top_delta(self, z):
- """ parameterization of topD. This converts the top level activation
- to an error signal.
- Args:
- z: tf.Tensor
- batch of final layer post activations
- Returns
- delta: tf.Tensor
- the error signal
- """
- s_idx = 0
- with tf.variable_scope('compute_top_delta'), tf.device(self.remote_device):
- # typically this takes [BS, length, input_channels],
- # We are applying this such that we convolve over the batch dimension.
- act = tf.expand_dims(tf.transpose(z, [1, 0]), 2) # [channels, BS, 1]
-
- mod = snt.Conv1D(output_channels=self.top_delta_size, kernel_shape=[5])
- act = mod(act)
-
- act = snt.BatchNorm(axis=[0, 1])(act, is_training=False)
- act = tf.nn.relu(act)
-
- bs = act.shape.as_list()[0]
- act = tf.transpose(act, [2, 1, 0])
- act = snt.Conv1D(output_channels=bs, kernel_shape=[3])(act)
- act = snt.BatchNorm(axis=[0, 1])(act, is_training=False)
- act = tf.nn.relu(act)
- act = snt.Conv1D(output_channels=bs, kernel_shape=[3])(act)
- act = snt.BatchNorm(axis=[0, 1])(act, is_training=False)
- act = tf.nn.relu(act)
- act = tf.transpose(act, [2, 1, 0])
-
- prev_act = act
- for i in range(self.top_delta_layers):
- mod = snt.Conv1D(output_channels=self.top_delta_size, kernel_shape=[3])
- act = mod(act)
-
- act = snt.BatchNorm(axis=[0, 1])(act, is_training=False)
- act = tf.nn.relu(act)
-
- prev_act = act
-
- mod = snt.Conv1D(output_channels=self.delta_dim, kernel_shape=[3])
- act = mod(act)
-
- # [bs, feature_channels, delta_channels]
- act = tf.transpose(act, [1, 0, 2])
- return act
-
- @snt.reuse_variables
- def compute_h(self,
- x,
- z,
- d,
- bias,
- W_bot,
- W_top,
- compute_perc=1.0,
- compute_units=None):
- """z = [BS, n_units] a = [BS, n_units] b = [BS, n_units] d = [BS, n_units, delta_channels]
-
- """
-
- s_idx = 0
- if compute_perc != 1.0:
- assert compute_units is None
-
- with tf.device(self.remote_device):
- inp_feat = [x, z]
- inp_feat = [tf.transpose(f, [1, 0]) for f in inp_feat]
-
- units = x.shape.as_list()[1]
- bs = x.shape.as_list()[0]
-
- # add unit ID, to help the network differentiate units
- id_theta = tf.linspace(0., (4) * np.pi, units)
- assert bs is not None
- id_theta_bs = tf.reshape(id_theta, [-1, 1]) * tf.ones([1, bs])
- inp_feat += [tf.sin(id_theta_bs), tf.cos(id_theta_bs)]
-
- # list of [units, BS, 1]
- inp_feat = [tf.expand_dims(f, 2) for f in inp_feat]
-
- d_trans = tf.transpose(d, [1, 0, 2])
-
- if compute_perc != 1.0:
- compute_units = int(compute_perc * inp_feat.shape.as_list()[0])
-
- # add weight matrix statistics, both from above and below
- w_stats_bot = get_weight_stats(W_bot, 0)
- w_stats_top = get_weight_stats(W_top, 1)
- w_stats = w_stats_bot + w_stats_top
- if W_bot is None or W_top is None:
- # if it's an edge layer (top or bottom), just duplicate the stats for
- # the weight matrix that does exist
- w_stats = w_stats + w_stats
- w_stats = [tf.ones([1, x.shape[0], 1]) * ww for ww in w_stats]
- # w_stats is a list, with entries with shape UNITS x 1 x channels
-
- if compute_units is None:
- inp_feat_in = inp_feat
- d_trans_in = d_trans
- w_stats_in = w_stats
- bias_in = tf.transpose(bias)
- else:
- # only run on a subset of the activations.
- mask = tf.random_uniform(
- minval=0,
- maxval=1,
- dtype=tf.float32,
- shape=inp_feat[0].shape.as_list()[0:1])
- _, ind = tf.nn.top_k(mask, k=compute_units)
- ind = tf.reshape(ind, [-1, 1])
-
- inp_feat_in = [tf.gather_nd(xx, ind) for xx in inp_feat]
- w_stats_in = [tf.gather_nd(xx, ind) for xx in w_stats]
- d_trans_in = tf.gather_nd(d_trans, ind)
- bias_in = tf.gather_nd(tf.transpose(bias), ind)
-
- w_stats_in = tf.concat(w_stats_in, 2)
- w_stats_in_norm = w_stats_in * tf.rsqrt(
- tf.reduce_mean(w_stats_in**2) + 1e-6)
-
- act = tf.concat(inp_feat_in + [d_trans_in], 2)
- act = snt.BatchNorm(axis=[0, 1])(act, is_training=True)
-
- bias_dense = tf.reshape(bias_in, [-1, 1, 1]) * tf.ones([1, bs, 1])
- act = tf.concat([w_stats_in_norm, bias_dense, act], 2)
-
- mod = snt.Conv1D(output_channels=self.compute_h_size, kernel_shape=[3])
- act = mod(act)
-
- act = snt.BatchNorm(axis=[0, 1])(act, is_training=True)
- act = tf.nn.relu(act)
-
- act2 = ConcatUnitConv()(act)
- act = act2
-
- prev_act = act
- for i in range(self.compute_h_layers):
- mod = snt.Conv1D(output_channels=self.compute_h_size, kernel_shape=[3])
- act = mod(act)
-
- act = snt.BatchNorm(axis=[0, 1])(act, is_training=True)
- act = tf.nn.relu(act)
-
- act = ConcatUnitConv()(act)
-
- prev_act = act
-
- h = act
- if compute_units is not None:
- shape = inp_feat[0].shape.as_list()[:1] + h.shape.as_list()[1:]
- h = tf.scatter_nd(ind, h, shape=shape)
-
- h = tf.transpose(h, [1, 0, 2]) # [bs, units, channels]
-
- return h
-
- ## wrappers to allow forward and backward to have different variables
- @snt.reuse_variables
- def merge_change_w_forward(self, change_w_terms, global_prefix='', prefix=''):
- return self.merge_change_w(
- change_w_terms, global_prefix=global_prefix, prefix=prefix)
-
- @snt.reuse_variables
- def merge_change_w_backward(self, change_w_terms, global_prefix='',
- prefix=''):
- return self.merge_change_w(
- change_w_terms, global_prefix=global_prefix, prefix=prefix)
-
- def merge_change_w(self, change_w_terms, global_prefix='', prefix=''):
- with tf.device(
- self.remote_device), tf.name_scope(global_prefix + '_merge_change_w'):
- w_base = change_w_terms['w_base']
-
- for kk in sorted(change_w_terms.keys()):
- name = global_prefix + 'change_w_plane_%s' % kk
- delta_w = change_w_terms[kk]
- mean, var = tf.nn.moments(delta_w, [0, 1])
- root_mean_square = tf.sqrt(tf.reduce_mean(delta_w**2) + 1e-6)
-
- for kk in sorted(change_w_terms.keys()):
- change_w_terms[kk] = self.normalize(change_w_terms[kk])
-
- initializers = {
- 'w': tf.constant_initializer(0.1),
- 'b': tf.zeros_initializer()
- }
- mod = snt.Linear(
- 1,
- name=global_prefix + '_weight_readout_coeffs',
- initializers=initializers)
-
- change_w_terms_list = [
- change_w_terms[kk] for kk in sorted(change_w_terms.keys())
- ]
- stack_terms = tf.stack(change_w_terms_list, axis=-1)
- change_w = tf.squeeze(
- snt.BatchApply(mod)(stack_terms), axis=-1) / len(change_w_terms)
-
- # only allow perpendicular updates, or updates which grow length. don't
- # allow length to decay towards zero.
- ip = tf.reduce_mean(change_w * w_base)
- # zero out any updates that shrink length
- ip = tf.nn.relu(ip)
- change_w -= w_base * ip
- change_w /= tf.sqrt(len(change_w_terms) * 1.)
-
- change_w = self.normalize(change_w)
-
- # encourage the receptive field to not collapse to 0
- change_w -= w_base / 7. # This is an arbitrary scale choice
-
- return tf.identity(change_w)
-
- @snt.reuse_variables
- def bias_readout(self, h):
- with tf.device(self.remote_device):
- mod = snt.Linear(1, name='bias_readout')
- ret = snt.BatchApply(mod)(h)
- return tf.squeeze(ret, 2)
-
- @snt.reuse_variables
- def next_delta(self, z, h, d):
- with tf.device(self.remote_device):
- return d * tf.expand_dims(tf.nn.sigmoid(z), 2) + self.to_delta_size(h)
-
- @utils.create_variables_in_class_scope
- def get_readout_mod(self, name):
- if name not in self.readout_mods:
- self.readout_mods[name] = GradChannelReadout(
- self.num_grad_channels, device=self.remote_device, name=name)
-
- return self.readout_mods[name]
-
- @utils.create_variables_in_class_scope
- def low_rank_readout(self, name, h1, h2, psd=False):
- BS = h1.shape.as_list()[0]
- r_t = self.get_readout_mod(name + '_top')(h1)
- if psd:
- r_b = r_t
- else:
- r_b = self.get_readout_mod(name + '_bottom')(h2)
- return tf.reduce_mean(tf.matmul(r_b, r_t, transpose_a=True), axis=0) / BS
-
- @snt.reuse_variables
- def to_delta_size(self, h):
- with tf.device(self.remote_device):
- mod = snt.Linear(self.delta_dim)
- return snt.BatchApply(mod)(h)
-
- @snt.reuse_variables
- def initial_state(self, variables):
- """The inner optimization state.
-
- Args:
- variables: list of tf.Variable
- list of variables to get the initial state of.
- Returns:
- opt_state: OptState
- """
-
- with tf.device(self.local_device):
- initial_opt_state = self.opt.get_state(variables)
-
- return OptState(
- variables=variables, opt_state=initial_opt_state, index=tf.constant(0))
-
- @snt.reuse_variables
- def compute_next_state(self, grads, learning_rate, cur_state,
- cur_transformer):
-
- summaries = []
- with tf.device(self.local_device):
- with tf.control_dependencies(summaries):
- new_vars, new_state = self.opt.compute_updates(
- cur_state.variables, grads, learning_rate, cur_state.opt_state)
- pass
-
- return OptState(
- variables=tuple(new_vars),
- opt_state=new_state,
- index=cur_state.index + 1)
-
- def assign_state(self, base_model, next_state):
- var_ups = [
- v.assign(nv) for v, nv in utils.eqzip(base_model.get_variables(),
- next_state.variables)
- ]
-
- opt_ups = self.opt.assign_state(next_state.opt_state)
-
- return tf.group(opt_ups, *var_ups)
-
- def local_variables(self):
- return list(self.opt.get_variables())
-
- def remote_variables(self):
- train = list(
- snt.get_variables_in_module(self, tf.GraphKeys.TRAINABLE_VARIABLES))
- train += list(
- snt.get_variables_in_module(self,
- tf.GraphKeys.MOVING_AVERAGE_VARIABLES))
- return train
-
-
-class MoreLocalWeightUpdateWLearner(snt.AbstractModule):
- """The BaseModel that the UnsupervisedUpdateRule acts on.
- """
-
- def __init__(self,
- remote_device,
- local_device,
- inner_size=128,
- output_size=32,
- n_layers=4,
- shuffle_input=True,
- activation_fn=tf.nn.relu,
- identical_updates=True,
- **kwargs):
- self.local_device = local_device
- self.remote_device = remote_device
- self.inner_size = inner_size
- self.n_layers = n_layers
- self.shuffle_input = shuffle_input
- self.activation_fn = activation_fn
- self.identical_updates = identical_updates
-
- self.output_size = output_size
- if output_size == None:
- self.output_size = inner_size
-
- self.shuffle_ind = None
-
- super(MoreLocalWeightUpdateWLearner, self).__init__(
- name='LocalWeightUpdateWLearner', **kwargs)
-
- @snt.reuse_variables
- def get_shuffle_ind(self, size):
- if self.shuffle_ind is None:
- # put the shuffle in tf memory to make the eval jobs
- # re-entrant.
- shuffle_ind_val = np.random.permutation(size)
- shuffle_ind = tf.get_variable(
- name='shuffle_ind', dtype=tf.int64, initializer=shuffle_ind_val)
- unshuffle_ind = tf.scatter_nd(
- tf.reshape(shuffle_ind, [-1, 1]), tf.range(size), [size])
-
- return shuffle_ind, unshuffle_ind
-
- def _build(self, batch):
- image = batch.image
- x0 = snt.BatchFlatten()(image)
- if self.shuffle_input:
- size = x0.shape.as_list()[1]
- shuffle_ind, unshuffle_ind = self.get_shuffle_ind(size)
- x0 = tf.gather(x0, shuffle_ind, axis=1)
-
- xs = [x0]
- mods = []
- zs = []
- init = {}
-
- for i in range(self.n_layers):
- mod = common.LinearBatchNorm(
- self.inner_size, activation_fn=self.activation_fn)
- z, x = mod(xs[i])
- xs.append(x)
- zs.append(z)
- mods.append(mod)
-
- mod = common.LinearBatchNorm(
- self.output_size, activation_fn=self.activation_fn)
- z, x = mod(xs[-1])
- mods.append(mod)
-
- xs.append(x)
- zs.append(z)
-
- embedding_x = xs[-1]
-
- # make a random set of backward mods
- backward_mods = []
- for i, (x, x_p1) in enumerate(zip(xs[0:-1], xs[1:])):
- m = common.LinearBatchNorm(
- x_p1.shape.as_list()[1], activation_fn=tf.identity)
- _ = m(x)
- backward_mods.append(m)
-
- shape = image.shape.as_list()[1:4]
-
- for mods_p, prefix in [(mods, 'forward'), (backward_mods, 'backward')]:
- if self.shuffle_input:
- unshuf_w = tf.gather(mods_p[0].w, unshuffle_ind, axis=0)
- else:
- unshuf_w = mods_p[0].w
- img = summary_utils.first_layer_weight_image(unshuf_w, shape)
- tf.summary.image(prefix + '_w0_receptive_field', img)
-
- for i, m in enumerate(mods_p[0:]):
- img = summary_utils.inner_layer_weight_image(m.w)
- tf.summary.image(prefix + '_w%d' % (i + 1), img)
-
- img = summary_utils.sorted_images(image, batch.label_onehot)
- tf.summary.image('inputs', img)
-
- # log out pre-activations and activations
- for all_vis, base_name in [(xs, 'x'), (zs, 'z')]:
- for i, x_vis in enumerate(all_vis):
- img = summary_utils.activation_image(x_vis, batch.label_onehot)
- tf.summary.image('%s%d' % (base_name, i), img)
-
- embedding_x = tf.identity(embedding_x)
-
- outputs = BaseModelOutputs(
- xs=xs, zs=zs, mods=mods, batch=batch, backward_mods=backward_mods)
-
- return embedding_x, outputs
-
- def compute_next_h_d(self, meta_opt, w_bot, w_top, bias, x, z, d, backward_w):
- """ Propogate error back down the network while computing hidden state.
- """
- if z is None:
- z = x
-
- h = meta_opt.compute_h(x, z, d, bias, w_bot,
- w_top) # [bs x 60 x h_channels]
-
- # compute the next d
- delta = meta_opt.next_delta(z, h, d)
-
- if backward_w is not None:
-
- def delta_matmul(w, delta):
- d = tf.transpose(delta, [0, 2, 1]) # [bs x delta_channels x n_units)
- d = snt.BatchApply(lambda x: tf.matmul(x, w, transpose_b=True))(d)
- d = tf.transpose(d, [0, 2, 1])
- return d
-
- # replace the "backward pass" with a random matrix.
- d = delta_matmul(backward_w, delta) # [bs x 60 x delta_channels]
- var = tf.reduce_mean(tf.square(d), [2], keepdims=True)
- d = d * tf.rsqrt(1e-6 + var)
-
- return h, d
-
- def weight_change_for_layer(self, meta_opt, l_idx, w_base, b_base, upper_h,
- lower_h, upper_x, lower_x, prefix, include_bias):
- """Compute the change in weights for each layer.
- This computes something roughly analagous to a gradient.
- """
- reduce_upper_h = upper_h
- reduce_lower_h = lower_h
-
- BS = lower_x.shape.as_list()[0]
-
- change_w_terms = dict()
-
- # initial weight value normalized
- # normalize the weights per receptive-field, rather than per-matrix
- weight_scale = tf.rsqrt(
- tf.reduce_mean(w_base**2, axis=0, keepdims=True) + 1e-6)
- w_base *= weight_scale
-
- change_w_terms['w_base'] = w_base
-
- # this will act to decay larger weights towards zero
- change_w_terms['large_decay'] = w_base**2 * tf.sign(w_base)
-
- # term based on activations
- ux0 = upper_x - tf.reduce_mean(upper_x, axis=0, keepdims=True)
- uxs0 = ux0 * tf.rsqrt(tf.reduce_mean(ux0**2, axis=0, keepdims=True) + 1e-6)
- change_U = tf.matmul(uxs0, uxs0, transpose_a=True) / BS
- change_U /= tf.sqrt(float(change_U.shape.as_list()[0]))
-
- cw = tf.matmul(w_base, change_U)
- cw_scale = tf.rsqrt(tf.reduce_mean(cw**2 + 1e-8))
- cw *= cw_scale
- change_w_terms['decorr_x'] = cw
-
- # hebbian term
- lx0 = lower_x - tf.reduce_mean(lower_x, axis=0, keepdims=True)
- lxs0 = lx0 * tf.rsqrt(tf.reduce_mean(lx0**2, axis=0, keepdims=True) + 1e-6)
- cw = tf.matmul(lxs0, uxs0, transpose_a=True) / BS
- change_w_terms['hebb'] = -cw
-
- # 0th order term
- w_term = meta_opt.low_rank_readout(prefix + 'weight_readout_0', upper_h,
- lower_h)
- change_w_terms['0_order'] = w_term
-
- # # rbf term (weight update scaled by distance from 0)
- w_term = meta_opt.low_rank_readout(prefix + 'weight_readout_rbf',
- reduce_upper_h, reduce_lower_h)
- change_w_terms['rbf'] = tf.exp(-w_base**2) * w_term
-
- # 1st order term (weight dependent update to weights)
- w_term = meta_opt.low_rank_readout(prefix + 'weight_readout_1',
- reduce_upper_h, reduce_lower_h)
- change_w_terms['1_order'] = w_base * w_term
-
- # more terms based on single layer readouts.
- for update_type in ['lin', 'sqr']:
- for h_source, h_source_name in [(reduce_upper_h, 'upper'),
- (reduce_lower_h, 'lower')]:
- structures = ['symm']
- if update_type == 'lin' and h_source_name == 'upper':
- structures += ['psd']
- for structure in structures:
- name = update_type + '_' + h_source_name + '_' + structure
- if structure == 'symm':
- change_U = meta_opt.low_rank_readout(prefix + name, h_source,
- h_source)
- change_U = (change_U + tf.transpose(change_U)) / tf.sqrt(2.)
- change_U = tf.matrix_set_diag(change_U,
- tf.zeros(
- [change_U.shape.as_list()[0]]))
- elif structure == 'psd':
- change_U = meta_opt.low_rank_readout(
- prefix + name, h_source, None, psd=True)
- else:
- assert False
- change_U /= tf.sqrt(float(change_U.shape.as_list()[0]))
-
- if update_type == 'lin':
- sign_multiplier = tf.ones_like(w_base)
- w_base_l = w_base
- elif update_type == 'sqr':
- sign_multiplier = tf.sign(w_base)
- w_base_l = tf.sqrt(1. + w_base**2) - 1.
-
- if h_source_name == 'upper':
- cw = tf.matmul(w_base_l, change_U) # [N^l-1 x N^l]
- elif h_source_name == 'lower':
- cw = tf.matmul(change_U, w_base_l)
- change_w_terms[name] = cw * sign_multiplier
-
-
- if prefix == 'forward':
- change_w = meta_opt.merge_change_w_forward(
- change_w_terms, global_prefix=prefix, prefix='l%d' % l_idx)
- elif prefix == 'backward':
- change_w = meta_opt.merge_change_w_backward(
- change_w_terms, global_prefix=prefix, prefix='l%d' % l_idx)
- else:
- assert (False)
-
- if not include_bias:
- return change_w
-
- change_b = tf.reduce_mean(meta_opt.bias_readout(upper_h), [0])
-
- # force nonlinearities to be exercised -- biases can't all be increased without bound
- change_b_mean = tf.reduce_mean(change_b)
- offset = -tf.nn.relu(-change_b_mean)
- change_b -= offset
-
- var = tf.reduce_mean(tf.square(change_b), [0], keepdims=True)
- change_b = (change_b) / tf.sqrt(0.5 + var)
- return change_w, change_b
-
- def compute_next_state(self, outputs, meta_opt, previous_state):
- zs = outputs.zs
- xs = outputs.xs
- batch = outputs.batch
- mods = outputs.mods
- backward_mods = outputs.backward_mods
- variables = self.get_variables()
-
- rev_mods = mods[::-1]
- rev_backward_mods = backward_mods[::-1]
- rev_xs = xs[::-1]
- rev_zs = zs[::-1] + [None]
-
- to_top = xs[-1]
-
- # variables that change in the loop
- hs = []
- d = meta_opt.compute_top_delta(to_top) # [bs x 32 x delta_channels]
-
- iterator = utils.eqzip(rev_backward_mods + [None], rev_mods + [None],
- [None] + rev_mods, rev_xs, rev_zs)
- for (backward_mod, lower_mod, upper_mod, x, z) in iterator:
- w_bot = None
- if not lower_mod is None:
- w_bot = previous_state.variables[variables.index(lower_mod.w)]
- w_top = None
- if not upper_mod is None:
- w_top = previous_state.variables[variables.index(upper_mod.w)]
- backward_w = None
- if backward_mod is not None:
- backward_w = previous_state.variables[variables.index(backward_mod.w)]
- if lower_mod is not None:
- bias = previous_state.variables[variables.index(lower_mod.b)]
- else:
- bias = tf.zeros([x.shape[1]])
-
- h, d = self.compute_next_h_d(
- meta_opt=meta_opt,
- w_bot=w_bot,
- w_top=w_top,
- bias=bias,
- backward_w=backward_w,
- x=x,
- z=z,
- d=d)
- hs.append(h)
-
- w_forward_var_idx = [variables.index(mod.w) for mod in rev_mods]
- w_backward_var_idx = [variables.index(mod.w) for mod in rev_backward_mods]
- b_var_idx = [variables.index(mod.b) for mod in rev_mods]
-
- # storage location for outputs of below loop
- grads = [None for _ in previous_state.variables]
-
- # over-ride learning rate for perturbation variables
- learning_rate = [None for _ in previous_state.variables]
-
- # This is a map -- no state is shared cross loop
- for l_idx, w_forward_idx, w_backward_idx, b_idx, upper_h, lower_h, lower_x, upper_x in utils.eqzip(
- range(len(w_forward_var_idx)), w_forward_var_idx, w_backward_var_idx,
- b_var_idx, hs[:-1], hs[1:], xs[::-1][1:], xs[::-1][:-1]):
-
- b_base = previous_state.variables[b_idx]
- change_w_forward, change_b = self.weight_change_for_layer(
- meta_opt=meta_opt,
- l_idx=l_idx,
- w_base=previous_state.variables[w_forward_idx],
- b_base=b_base,
- upper_h=upper_h,
- lower_h=lower_h,
- upper_x=upper_x,
- lower_x=lower_x,
- prefix='forward',
- include_bias=True)
-
- if self.identical_updates:
- change_w_backward = change_w_forward
- else:
- change_w_backward = self.weight_change_for_layer(
- meta_opt=meta_opt,
- l_idx=l_idx,
- w_base=previous_state.variables[w_backward_idx],
- b_base=b_base,
- upper_h=upper_h,
- lower_h=lower_h,
- upper_x=upper_x,
- lower_x=lower_x,
- prefix='backward',
- include_bias=False)
-
- grads[w_forward_idx] = change_w_forward
-
- grads[w_backward_idx] = change_w_backward
-
- grads[b_idx] = change_b
-
- cur_transformer = common.transformer_at_state(self,
- previous_state.variables)
- next_state = meta_opt.compute_next_state(
- grads,
- learning_rate=learning_rate,
- cur_state=previous_state,
- cur_transformer=lambda x: cur_transformer(x)[0])
- return next_state
-
- def initial_state(self, meta_opt):
- return meta_opt.initial_state(self.get_variables())
diff --git a/research/learning_unsupervised_learning/datasets/__init__.py b/research/learning_unsupervised_learning/datasets/__init__.py
deleted file mode 100644
index 9949cd96ca8f2fe1c39705a5ca8570de9cad5a66..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/datasets/__init__.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import mnist
diff --git a/research/learning_unsupervised_learning/datasets/common.py b/research/learning_unsupervised_learning/datasets/common.py
deleted file mode 100644
index 11f65ceab57a4114ca3876b3cb6eed86e2263745..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/datasets/common.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Copyright 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-
-import tensorflow as tf
-import numpy as np
-
-ImageLabelOnehot = collections.namedtuple('ImageLabelOnehot',
- ['image', 'label', 'label_onehot'])
-ImageLabelOnehotRegression = collections.namedtuple(
- "ImageLabelOnehotRegression",
- ["image", "label", "label_onehot", "regression_target"])
diff --git a/research/learning_unsupervised_learning/datasets/mnist.py b/research/learning_unsupervised_learning/datasets/mnist.py
deleted file mode 100644
index 6ee595d99ad2523042454f038b4665095f501caf..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/datasets/mnist.py
+++ /dev/null
@@ -1,74 +0,0 @@
-# Copyright 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-
-import sonnet as snt
-import tensorflow as tf
-from tensorflow.python.keras.datasets import mnist
-from learning_unsupervised_learning.datasets import common
-
-class Mnist(snt.AbstractModule):
- def __init__(self, device, batch_size=128, name="Mnist"):
- self.device = device
- self.batch_size = batch_size
-
- self._make_dataset()
- self.iterator = None
-
- super(Mnist, self).__init__(name=name)
-
- def _make_dataset(self):
- (x_train, y_train), (x_test, y_test) = mnist.load_data()
-
- x_train = x_train.reshape(60000, 784)
- x_test = x_test.reshape(10000, 784)
-
- dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))
- dataset = dataset.repeat()
- dataset = dataset.shuffle(self.batch_size * 3)
- dataset = dataset.batch(self.batch_size)
- def _map_fn(image, label):
- image = tf.to_float(image) / 255.
- label.set_shape([self.batch_size])
- label = tf.cast(label, dtype=tf.int32)
- label_onehot = tf.one_hot(label, 10)
- image = tf.reshape(image, [self.batch_size, 28, 28, 1])
- return common.ImageLabelOnehot(
- image=image, label=label, label_onehot=label_onehot)
-
- self.dataset = dataset.map(_map_fn)
-
- def _build(self):
- if self.iterator is None:
- self.iterator = self.dataset.make_one_shot_iterator()
- batch = self.iterator.get_next()
- [b.set_shape([self.batch_size] + b.shape.as_list()[1:]) for b in batch]
- return batch
-
-
-class TinyMnist(Mnist):
- def __init__(self, *args, **kwargs):
- kwargs.setdefault("name", "TinyMnist")
- super(TinyMnist, self).__init__(*args, **kwargs)
-
- def _make_dataset(self):
- super(TinyMnist, self)._make_dataset()
-
- def _map_fn(batch):
- new_img = tf.image.resize_images(batch.image, [14, 14])
- return common.ImageLabelOnehot(
- image=new_img, label=batch.label, label_onehot=batch.label_onehot)
-
- self.dataset = self.dataset.map(_map_fn)
diff --git a/research/learning_unsupervised_learning/evaluation.py b/research/learning_unsupervised_learning/evaluation.py
deleted file mode 100644
index 2ec40e99a672f9420200653b92818374e0e84d78..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/evaluation.py
+++ /dev/null
@@ -1,76 +0,0 @@
-# Copyright 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-
-"""Evaluation job.
-
-This sits on the side and performs evaluation on a saved model.
-This is a separate process for ease of use and stability of numbers.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-from learning_unsupervised_learning import utils
-
-
-def construct_evaluation_graph(theta_process_fn=None,
- w_learner_fn=None,
- dataset_fn=None,
- meta_objectives=None,
- ):
- """Construct the evaluation graph.
- """
- if meta_objectives is None:
- meta_objectives = []
-
- tf.train.create_global_step()
-
- local_device = ""
- remote_device = ""
-
- meta_opt = theta_process_fn(
- remote_device=remote_device, local_device=local_device)
-
- base_model = w_learner_fn(
- remote_device=remote_device, local_device=local_device)
-
- train_dataset = dataset_fn(device=local_device)
-
- # construct variables
- x, outputs = base_model(train_dataset())
- initial_state = base_model.initial_state(meta_opt, max_steps=10)
- next_state = base_model.compute_next_state(outputs, meta_opt, initial_state)
- with utils.state_barrier_context(next_state):
- train_one_step_op = meta_opt.assign_state(base_model, next_state)
-
- meta_objs = []
- for meta_obj_fn in meta_objectives:
- meta_obj = meta_obj_fn(local_device="", remote_device="")
- meta_objs.append(meta_obj)
- J = meta_obj(train_dataset, lambda x: base_model(x)[0])
- tf.summary.scalar(str(meta_obj.__class__.__name__)+"_J", tf.reduce_mean(J))
-
- # TODO(lmetz) this is kinda error prone.
- # We should share the construction of the global variables across train and
- # make sure both sets of savable variables are the same
- checkpoint_vars = meta_opt.remote_variables() + [tf.train.get_global_step()]
- for meta_obj in meta_objs:
- checkpoint_vars.extend(meta_obj.remote_variables())
-
- return checkpoint_vars, train_one_step_op, (base_model, train_dataset)
diff --git a/research/learning_unsupervised_learning/meta_objective/__init__.py b/research/learning_unsupervised_learning/meta_objective/__init__.py
deleted file mode 100644
index 54c46145e3c3a9f19110f92197f1d3cb2afe31fb..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/meta_objective/__init__.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-
-import sklearn
-import linear_regression
diff --git a/research/learning_unsupervised_learning/meta_objective/linear_regression.py b/research/learning_unsupervised_learning/meta_objective/linear_regression.py
deleted file mode 100644
index b49fc2529ccba08a6b47019cd7546f8fb409b28b..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/meta_objective/linear_regression.py
+++ /dev/null
@@ -1,258 +0,0 @@
-# Copyright 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-
-
-"""Closed form linear regression.
-
-Can be differentiated through.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-import numpy as np
-import sonnet as snt
-import tensorflow as tf
-
-from learning_unsupervised_learning import utils
-from learning_unsupervised_learning import variable_replace
-
-
-def solve_ridge(x, y, ridge_factor):
- with tf.name_scope("solve_ridge"):
- # Added a column of ones to the end of the feature matrix for bias
- A = tf.concat([x, tf.ones((x.shape.as_list()[0], 1))], axis=1)
-
- # Analytic solution for the ridge regression loss
- inv_target = tf.matmul(A, A, transpose_a=True)
- np_diag_penalty = ridge_factor * np.ones(
- A.shape.as_list()[1], dtype="float32")
- # Remove penalty on bias component of weights
- np_diag_penalty[-1] = 0.
- diag_penalty = tf.constant(np_diag_penalty)
- inv_target += tf.diag(diag_penalty)
-
- inv = tf.matrix_inverse(inv_target)
- w = tf.matmul(inv, tf.matmul(A, y, transpose_a=True))
- return w
-
-
-class LinearRegressionMetaObjective(snt.AbstractModule):
- """A meta objective based on training Ridge Regression with analytic solution.
-
- This is used to evaluate the performance of a given feature set trained in
- some other manner.
- """
-
- def __init__(self,
- local_device=None,
- remote_device=None,
- zero_one_labels=True,
- normalize_y_hat=True,
- normalize_act=False,
- averages=1,
- ridge_factor=0.1,
- center_y=True,
- hinge_loss=False,
- samples_per_class=10,
- test_train_scalar=1.0,
- ):
- self._local_device = local_device
- self._remote_device = remote_device
- self.zero_one_labels = zero_one_labels
- self.normalize_y_hat = normalize_y_hat
- self.normalize_act = normalize_act
- self.ridge_factor = ridge_factor
- self.averages = averages
- self.samples_per_class = samples_per_class
- self.center_y=center_y
- self.test_train_scalar=test_train_scalar
- self.hinge_loss = hinge_loss
-
- self.dataset_map = {}
-
- super(LinearRegressionMetaObjective,
- self).__init__(name="LinearRegressionMetaObjective")
-
- def _build(self, dataset, feature_transformer):
- if self.samples_per_class is not None:
- if dataset not in self.dataset_map:
- # datasets are outside of frames from while loops
- with tf.control_dependencies(None):
- self.dataset_map[dataset] = utils.sample_n_per_class(
- dataset, self.samples_per_class)
-
- dataset = self.dataset_map[dataset]
-
- stats = collections.defaultdict(list)
- losses = []
- # TODO(lmetz) move this to ingraph control flow?
- for _ in xrange(self.averages):
- loss, stat = self._build_once(dataset, feature_transformer)
- losses.append(loss)
- for k, v in stat.items():
- stats[k].append(v)
- stats = {k: tf.add_n(v) / float(len(v)) for k, v in stats.items()}
-
- summary_updates = []
- for k, v in stats.items():
- tf.summary.scalar(k, v)
-
- with tf.control_dependencies(summary_updates):
- return tf.add_n(losses) / float(len(losses))
-
- def _build_once(self, dataset, feature_transformer):
- with tf.device(self._local_device):
- batch = dataset()
- num_classes = batch.label_onehot.shape.as_list()[1]
-
- regression_mod = snt.Linear(num_classes)
-
- if self.normalize_act:
-
- def normalize_transformer(x):
- unnorm_x = feature_transformer(x)
- return tf.nn.l2_normalize(unnorm_x, 0)
-
- feature_transformer_wrap = normalize_transformer
- else:
- feature_transformer_wrap = feature_transformer
-
- # construct the variables of the right shape in the sonnet module by
- # calling a forward pass through the regressor.
- with utils.assert_no_new_variables():
- dummy_features = feature_transformer_wrap(batch)
- regression_mod(dummy_features)
- reg_w = regression_mod.w
- reg_b = regression_mod.b
-
- batch_test = dataset()
- all_batch = utils.structure_map_multi(lambda x: tf.concat(x, 0), [batch, batch_test])
- #all_batch = tf.concat([batch, batch_test], 0)
- # Grab a new batch of data from the dataset.
- features = feature_transformer_wrap(all_batch)
- features, features_test = utils.structure_map_split(lambda x: tf.split(x, 2, axis=0), features)
-
- def center_y(y):
- y -= tf.reduce_mean(y)
- y *= tf.rsqrt(tf.reduce_mean(tf.reduce_sum(y**2, axis=[1], keep_dims=True)))
- return y
- def get_y_vec(batch):
- y_pieces = []
- if hasattr(batch, "label_onehot"):
- if self.zero_one_labels:
- y_pieces += [batch.label_onehot]
- else:
- y_pieces += [2. * batch.label_onehot - 1.]
- if hasattr(batch, "regression_target"):
- y_pieces += [batch.regression_target]
- y = tf.concat(y_pieces, 1)
- if self.center_y:
- y = center_y(y)
- return y
-
- y_train = get_y_vec(batch)
-
- w = solve_ridge(features, y_train, self.ridge_factor)
-
- # Generate features from another batch to evaluate loss on the validation
- # set. This provide a less overfit signal to the learned optimizer.
- y_test = get_y_vec(batch_test)
-
- def compute_logit(features):
- # We have updated the classifier mod in previous steps, we need to
- # substitute out those variables to get new values.
- replacement = collections.OrderedDict([(reg_w, w[:-1]), (reg_b, w[-1])])
- with variable_replace.variable_replace(replacement):
- logits = regression_mod(features)
-
- return logits
-
- batch_size = y_train.shape.as_list()[0]
-
- logit_train = compute_logit(features)
- logit_test_unnorm = compute_logit(features_test)
- if self.normalize_y_hat:
- logit_test = logit_test_unnorm / tf.sqrt(
- tf.reduce_sum(logit_test_unnorm**2, axis=[1], keep_dims=True))
- else:
- logit_test = logit_test_unnorm
-
- stats = {}
-
- if self.hinge_loss:
- # slightly closer to the true classification loss
- # any distance smaller than 1 is guaranteed to map to the correct class
- mse_test = tf.reduce_sum(tf.nn.relu(tf.reduce_sum(tf.square(logit_test - y_test), axis=1)-1.)) / batch_size
- else:
- mse_test = tf.reduce_sum(tf.square(logit_test - y_test)) / batch_size
-
- stats["mse_test"] = mse_test
-
- mse_train = tf.reduce_sum(tf.square(logit_train - y_train)) / batch_size
- stats["mse_train"] = mse_train
-
- is_correct_test = tf.equal(tf.argmax(logit_test, 1), tf.argmax(y_test, 1))
- accuracy_test = tf.reduce_mean(tf.cast(is_correct_test, tf.float32))
- stats["accuracy_test"] = accuracy_test
-
- def test_confusion_fn():
- test_confusion = tf.confusion_matrix(tf.argmax(y_test, 1), tf.argmax(logit_test, 1))
- test_confusion = tf.to_float(test_confusion) / tf.constant((logit_test.shape.as_list()[0] / float(logit_test.shape.as_list()[1])), dtype=tf.float32)
- test_confusion = tf.expand_dims(tf.expand_dims(test_confusion, 0), 3)
- return test_confusion
- tf.summary.image("test_confusion", test_confusion_fn())
-
- def train_confusion_fn():
- train_confusion = tf.confusion_matrix(tf.argmax(y_train, 1), tf.argmax(logit_train, 1))
- train_confusion = tf.to_float(train_confusion) / tf.constant((logit_train.shape.as_list()[0] / float(logit_train.shape.as_list()[1])), dtype=tf.float32)
- train_confusion = tf.expand_dims(tf.expand_dims(train_confusion, 0), 3)
- return train_confusion
- tf.summary.image("train_confusion", train_confusion_fn())
-
- is_correct = tf.equal(tf.argmax(logit_train, 1), tf.argmax(y_train, 1))
- accuracy_train = tf.reduce_mean(tf.cast(is_correct, tf.float32))
- stats["accuracy_train"] = accuracy_train
-
- reg = self.ridge_factor * tf.reduce_sum(tf.square(w[:-1])) / batch_size
- stats["ridge_component"] = reg
-
- stats["total_loss"] = mse_test + reg
-
- loss_to_train_at = (reg+ mse_test) * self.test_train_scalar + (mse_train + reg)*(1 - self.test_train_scalar)
-
- loss_to_train_at = tf.identity(loss_to_train_at)
-
- # Minimizing the test loss should not require regurization because the
- # metaobjective is solved for the training loss
- return loss_to_train_at, stats
-
- def local_variables(self):
- """List of variables that need to be updated for each evaluation.
-
- These variables should not be stored on a parameter server and
- should be reset every computation of a meta_objective loss.
-
- Returns:
- vars: list of tf.Variable
- """
- return list(
- snt.get_variables_in_module(self, tf.GraphKeys.TRAINABLE_VARIABLES))
-
- def remote_variables(self):
- return []
diff --git a/research/learning_unsupervised_learning/meta_objective/sklearn.py b/research/learning_unsupervised_learning/meta_objective/sklearn.py
deleted file mode 100644
index 4f1f2d59102c511fd42ad323c32ab1709bd60c90..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/meta_objective/sklearn.py
+++ /dev/null
@@ -1,167 +0,0 @@
-# Copyright 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-
-"""
-
-Can NOT be differentiated through.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-import numpy as np
-import sonnet as snt
-import tensorflow as tf
-from tensorflow.python.framework import function
-
-from learning_unsupervised_learning import utils
-
-from learning_unsupervised_learning.meta_objective import utils as meta_obj_utils
-
-from sklearn import svm
-from sklearn import linear_model
-
-
-def build_fit(device, model_fn, num_classes, probs=True):
-
- def _py_fit_predict(trX, trY, teX):
- assert len(np.unique(trY)) == num_classes
- model = model_fn()
- model.fit(trX, trY)
- trP = model.predict(trX)
- teP = model.predict(teX)
- if probs:
- teP_probs = model.predict_log_proba(teX)
- return trP.astype(np.int64), teP.astype(np.int64), teP_probs.astype(
- np.float32)
- else:
- teP = model.predict(teX)
- return trP.astype(np.int64), teP.astype(np.int64)
-
- def return_fn(trX, trY, teX):
- with tf.device(device):
- with tf.device("/cpu:0"):
- if probs:
- return tf.py_func(
- _py_fit_predict,
- [tf.identity(trX),
- tf.identity(trY),
- tf.identity(teX)], [tf.int64, tf.int64, tf.float32])
- else:
- return tf.py_func(
- _py_fit_predict,
- [tf.identity(trX),
- tf.identity(trY),
- tf.identity(teX)], [tf.int64, tf.int64])
-
- return return_fn
-
-
-class SKLearn(meta_obj_utils.MultiTrialMetaObjective):
-
- def __init__(
- self,
- local_device=None,
- remote_device=None,
- averages=1,
- samples_per_class=10,
- probs=False,
- stddev=0.01,
- n_samples=10,
- name="SKLearn",
- ):
- self._local_device = local_device
- self._remote_device = remote_device
- self.name = name
- self.probs = probs
- self.n_samples = n_samples
- self.stddev = stddev
-
- super(SKLearn, self).__init__(
- name=name, samples_per_class=samples_per_class, averages=averages)
-
- def _get_model(self):
- raise NotImplemented()
-
- def _build_once(self, dataset, feature_transformer):
- with tf.device(self._local_device):
- tr_batch = dataset()
- te_batch = dataset()
- num_classes = tr_batch.label_onehot.shape.as_list()[1]
- all_batch = utils.structure_map_multi(lambda x: tf.concat(x, 0),
- [tr_batch, te_batch])
- features = feature_transformer(all_batch)
- trX, teX = utils.structure_map_split(lambda x: tf.split(x, 2, axis=0),
- features)
- trY = tf.to_int64(tr_batch.label)
- trY_onehot = tf.to_int32(tr_batch.label_onehot)
- teY = tf.to_int64(te_batch.label)
- teY_shape = teY.shape.as_list()
-
- def blackbox((trX, trY, teX, teY)):
- trY = tf.to_int32(tf.rint(trY))
- teY = tf.to_int32(tf.rint(teY))
- tf_fn = build_fit(
- self._local_device,
- self._get_model,
- num_classes=num_classes,
- probs=self.probs)
- if self.probs:
- trP, teP, teP_probs = tf_fn(trX, trY, teX)
- else:
- trP, teP = tf_fn(trX, trY, teX)
-
- teY.set_shape(teY_shape)
- if self.probs:
- onehot = tf.one_hot(teY, num_classes)
- crossent = -tf.reduce_sum(onehot * teP_probs, [1])
- return tf.reduce_mean(crossent)
- else:
- # use error rate as the loss if no surrogate is avalible.
- return 1 - tf.reduce_mean(
- tf.to_float(tf.equal(teY, tf.to_int32(teP))))
-
- test_loss = blackbox((trX, tf.to_float(trY), teX, tf.to_float(teY)))
-
- stats = {}
-
- tf_fn = build_fit(
- self._local_device,
- self._get_model,
- num_classes=num_classes,
- probs=self.probs)
- if self.probs:
- trP, teP, teP_probs = tf_fn(trX, trY, teX)
- else:
- trP, teP = tf_fn(trX, trY, teX)
- stats["%s/accuracy_train" % self.name] = tf.reduce_mean(
- tf.to_float(tf.equal(tf.to_int32(trY), tf.to_int32(trP))))
- stats["%s/accuracy_test" % self.name] = tf.reduce_mean(
- tf.to_float(tf.equal(tf.to_int32(teY), tf.to_int32(teP))))
- stats["%s/test_loss" % self.name] = test_loss
- return test_loss, stats
-
-
-class LogisticRegression(SKLearn):
-
- def __init__(self, C=1.0, name="LogisticRegression", probs=True, **kwargs):
- self.C = C
- super(LogisticRegression, self).__init__(name=name, probs=probs, **kwargs)
-
- def _get_model(self):
- return linear_model.LogisticRegression(C=self.C)
diff --git a/research/learning_unsupervised_learning/meta_objective/utils.py b/research/learning_unsupervised_learning/meta_objective/utils.py
deleted file mode 100644
index a29197d1d0cb7f0fdcebac3980027640651f185b..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/meta_objective/utils.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-import numpy as np
-import sonnet as snt
-import tensorflow as tf
-
-from learning_unsupervised_learning import optimizers
-from learning_unsupervised_learning import utils
-from learning_unsupervised_learning import summary_utils
-from learning_unsupervised_learning import variable_replace
-
-class MultiTrialMetaObjective(snt.AbstractModule):
- def __init__(self, samples_per_class, averages, **kwargs):
- self.samples_per_class = samples_per_class
- self.averages = averages
- self.dataset_map = {}
-
- super(MultiTrialMetaObjective,
- self).__init__(**kwargs)
-
- def _build(self, dataset, feature_transformer):
- if self.samples_per_class is not None:
- if dataset not in self.dataset_map:
- # datasets are outside of frames from while loops
- with tf.control_dependencies(None):
- self.dataset_map[dataset] = utils.sample_n_per_class(
- dataset, self.samples_per_class)
-
- dataset = self.dataset_map[dataset]
-
- stats = collections.defaultdict(list)
- losses = []
- # TODO(lmetz) move this to ingraph control flow?
- for _ in xrange(self.averages):
- loss, stat = self._build_once(dataset, feature_transformer)
- losses.append(loss)
- for k, v in stat.items():
- stats[k].append(v)
- stats = {k: tf.add_n(v) / float(len(v)) for k, v in stats.items()}
-
- for k, v in stats.items():
- tf.summary.scalar(k, v)
-
- return tf.add_n(losses) / float(len(losses))
-
- def local_variables(self):
- """List of variables that need to be updated for each evaluation.
-
- These variables should not be stored on a parameter server and
- should be reset every computation of a meta_objective loss.
-
- Returns:
- vars: list of tf.Variable
- """
- return list(
- snt.get_variables_in_module(self, tf.GraphKeys.TRAINABLE_VARIABLES))
-
- def remote_variables(self):
- return []
diff --git a/research/learning_unsupervised_learning/optimizers.py b/research/learning_unsupervised_learning/optimizers.py
deleted file mode 100644
index 02c6106b19d1255907beb0ade07c46c5b065f701..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/optimizers.py
+++ /dev/null
@@ -1,133 +0,0 @@
-# Copyright 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-
-
-"""Optimizers for use in unrolled optimization.
-
-These optimizers contain a compute_updates function and its own ability to keep
-track of internal state.
-These functions can be used with a tf.while_loop to perform multiple training
-steps per sess.run.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import abc
-import collections
-import tensorflow as tf
-import sonnet as snt
-
-from learning_unsupervised_learning import utils
-
-from tensorflow.python.framework import ops
-from tensorflow.python.ops import math_ops
-from tensorflow.python.ops import resource_variable_ops
-from tensorflow.python.training import optimizer
-from tensorflow.python.training import training_ops
-
-
-class UnrollableOptimizer(snt.AbstractModule):
- """Interface for optimizers that can be used in unrolled computation.
- apply_gradients is derrived from compute_update and assign_state.
- """
-
- def __init__(self, *args, **kwargs):
- super(UnrollableOptimizer, self).__init__(*args, **kwargs)
- self()
-
- @abc.abstractmethod
- def compute_updates(self, xs, gs, state=None):
- """Compute next step updates for a given variable list and state.
-
- Args:
- xs: list of tensors
- The "variables" to perform an update on.
- Note these must match the same order for which get_state was originally
- called.
- gs: list of tensors
- Gradients of `xs` with respect to some loss.
- state: Any
- Optimizer specific state to keep track of accumulators such as momentum
- terms
- """
- raise NotImplementedError()
-
- def _build(self):
- pass
-
- @abc.abstractmethod
- def get_state(self, var_list):
- """Get the state value associated with a list of tf.Variables.
-
- This state is commonly going to be a NamedTuple that contains some
- mapping between variables and the state associated with those variables.
- This state could be a moving momentum variable tracked by the optimizer.
-
- Args:
- var_list: list of tf.Variable
- Returns:
- state: Any
- Optimizer specific state
- """
- raise NotImplementedError()
-
- def assign_state(self, state):
- """Assigns the state to the optimizers internal variables.
-
- Args:
- state: Any
- Returns:
- op: tf.Operation
- The operation that performs the assignment.
- """
- raise NotImplementedError()
-
- def apply_gradients(self, grad_vars):
- gradients, variables = zip(*grad_vars)
- state = self.get_state(variables)
- new_vars, new_state = self.compute_updates(variables, gradients, state)
- assign_op = self.assign_state(new_state)
- op = utils.assign_variables(variables, new_vars)
- return tf.group(assign_op, op, name="apply_gradients")
-
-
-class UnrollableGradientDescentRollingOptimizer(UnrollableOptimizer):
-
- def __init__(self,
- learning_rate,
- name="UnrollableGradientDescentRollingOptimizer"):
- self.learning_rate = learning_rate
- super(UnrollableGradientDescentRollingOptimizer, self).__init__(name=name)
-
-
- def compute_updates(self, xs, gs, learning_rates, state):
- new_vars = []
- for x, g, lr in utils.eqzip(xs, gs, learning_rates):
- if lr is None:
- lr = self.learning_rate
- if g is not None:
- new_vars.append((x * (1 - lr) - g * lr))
- else:
- new_vars.append(x)
- return new_vars, state
-
- def get_state(self, var_list):
- return tf.constant(0.0)
-
- def assign_state(self, state, var_list=None):
- return tf.no_op()
diff --git a/research/learning_unsupervised_learning/run_eval.py b/research/learning_unsupervised_learning/run_eval.py
deleted file mode 100644
index dcb2529dd4cc5354012befd5790c8d402f4caafd..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/run_eval.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# Copyright 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-""" Script that iteratively applies the unsupervised update rule and evaluates the
-
-meta-objective performance.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from absl import flags
-from absl import app
-
-from learning_unsupervised_learning import evaluation
-from learning_unsupervised_learning import datasets
-from learning_unsupervised_learning import architectures
-from learning_unsupervised_learning import summary_utils
-from learning_unsupervised_learning import meta_objective
-
-import tensorflow as tf
-import sonnet as snt
-
-from tensorflow.contrib.framework.python.framework import checkpoint_utils
-
-flags.DEFINE_string("checkpoint_dir", None, "Dir to load pretrained update rule from")
-flags.DEFINE_string("train_log_dir", None, "Training log directory")
-
-FLAGS = flags.FLAGS
-
-
-def train(train_log_dir, checkpoint_dir, eval_every_n_steps=10, num_steps=3000):
- dataset_fn = datasets.mnist.TinyMnist
- w_learner_fn = architectures.more_local_weight_update.MoreLocalWeightUpdateWLearner
- theta_process_fn = architectures.more_local_weight_update.MoreLocalWeightUpdateProcess
-
- meta_objectives = []
- meta_objectives.append(
- meta_objective.linear_regression.LinearRegressionMetaObjective)
- meta_objectives.append(meta_objective.sklearn.LogisticRegression)
-
- checkpoint_vars, train_one_step_op, (
- base_model, dataset) = evaluation.construct_evaluation_graph(
- theta_process_fn=theta_process_fn,
- w_learner_fn=w_learner_fn,
- dataset_fn=dataset_fn,
- meta_objectives=meta_objectives)
- batch = dataset()
- pre_logit, outputs = base_model(batch)
-
- global_step = tf.train.get_or_create_global_step()
- var_list = list(
- snt.get_variables_in_module(base_model, tf.GraphKeys.TRAINABLE_VARIABLES))
-
- tf.logging.info("all vars")
- for v in tf.all_variables():
- tf.logging.info(" %s" % str(v))
- global_step = tf.train.get_global_step()
- accumulate_global_step = global_step.assign_add(1)
- reset_global_step = global_step.assign(0)
-
- train_op = tf.group(
- train_one_step_op, accumulate_global_step, name="train_op")
-
- summary_op = tf.summary.merge_all()
-
- file_writer = summary_utils.LoggingFileWriter(train_log_dir, regexes=[".*"])
- if checkpoint_dir:
- str_var_list = checkpoint_utils.list_variables(checkpoint_dir)
- name_to_v_map = {v.op.name: v for v in tf.all_variables()}
- var_list = [
- name_to_v_map[vn] for vn, _ in str_var_list if vn in name_to_v_map
- ]
- saver = tf.train.Saver(var_list)
- missed_variables = [
- v.op.name for v in set(
- snt.get_variables_in_scope("LocalWeightUpdateProcess",
- tf.GraphKeys.GLOBAL_VARIABLES)) -
- set(var_list)
- ]
- assert len(missed_variables) == 0, "Missed a theta variable."
-
- hooks = []
-
- with tf.train.SingularMonitoredSession(master="", hooks=hooks) as sess:
-
- # global step should be restored from the evals job checkpoint or zero for fresh.
- step = sess.run(global_step)
-
- if step == 0 and checkpoint_dir:
- tf.logging.info("force restore")
- saver.restore(sess, checkpoint_dir)
- tf.logging.info("force restore done")
- sess.run(reset_global_step)
- step = sess.run(global_step)
-
- while step < num_steps:
- if step % eval_every_n_steps == 0:
- s, _, step = sess.run([summary_op, train_op, global_step])
- file_writer.add_summary(s, step)
- else:
- _, step = sess.run([train_op, global_step])
-
-
-def main(argv):
- train(FLAGS.train_log_dir, FLAGS.checkpoint_dir)
-
-
-if __name__ == "__main__":
- app.run(main)
diff --git a/research/learning_unsupervised_learning/summary_utils.py b/research/learning_unsupervised_learning/summary_utils.py
deleted file mode 100644
index d5c0fdd9186bdef0b4e25ca10978e22ab910d276..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/summary_utils.py
+++ /dev/null
@@ -1,181 +0,0 @@
-# Copyright 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-
-
-import collections
-import functools
-import threading
-import tensorflow as tf
-import matplotlib
-import numpy as np
-import time
-import re
-import math
-matplotlib.use("Agg")
-
-import matplotlib.pyplot as plt
-import scipy.signal
-
-from tensorflow.python.util import tf_should_use
-from tensorflow.contrib.summary import summary_ops
-from tensorflow.python.ops import summary_op_util
-from tensorflow.contrib.summary import gen_summary_ops
-
-_DEBUG_DISABLE_SUMMARIES=False
-
-class LoggingFileWriter(tf.summary.FileWriter):
- """A FileWriter that also logs things out.
-
- This is entirely for ease of debugging / not having to open up Tensorboard
- a lot.
- """
-
- def __init__(self, logdir, regexes=[], **kwargs):
- self.regexes = regexes
- super(LoggingFileWriter, self).__init__(logdir, **kwargs)
-
- def add_summary(self, summary, global_step):
- if type(summary) != tf.Summary:
- summary_p = tf.Summary()
- summary_p.ParseFromString(summary)
- summary = summary_p
- for s in summary.value:
- for exists in [re.match(p, s.tag) for p in self.regexes]:
- if exists is not None:
- tf.logging.info("%d ] %s : %f", global_step, s.tag, s.simple_value)
- break
- super(LoggingFileWriter, self).add_summary(summary, global_step)
-
-
-def image_grid(images, max_grid_size=4, border=1):
- """Given images and N, return first N^2 images as an NxN image grid.
-
- Args:
- images: a `Tensor` of size [batch_size, height, width, channels]
- max_grid_size: Maximum image grid height/width
-
- Returns:
- Single image batch, of dim [1, h*n, w*n, c]
- """
- batch_size = images.shape.as_list()[0]
- to_pad = int((np.ceil(np.sqrt(batch_size)))**2 - batch_size)
- images = tf.pad(images, [[0, to_pad], [0, border], [0, border], [0, 0]])
-
- batch_size = images.shape.as_list()[0]
- grid_size = min(int(np.sqrt(batch_size)), max_grid_size)
- assert images.shape.as_list()[0] >= grid_size * grid_size
-
- # If we have a depth channel
- if images.shape.as_list()[-1] == 4:
- images = images[:grid_size * grid_size, :, :, 0:3]
- depth = tf.image.grayscale_to_rgb(images[:grid_size * grid_size, :, :, 3:4])
-
- images = tf.reshape(images, [-1, images.shape.as_list()[2], 3])
- split = tf.split(images, grid_size, axis=0)
- depth = tf.reshape(depth, [-1, images.shape.as_list()[2], 3])
- depth_split = tf.split(depth, grid_size, axis=0)
- grid = tf.concat(split + depth_split, 1)
- return tf.expand_dims(grid, 0)
- else:
- images = images[:grid_size * grid_size, :, :, :]
- images = tf.reshape(
- images, [-1, images.shape.as_list()[2],
- images.shape.as_list()[3]])
- split = tf.split(value=images, num_or_size_splits=grid_size, axis=0)
- grid = tf.concat(split, 1)
- return tf.expand_dims(grid, 0)
-
-
-def first_layer_weight_image(weight, shape):
- weight_image = tf.reshape(weight,
- shape + [tf.identity(weight).shape.as_list()[1]])
- # [winx, winy, wout]
- mean, var = tf.nn.moments(weight_image, [0,1,2], keep_dims=True)
- #mean, var = tf.nn.moments(weight_image, [0,1], keep_dims=True)
- weight_image = (weight_image - mean) / tf.sqrt(var + 1e-5)
- weight_image = (weight_image + 1.0) / 2.0
- weight_image = tf.clip_by_value(weight_image, 0, 1)
- weight_image = tf.transpose(weight_image, (3, 0, 1, 2))
- grid = image_grid(weight_image, max_grid_size=10)
- return grid
-
-def inner_layer_weight_image(weight):
- """Visualize a weight matrix of an inner layer.
- Add padding to make it square, then visualize as a gray scale image
- """
- weight = tf.identity(weight) # turn into a tensor
- weight = weight / (tf.reduce_max(tf.abs(weight), [0], keep_dims=True))
- weight = tf.reshape(weight, [1]+weight.shape.as_list() + [1])
- return weight
-
-
-def activation_image(activations, label_onehot):
- """Make a row sorted by class for each activation. Put a black line around the activations."""
- labels = tf.argmax(label_onehot, axis=1)
- _, n_classes = label_onehot.shape.as_list()
- mean, var = tf.nn.moments(activations, [0, 1])
- activations = (activations - mean)/tf.sqrt(var+1e-5)
-
- activations = tf.clip_by_value(activations, -1, 1)
- activations = (activations + 1.0) / 2.0 # shift to [0, 1]
-
- canvas = []
- for i in xrange(n_classes):
- inds = tf.where(tf.equal(labels, i))
-
- def _gather():
- return tf.squeeze(tf.gather(activations, inds), 1)
-
- def _empty():
- return tf.zeros([0, activations.shape.as_list()[1]], dtype=tf.float32)
-
- assert inds.shape.as_list()[0] is None
- x = tf.cond(tf.equal(tf.shape(inds)[0], 0), _empty, _gather)
- canvas.append(x)
- canvas.append(tf.zeros([1, activations.shape.as_list()[1]]))
- canvas = tf.concat(canvas, 0)
- canvas = tf.reshape(canvas, [1, activations.shape.as_list()[0]+n_classes, canvas.shape.as_list()[1], 1])
- return canvas
-
-
-def sorted_images(images, label_onehot):
- # images is [bs, x, y, c]
- labels = tf.argmax(label_onehot, axis=1)
- _, n_classes = label_onehot.shape.as_list()
- to_stack = []
- for i in xrange(n_classes):
- inds = tf.where(tf.equal(labels, i))
-
- def _gather():
- return tf.squeeze(tf.gather(images, inds), 1)
-
- def _empty():
- return tf.zeros([0] + images.shape.as_list()[1:], dtype=tf.float32)
-
- assert inds.shape.as_list()[0] is None
- x = tf.cond(tf.equal(tf.shape(inds)[0], 0), _empty, _gather)
- to_stack.append(x)
- # pad / trim all up to 10.
- padded = []
- for t in to_stack:
- n_found = tf.shape(t)[0]
- pad = tf.pad(t[0:10], tf.stack([tf.stack([0,tf.maximum(0, 10-n_found)]), [0,0], [0,0], [0,0]]))
- padded.append(pad)
-
- xs = [tf.concat(tf.split(p, 10), axis=1) for p in padded]
- ys = tf.concat(xs, axis=2)
- ys = tf.cast(tf.clip_by_value(ys, 0., 1.) * 255., tf.uint8)
- return ys
diff --git a/research/learning_unsupervised_learning/utils.py b/research/learning_unsupervised_learning/utils.py
deleted file mode 100644
index ca56ca93181df1ed9c403fef79e8154c3c9515b4..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/utils.py
+++ /dev/null
@@ -1,287 +0,0 @@
-# Copyright 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Utilities.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import contextlib
-import tensorflow as tf
-import sonnet as snt
-import itertools
-import functools
-
-from tensorflow.core.framework import node_def_pb2
-from tensorflow.python.framework import device as pydev
-from tensorflow.python.framework import errors
-from tensorflow.python.ops import variable_scope as variable_scope_ops
-from sonnet.python.modules import util as snt_util
-
-from tensorflow.python.util import nest
-
-
-def eqzip(*args):
- """Zip but raises error if lengths don't match.
-
- Args:
- *args: list of lists or tuples
- Returns:
- list: the result of zip
- Raises:
- ValueError: when the lengths don't match
- """
-
- sizes = [len(x) for x in args]
- if not all([sizes[0] == x for x in sizes]):
- raise ValueError("Lists are of different sizes. \n %s"%str(sizes))
- return zip(*args)
-
-
-@contextlib.contextmanager
-def assert_no_new_variables():
- """Ensure that no tf.Variables are constructed inside the context.
-
- Yields:
- None
- Raises:
- ValueError: if there is a variable created.
- """
- num_vars = len(tf.global_variables())
- old_variables = tf.global_variables()
- yield
- if len(tf.global_variables()) != num_vars:
- new_vars = set(tf.global_variables()) - set(old_variables)
- tf.logging.error("NEW VARIABLES CREATED")
- tf.logging.error(10*"=")
- for v in new_vars:
- tf.logging.error(v)
-
- raise ValueError("Variables created inside an "
- "assert_no_new_variables context")
- if old_variables != tf.global_variables():
- raise ValueError("Variables somehow changed inside an "
- "assert_no_new_variables context."
- "This means something modified the tf.global_variables()")
-
-
-def get_variables_in_modules(module_list):
- var_list = []
- for m in module_list:
- var_list.extend(snt.get_variables_in_module(m))
- return var_list
-
-
-def state_barrier_context(state):
- """Return a context manager that prevents interior ops from running
- unless the whole state has been computed.
-
- This is to prevent assign race conditions.
- """
- tensors = [x for x in nest.flatten(state) if type(x) == tf.Tensor]
- tarray = [x.flow for x in nest.flatten(state) if hasattr(x, "flow")]
- return tf.control_dependencies(tensors + tarray)
-
-
-def _identity_fn(tf_entity):
- if hasattr(tf_entity, "identity"):
- return tf_entity.identity()
- else:
- return tf.identity(tf_entity)
-
-
-def state_barrier_result(state):
- """Return the same state, but with a control dependency to prevent it from
- being partially computed
- """
- with state_barrier_context(state):
- return nest.map_structure(_identity_fn, state)
-
-
-def train_iterator(num_iterations):
- """Iterator that returns an index of the current step.
- This iterator runs forever if num_iterations is None
- otherwise it runs for some fixed amount of steps.
- """
- if num_iterations is None:
- return itertools.count()
- else:
- return xrange(num_iterations)
-
-
-def print_op(op, msg):
- """Print a string and return an op wrapped in a control dependency to make
- sure it ran."""
- print_op = tf.Print(tf.constant(0), [tf.constant(0)], msg)
- return tf.group(op, print_op)
-
-
-class MultiQueueRunner(tf.train.QueueRunner):
- """A QueueRunner with multiple queues """
- def __init__(self, queues, enqueue_ops):
- close_op = tf.group(* [q.close() for q in queues])
- cancel_op = tf.group(
- * [q.close(cancel_pending_enqueues=True) for q in queues])
- queue_closed_exception_types = (errors.OutOfRangeError,)
-
- enqueue_op = tf.group(*enqueue_ops, name="multi_enqueue")
-
- super(MultiQueueRunner, self).__init__(
- queues[0],
- enqueue_ops=[enqueue_op],
- close_op=close_op,
- cancel_op=cancel_op,
- queue_closed_exception_types=queue_closed_exception_types)
-
-
-# This function is not elegant, but I tried so many other ways to get this to
-# work and this is the only one that ended up not incuring significant overhead
-# or obscure tensorflow bugs.
-def sample_n_per_class(dataset, samples_per_class):
- """Create a new callable / dataset object that returns batches of each with
- samples_per_class per label.
-
- Args:
- dataset: fn
- samples_per_class: int
- Returns:
- function, [] -> batch where batch is the same type as the return of
- dataset().
- """
-
- with tf.control_dependencies(None), tf.name_scope(None):
- with tf.name_scope("queue_runner/sample_n_per_class"):
- batch = dataset()
- num_classes = batch.label_onehot.shape.as_list()[1]
- batch_size = num_classes * samples_per_class
-
- flatten = nest.flatten(batch)
- queues = []
- enqueue_ops = []
- capacity = samples_per_class * 20
- for i in xrange(num_classes):
- queue = tf.FIFOQueue(
- capacity=capacity,
- shapes=[f.shape.as_list()[1:] for f in flatten],
- dtypes=[f.dtype for f in flatten])
- queues.append(queue)
-
- idx = tf.where(tf.equal(batch.label, i))
- sub_batch = []
- to_enqueue = []
- for elem in batch:
- new_e = tf.gather(elem, idx)
- new_e = tf.squeeze(new_e, 1)
- to_enqueue.append(new_e)
-
- remaining = (capacity - queue.size())
- to_add = tf.minimum(tf.shape(idx)[0], remaining)
-
- def _enqueue():
- return queue.enqueue_many([t[:to_add] for t in to_enqueue])
-
- enqueue_op = tf.cond(
- tf.equal(to_add, 0), tf.no_op, _enqueue)
- enqueue_ops.append(enqueue_op)
-
- # This has caused many deadlocks / issues. This is some logging to at least
- # shed light to what is going on.
- print_lam = lambda: tf.Print(tf.constant(0.0), [q.size() for q in queues], "MultiQueueRunner queues status. Has capacity %d"%capacity)
- some_percent_of_time = tf.less(tf.random_uniform([]), 0.0005)
- maybe_print = tf.cond(some_percent_of_time, print_lam, lambda: tf.constant(0.0))
- with tf.control_dependencies([maybe_print]):
- enqueue_ops = [tf.group(e) for e in enqueue_ops]
- qr = MultiQueueRunner(queues=queues, enqueue_ops=enqueue_ops)
- tf.train.add_queue_runner(qr)
-
- def dequeue_batch():
- with tf.name_scope("sample_n_per_batch/dequeue/"):
- entries = []
- for q in queues:
- entries.append(q.dequeue_many(samples_per_class))
-
- flat_batch = [tf.concat(x, 0) for x in zip(*entries)]
- idx = tf.random_shuffle(tf.range(batch_size))
- flat_batch = [tf.gather(f, idx, axis=0) for f in flat_batch]
- return nest.pack_sequence_as(batch, flat_batch)
-
- return dequeue_batch
-
-def structure_map_multi(func, values):
- all_values = [nest.flatten(v) for v in values]
- rets = []
- for pair in zip(*all_values):
- rets.append(func(pair))
- return nest.pack_sequence_as(values[0], rets)
-
-def structure_map_split(func, value):
- vv = nest.flatten(value)
- rets = []
- for v in vv:
- rets.append(func(v))
- return [nest.pack_sequence_as(value, r) for r in zip(*rets)]
-
-def assign_variables(targets, values):
- return tf.group(*[t.assign(v) for t,v in eqzip(targets, values)],
- name="assign_variables")
-
-
-def create_variables_in_class_scope(method):
- """Force the variables constructed in this class to live in the sonnet module.
- Wraps a method on a sonnet module.
-
- For example the following will create two different variables.
- ```
- class Mod(snt.AbstractModule):
- @create_variables_in_class_scope
- def dynamic_thing(self, input, name):
- return snt.Linear(name)(input)
- mod.dynamic_thing(x, name="module_nameA")
- mod.dynamic_thing(x, name="module_nameB")
- # reuse
- mod.dynamic_thing(y, name="module_nameA")
- ```
- """
- @functools.wraps(method)
- def wrapper(obj, *args, **kwargs):
- def default_context_manager(reuse=None):
- variable_scope = obj.variable_scope
- return tf.variable_scope(variable_scope, reuse=reuse)
-
- variable_scope_context_manager = getattr(obj, "_enter_variable_scope",
- default_context_manager)
- graph = tf.get_default_graph()
-
- # Temporarily enter the variable scope to capture it
- with variable_scope_context_manager() as tmp_variable_scope:
- variable_scope = tmp_variable_scope
-
- with variable_scope_ops._pure_variable_scope(
- variable_scope, reuse=tf.AUTO_REUSE) as pure_variable_scope:
-
- name_scope = variable_scope.original_name_scope
- if name_scope[-1] != "/":
- name_scope += "/"
-
- with tf.name_scope(name_scope):
- sub_scope = snt_util.to_snake_case(method.__name__)
- with tf.name_scope(sub_scope) as scope:
- out_ops = method(obj, *args, **kwargs)
- return out_ops
-
- return wrapper
-
diff --git a/research/learning_unsupervised_learning/variable_replace.py b/research/learning_unsupervised_learning/variable_replace.py
deleted file mode 100644
index ebfbeadc8aba7f8a09e1392f1de8d7b33f10d43c..0000000000000000000000000000000000000000
--- a/research/learning_unsupervised_learning/variable_replace.py
+++ /dev/null
@@ -1,112 +0,0 @@
-# Copyright 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-
-from __future__ import absolute_import
-from __future__ import division
-
-import tensorflow as tf
-from contextlib import contextmanager
-
-from tensorflow.python.ops import variable_scope
-
-# sanity global state to ensure non recursive.
-_is_variable_replacing = [False]
-
-def in_variable_replace_scope():
- return _is_variable_replacing[0]
-
-@contextmanager
-def variable_replace(replacements, no_new=True):
- """ A context manager that replaces variables.
-
- This is a context manager that replaces all calls to
- get_variable with the variable in replacements.
- This function does not support recursive application.
-
- Args:
- replacements: dict
- dictionary mapping a variable to replace (the key), with
- the variable one wants to replace this variable with (the value).
- no_new: bool
- raise an error if variables were created.
- This is for sanity checking.
- Raises:
- ValueError: if a new variable or not all the replacements are used.
- """
- # TODO(lmetz) This function is a bit scary, as it relies on monkey patching
- # the call to get_variable. Ideally this can be done with variable_scope's
- # custom_getter attribute, but when initially writing this that was not
- # avalible.
-
- replacements = {k: v for k, v in replacements.items() if not k == v}
-
- init_vars = tf.trainable_variables()
- old_get_variable = variable_scope.get_variable
- old_tf_get_variable = tf.get_variable
-
- names_replace = {}
- has_replaced_names = []
- tf.logging.vlog(2, "Trying to replace")
- for k, v in replacements.items():
- tf.logging.vlog(2, k.name + " >> " + v.name)
- tf.logging.vlog(2, "===")
-
- for k, v in replacements.items():
- strip_name = k.name.replace("/read:0", "")
- strip_name = strip_name.replace(":0", "")
- names_replace[strip_name] = v
- # TODO(lmetz) is there a cleaner way to do this?
- def new_get_variable(name, *args, **kwargs):
- #print "Monkeypatch get variable run with name:", name
- n = tf.get_variable_scope().name + "/" + name
- #print "Monkeypatch get variable run with name:", n
- if n in names_replace:
- has_replaced_names.append(n)
- return names_replace[n]
- else:
- return old_get_variable(name, *args, **kwargs)
-
- # perform the monkey patch
- if _is_variable_replacing[0] == True:
- raise ValueError("No recursive calling to variable replace allowed.")
-
- variable_scope.get_variable = new_get_variable
- tf.get_variable = new_get_variable
-
- _is_variable_replacing[0] = True
-
- yield
-
- if set(has_replaced_names) != set(names_replace.keys()):
- print "Didn't use all replacements"
- print "replaced variables that are not requested??"
- print "==="
- for n in list(set(has_replaced_names) - set(names_replace.keys())):
- print n
- print "Missed replacing variables"
- print "==="
- for n in list(set(names_replace.keys()) - set(has_replaced_names)):
- print n, "==>", names_replace[n].name
- raise ValueError("Fix this -- see stderr")
-
- # undo the monkey patch
- tf.get_variable = old_tf_get_variable
- variable_scope.get_variable = old_get_variable
-
- _is_variable_replacing[0] = False
-
- final_vars = tf.trainable_variables()
- assert set(init_vars) == set(final_vars), "trainable variables changed"
diff --git a/research/lexnet_nc/README.md b/research/lexnet_nc/README.md
deleted file mode 100644
index 4ecb5d39867c2ebf7280b9d19bbabb41957b9465..0000000000000000000000000000000000000000
--- a/research/lexnet_nc/README.md
+++ /dev/null
@@ -1,215 +0,0 @@
-
-
-
-
-# LexNET for Noun Compound Relation Classification
-
-This is a [Tensorflow](http://www.tensorflow.org/) implementation of the LexNET
-algorithm for classifying relationships, specifically applied to classifying the
-relationships that hold between noun compounds:
-
-* *olive oil* is oil that is *made from* olives
-* *cooking oil* which is oil that is *used for* cooking
-* *motor oil* is oil that is *contained in* a motor
-
-The model is a supervised classifier that predicts the relationship that holds
-between the constituents of a two-word noun compound using:
-
-1. A neural "paraphrase" of each syntactic dependency path that connects the
- constituents in a large corpus. For example, given a sentence like *This fine
- oil is made from first-press olives*, the dependency path is something like
- `oil from POBJ> olive`.
-2. The distributional information provided by the individual words; i.e., the
- word embeddings of the two consituents.
-3. The distributional signal provided by the compound itself; i.e., the
- embedding of the noun compound in context.
-
-The model includes several variants: *path-based model* uses (1) alone, the
-*distributional model* uses (2) alone, and the *integrated model* uses (1) and
-(2). The *distributional-nc model* and the *integrated-nc* model each add (3).
-
-Training a model requires the following:
-
-1. A collection of noun compounds that have been labeled using a *relation
- inventory*. The inventory describes the specific relationships that you'd
- like the model to differentiate (e.g. *part of* versus *composed of* versus
- *purpose*), and generally may consist of tens of classes. You can download
- the dataset used in the paper from
- [here](https://vered1986.github.io/papers/Tratz2011_Dataset.tar.gz).
-2. A collection of word embeddings: the path-based model uses the word
- embeddings as part of the path representation, and the distributional models
- use the word embeddings directly as prediction features.
-3. The path-based model requires a collection of syntactic dependency parses
- that connect the constituents for each noun compound. To generate these,
- you'll need a corpus from which to train this data; we used Wikipedia and the
- [LDC GigaWord5](https://catalog.ldc.upenn.edu/LDC2011T07) corpora.
-
-# Contents
-
-The following source code is included here:
-
-* `learn_path_embeddings.py` is a script that trains and evaluates a path-based
- model to predict a noun-compound relationship given labeled noun-compounds and
- dependency parse paths.
-* `learn_classifier.py` is a script that trains and evaluates a classifier based
- on any combination of paths, word embeddings, and noun-compound embeddings.
-* `get_indicative_paths.py` is a script that generates the most indicative
- syntactic dependency paths for a particular relationship.
-
-Also included are utilities for preparing data for training:
-
-* `text_embeddings_to_binary.py` converts a text file containing word embeddings
- into a binary file that is quicker to load.
-* `extract_paths.py` finds all the dependency paths that connect words in a
- corpus.
-* `sorted_paths_to_examples.py` processes the output of `extract_paths.py` to
- produce summarized training data.
-
-This code (in particular, the utilities used to prepare the data) differs from
-the code that was used to prepare data for the paper. Notably, we used a
-proprietary dependency parser instead of spaCy, which is used here.
-
-# Dependencies
-
-* [TensorFlow](http://www.tensorflow.org/): see detailed installation
- instructions at that site.
-* [SciKit Learn](http://scikit-learn.org/): you can probably just install this
- with `pip install sklearn`.
-* [SpaCy](https://spacy.io/): `pip install spacy` ought to do the trick, along
- with the English model.
-
-# Creating the Model
-
-This sections described the steps necessary to create and evaluate the model
-described in the paper.
-
-## Generate Path Data
-
-To begin, you need three text files:
-
-1. **Corpus**. This file should contain natural language sentences, written with
- one sentence per line. For purposes of exposition, we'll assume that you
- have English Wikipedia serialized this way in `${HOME}/data/wiki.txt`.
-2. **Labeled Noun Compound Pairs**. This file contain (modfier, head, label)
- tuples, tab-separated, with one per line. The *label* represented the
- relationship between the head and the modifier; e.g., if `purpose` is one
- your labels, you could possibly include `toothpastepurpose`.
-3. **Word Embeddings**. We used the
- [GloVe](https://nlp.stanford.edu/projects/glove/) word embeddings; in
- particular the 6B token, 300d variant. We'll assume you have this file as
- `${HOME}/data/glove.6B.300d.txt`.
-
-We first processed the embeddings from their text format into something that we
-can load a little bit more quickly:
-
- ./text_embeddings_to_binary.py \
- --input ${HOME}/data/glove.6B.300d.txt \
- --output_vocab ${HOME}/data/vocab.txt \
- --output_npy ${HOME}/data/glove.6B.300d.npy
-
-Next, we'll extract all the dependency parse paths connecting our labeled pairs
-from the corpus. This process takes a *looooong* time, but is trivially
-parallelized using map-reduce if you have access to that technology.
-
- ./extract_paths.py \
- --corpus ${HOME}/data/wiki.txt \
- --labeled_pairs ${HOME}/data/labeled-pairs.tsv \
- --output ${HOME}/data/paths.tsv
-
-The file it produces (`paths.tsv`) is a tab-separated file that contains the
-modifier, the head, the label, the encoded path, and the sentence from which the
-path was drawn. (This last is mostly for sanity checking.) A sample row might
-look something like this (where newlines would actually be tab characters):
-
- navy
- captain
- owner_emp_use
- /PROPN/dobj/>::enter/VERB/ROOT/^::follow/VERB/advcl/<::in/ADP/prep/<::footstep/NOUN/pobj/<::of/ADP/prep/<::father/NOUN/pobj/<::bover/PROPN/appos/<::/PROPN/compound/<
- He entered the Royal Navy following in the footsteps of his father Captain John Bover and two of his elder brothers as volunteer aboard HMS Perseus
-
-This file must be sorted as follows:
-
- sort -k1,3 -t$'\t' paths.tsv > sorted.paths.tsv
-
-In particular, rows with the same modifier, head, and label must appear
-contiguously.
-
-We next create a file that contains all the relation labels from our original
-labeled pairs:
-
- awk 'BEGIN {FS="\t"} {print $3}' < ${HOME}/data/labeled-pairs.tsv \
- | sort -u > ${HOME}/data/relations.txt
-
-With these in hand, we're ready to produce the train, validation, and test data:
-
- ./sorted_paths_to_examples.py \
- --input ${HOME}/data/sorted.paths.tsv \
- --vocab ${HOME}/data/vocab.txt \
- --relations ${HOME}/data/relations.txt \
- --splits ${HOME}/data/splits.txt \
- --output_dir ${HOME}/data
-
-Here, `splits.txt` is a file that indicates which "split" (train, test, or
-validation) you want the pair to appear in. It should be a tab-separate file
-which conatins the modifier, head, and the dataset ( `train`, `test`, or `val`)
-into which the pair should be placed; e.g.,:
-
- tooth paste train
- banana seat test
-
-The program will produce a separate file for each dataset split in the directory
-specified by `--output_dir`. Each file is contains `tf.train.Example` protocol
-buffers encoded using the `TFRecord` file format.
-
-## Create Path Embeddings
-
-Now we're ready to train the path embeddings using `learn_path_embeddings.py`:
-
- ./learn_path_embeddings.py \
- --train ${HOME}/data/train.tfrecs.gz \
- --val ${HOME}/data/val.tfrecs.gz \
- --text ${HOME}/data/test.tfrecs.gz \
- --embeddings ${HOME}/data/glove.6B.300d.npy
- --relations ${HOME}/data/relations.txt
- --output ${HOME}/data/path-embeddings \
- --logdir /tmp/learn_path_embeddings
-
-The path embeddings will be placed at the location specified by `--output`.
-
-## Train classifiers
-
-Train classifiers and evaluate on the validation and test data using
-`train_classifiers.py` script. This shell script fragment will iterate through
-each dataset, split, corpus, and model type to train and evaluate classifiers.
-
- LOGDIR=/tmp/learn_classifier
- for DATASET in tratz/fine_grained tratz/coarse_grained ; do
- for SPLIT in random lexical_head lexical_mod lexical_full ; do
- for CORPUS in wiki_gigiawords ; do
- for MODEL in dist dist-nc path integrated integrated-nc ; do
- # Filename for the log that will contain the classifier results.
- LOGFILE=$(echo "${DATASET}.${SPLIT}.${CORPUS}.${MODEL}.log" | sed -e "s,/,.,g")
- python learn_classifier.py \
- --dataset_dir ~/lexnet/datasets \
- --dataset "${DATASET}" \
- --corpus "${SPLIT}/${CORPUS}" \
- --embeddings_base_path ~/lexnet/embeddings \
- --logdir ${LOGDIR} \
- --input "${MODEL}" > "${LOGDIR}/${LOGFILE}"
- done
- done
- done
- done
-
-The log file will contain the final performance (precision, recall, F1) on the
-train, dev, and test sets, and will include a confusion matrix for each.
-
-# Contact
-
-If you have any questions, issues, or suggestions, feel free to contact either
-@vered1986 or @waterson.
-
-If you use this code for any published research, please include the following citation:
-
-Olive Oil Is Made of Olives, Baby Oil Is Made for Babies: Interpreting Noun Compounds Using Paraphrases in a Neural Model.
-Vered Shwartz and Chris Waterson. NAACL 2018. [link](https://arxiv.org/pdf/1803.08073.pdf).
diff --git a/research/lexnet_nc/extract_paths.py b/research/lexnet_nc/extract_paths.py
deleted file mode 100755
index 833eec2c1b8a176b487d4e663a737b9502b49eda..0000000000000000000000000000000000000000
--- a/research/lexnet_nc/extract_paths.py
+++ /dev/null
@@ -1,119 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017, 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import itertools
-import sys
-
-import spacy
-import tensorflow as tf
-
-tf.flags.DEFINE_string('corpus', '', 'Filename of corpus')
-tf.flags.DEFINE_string('labeled_pairs', '', 'Filename of labeled pairs')
-tf.flags.DEFINE_string('output', '', 'Filename of output file')
-FLAGS = tf.flags.FLAGS
-
-
-def get_path(mod_token, head_token):
- """Returns the path between a modifier token and a head token."""
- # Compute the path from the root to each token.
- mod_ancestors = list(reversed(list(mod_token.ancestors)))
- head_ancestors = list(reversed(list(head_token.ancestors)))
-
- # If the paths don't start at the same place (odd!) then there is no path at
- # all.
- if (not mod_ancestors or not head_ancestors
- or mod_ancestors[0] != head_ancestors[0]):
- return None
-
- # Eject elements from the common path until we reach the first differing
- # ancestor.
- ix = 1
- while (ix < len(mod_ancestors) and ix < len(head_ancestors)
- and mod_ancestors[ix] == head_ancestors[ix]):
- ix += 1
-
- # Construct the path. TODO: add "satellites", possibly honor sentence
- # ordering between modifier and head rather than just always traversing from
- # the modifier to the head?
- path = ['/'.join(('', mod_token.pos_, mod_token.dep_, '>'))]
-
- path += ['/'.join((tok.lemma_, tok.pos_, tok.dep_, '>'))
- for tok in reversed(mod_ancestors[ix:])]
-
- root_token = mod_ancestors[ix - 1]
- path += ['/'.join((root_token.lemma_, root_token.pos_, root_token.dep_, '^'))]
-
- path += ['/'.join((tok.lemma_, tok.pos_, tok.dep_, '<'))
- for tok in head_ancestors[ix:]]
-
- path += ['/'.join(('', head_token.pos_, head_token.dep_, '<'))]
-
- return '::'.join(path)
-
-
-def main(_):
- nlp = spacy.load('en_core_web_sm')
-
- # Grab the set of labeled pairs for which we wish to collect paths.
- with tf.gfile.GFile(FLAGS.labeled_pairs) as fh:
- parts = (l.decode('utf-8').split('\t') for l in fh.read().splitlines())
- labeled_pairs = {(mod, head): rel for mod, head, rel in parts}
-
- # Create a mapping from each head to the modifiers that are used with it.
- mods_for_head = {
- head: set(hm[1] for hm in head_mods)
- for head, head_mods in itertools.groupby(
- sorted((head, mod) for (mod, head) in labeled_pairs.iterkeys()),
- lambda (head, mod): head)}
-
- # Collect all the heads that we know about.
- heads = set(mods_for_head.keys())
-
- # For each sentence that contains a (head, modifier) pair that's in our set,
- # emit the dependency path that connects the pair.
- out_fh = sys.stdout if not FLAGS.output else tf.gfile.GFile(FLAGS.output, 'w')
- in_fh = sys.stdin if not FLAGS.corpus else tf.gfile.GFile(FLAGS.corpus)
-
- num_paths = 0
- for line, sen in enumerate(in_fh, start=1):
- if line % 100 == 0:
- print('\rProcessing line %d: %d paths' % (line, num_paths),
- end='', file=sys.stderr)
-
- sen = sen.decode('utf-8').strip()
- doc = nlp(sen)
-
- for head_token in doc:
- head_text = head_token.text.lower()
- if head_text in heads:
- mods = mods_for_head[head_text]
- for mod_token in doc:
- mod_text = mod_token.text.lower()
- if mod_text in mods:
- path = get_path(mod_token, head_token)
- if path:
- label = labeled_pairs[(mod_text, head_text)]
- line = '\t'.join((mod_text, head_text, label, path, sen))
- print(line.encode('utf-8'), file=out_fh)
- num_paths += 1
-
- out_fh.close()
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/lexnet_nc/get_indicative_paths.py b/research/lexnet_nc/get_indicative_paths.py
deleted file mode 100755
index f8b34cca221a07c0b633024b71f082b8f61b3a45..0000000000000000000000000000000000000000
--- a/research/lexnet_nc/get_indicative_paths.py
+++ /dev/null
@@ -1,111 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017, 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Extracts paths that are indicative of each relation."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-
-import tensorflow as tf
-
-from . import path_model
-from . import lexnet_common
-
-tf.flags.DEFINE_string(
- 'dataset_dir', 'datasets',
- 'Dataset base directory')
-
-tf.flags.DEFINE_string(
- 'dataset',
- 'tratz/fine_grained',
- 'Subdirectory containing the corpus directories: '
- 'subdirectory of dataset_dir')
-
-tf.flags.DEFINE_string(
- 'corpus', 'random/wiki',
- 'Subdirectory containing the corpus and split: '
- 'subdirectory of dataset_dir/dataset')
-
-tf.flags.DEFINE_string(
- 'embeddings_base_path', 'embeddings',
- 'Embeddings base directory')
-
-tf.flags.DEFINE_string(
- 'logdir', 'logdir',
- 'Directory of model output files')
-
-tf.flags.DEFINE_integer(
- 'top_k', 20, 'Number of top paths to extract')
-
-tf.flags.DEFINE_float(
- 'threshold', 0.8, 'Threshold above which to consider paths as indicative')
-
-FLAGS = tf.flags.FLAGS
-
-
-def main(_):
- hparams = path_model.PathBasedModel.default_hparams()
-
- # First things first. Load the path data.
- path_embeddings_file = 'path_embeddings/{dataset}/{corpus}'.format(
- dataset=FLAGS.dataset,
- corpus=FLAGS.corpus)
-
- path_dim = (hparams.lemma_dim + hparams.pos_dim +
- hparams.dep_dim + hparams.dir_dim)
-
- path_embeddings, path_to_index = path_model.load_path_embeddings(
- os.path.join(FLAGS.embeddings_base_path, path_embeddings_file),
- path_dim)
-
- # Load and count the classes so we can correctly instantiate the model.
- classes_filename = os.path.join(
- FLAGS.dataset_dir, FLAGS.dataset, 'classes.txt')
-
- with open(classes_filename) as f_in:
- classes = f_in.read().splitlines()
-
- hparams.num_classes = len(classes)
-
- # We need the word embeddings to instantiate the model, too.
- print('Loading word embeddings...')
- lemma_embeddings = lexnet_common.load_word_embeddings(
- FLAGS.embeddings_base_path, hparams.lemma_embeddings_file)
-
- # Instantiate the model.
- with tf.Graph().as_default():
- with tf.variable_scope('lexnet'):
- instance = tf.placeholder(dtype=tf.string)
- model = path_model.PathBasedModel(
- hparams, lemma_embeddings, instance)
-
- with tf.Session() as session:
- model_dir = '{logdir}/results/{dataset}/path/{corpus}'.format(
- logdir=FLAGS.logdir,
- dataset=FLAGS.dataset,
- corpus=FLAGS.corpus)
-
- saver = tf.train.Saver()
- saver.restore(session, os.path.join(model_dir, 'best.ckpt'))
-
- path_model.get_indicative_paths(
- model, session, path_to_index, path_embeddings, classes,
- model_dir, FLAGS.top_k, FLAGS.threshold)
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/lexnet_nc/learn_classifier.py b/research/lexnet_nc/learn_classifier.py
deleted file mode 100755
index ec284029535609ffd2cc0f2f5cddb9b87954aa81..0000000000000000000000000000000000000000
--- a/research/lexnet_nc/learn_classifier.py
+++ /dev/null
@@ -1,223 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017, 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Trains the integrated LexNET classifier."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-
-import lexnet_common
-import lexnet_model
-import path_model
-from sklearn import metrics
-import tensorflow as tf
-
-tf.flags.DEFINE_string(
- 'dataset_dir', 'datasets',
- 'Dataset base directory')
-
-tf.flags.DEFINE_string(
- 'dataset', 'tratz/fine_grained',
- 'Subdirectory containing the corpus directories: '
- 'subdirectory of dataset_dir')
-
-tf.flags.DEFINE_string(
- 'corpus', 'wiki/random',
- 'Subdirectory containing the corpus and split: '
- 'subdirectory of dataset_dir/dataset')
-
-tf.flags.DEFINE_string(
- 'embeddings_base_path', 'embeddings',
- 'Embeddings base directory')
-
-tf.flags.DEFINE_string(
- 'logdir', 'logdir',
- 'Directory of model output files')
-
-tf.flags.DEFINE_string('hparams', '', 'Hyper-parameters')
-
-tf.flags.DEFINE_string(
- 'input', 'integrated',
- 'The model(dist/dist-nc/path/integrated/integrated-nc')
-
-FLAGS = tf.flags.FLAGS
-
-
-def main(_):
- # Pick up any one-off hyper-parameters.
- hparams = lexnet_model.LexNETModel.default_hparams()
- hparams.corpus = FLAGS.corpus
- hparams.input = FLAGS.input
- hparams.path_embeddings_file = 'path_embeddings/%s/%s' % (
- FLAGS.dataset, FLAGS.corpus)
-
- input_dir = hparams.input if hparams.input != 'path' else 'path_classifier'
-
- # Set the number of classes
- classes_filename = os.path.join(
- FLAGS.dataset_dir, FLAGS.dataset, 'classes.txt')
- with open(classes_filename) as f_in:
- classes = f_in.read().splitlines()
-
- hparams.num_classes = len(classes)
- print('Model will predict into %d classes' % hparams.num_classes)
-
- # Get the datasets
- train_set, val_set, test_set = (
- os.path.join(
- FLAGS.dataset_dir, FLAGS.dataset, FLAGS.corpus,
- filename + '.tfrecs.gz')
- for filename in ['train', 'val', 'test'])
-
- print('Running with hyper-parameters: {}'.format(hparams))
-
- # Load the instances
- print('Loading instances...')
- opts = tf.python_io.TFRecordOptions(
- compression_type=tf.python_io.TFRecordCompressionType.GZIP)
- train_instances = list(tf.python_io.tf_record_iterator(train_set, opts))
- val_instances = list(tf.python_io.tf_record_iterator(val_set, opts))
- test_instances = list(tf.python_io.tf_record_iterator(test_set, opts))
-
- # Load the word embeddings
- print('Loading word embeddings...')
- relata_embeddings, path_embeddings, nc_embeddings, path_to_index = (
- None, None, None, None)
- if hparams.input in ['dist', 'dist-nc', 'integrated', 'integrated-nc']:
- relata_embeddings = lexnet_common.load_word_embeddings(
- FLAGS.embeddings_base_path, hparams.relata_embeddings_file)
-
- if hparams.input in ['path', 'integrated', 'integrated-nc']:
- path_embeddings, path_to_index = path_model.load_path_embeddings(
- os.path.join(FLAGS.embeddings_base_path, hparams.path_embeddings_file),
- hparams.path_dim)
-
- if hparams.input in ['dist-nc', 'integrated-nc']:
- nc_embeddings = lexnet_common.load_word_embeddings(
- FLAGS.embeddings_base_path, hparams.nc_embeddings_file)
-
- # Define the graph and the model
- with tf.Graph().as_default():
- model = lexnet_model.LexNETModel(
- hparams, relata_embeddings, path_embeddings,
- nc_embeddings, path_to_index)
-
- # Initialize a session and start training
- session = tf.Session()
- session.run(tf.global_variables_initializer())
-
- # Initalize the path mapping
- if hparams.input in ['path', 'integrated', 'integrated-nc']:
- session.run(tf.tables_initializer())
- session.run(model.initialize_path_op, {
- model.path_initial_value_t: path_embeddings
- })
-
- # Initialize the NC embeddings
- if hparams.input in ['dist-nc', 'integrated-nc']:
- session.run(model.initialize_nc_op, {
- model.nc_initial_value_t: nc_embeddings
- })
-
- # Load the labels
- print('Loading labels...')
- train_labels = model.load_labels(session, train_instances)
- val_labels = model.load_labels(session, val_instances)
- test_labels = model.load_labels(session, test_instances)
-
- save_path = '{logdir}/results/{dataset}/{input}/{corpus}'.format(
- logdir=FLAGS.logdir, dataset=FLAGS.dataset,
- corpus=model.hparams.corpus, input=input_dir)
-
- if not os.path.exists(save_path):
- os.makedirs(save_path)
-
- # Train the model
- print('Training the model...')
- model.fit(session, train_instances, epoch_completed,
- val_instances, val_labels, save_path)
-
- # Print the best performance on the validation set
- print('Best performance on the validation set: F1=%.3f' %
- epoch_completed.best_f1)
-
- # Evaluate on the train and validation sets
- lexnet_common.full_evaluation(model, session, train_instances, train_labels,
- 'Train', classes)
- lexnet_common.full_evaluation(model, session, val_instances, val_labels,
- 'Validation', classes)
- test_predictions = lexnet_common.full_evaluation(
- model, session, test_instances, test_labels, 'Test', classes)
-
- # Write the test predictions to a file
- predictions_file = os.path.join(save_path, 'test_predictions.tsv')
- print('Saving test predictions to %s' % save_path)
- test_pairs = model.load_pairs(session, test_instances)
- lexnet_common.write_predictions(test_pairs, test_labels, test_predictions,
- classes, predictions_file)
-
-
-def epoch_completed(model, session, epoch, epoch_loss,
- val_instances, val_labels, save_path):
- """Runs every time an epoch completes.
-
- Print the performance on the validation set, and update the saved model if
- its performance is better on the previous ones. If the performance dropped,
- tell the training to stop.
-
- Args:
- model: The currently trained path-based model.
- session: The current TensorFlow session.
- epoch: The epoch number.
- epoch_loss: The current epoch loss.
- val_instances: The validation set instances (evaluation between epochs).
- val_labels: The validation set labels (for evaluation between epochs).
- save_path: Where to save the model.
-
- Returns:
- whether the training should stop.
- """
- stop_training = False
-
- # Evaluate on the validation set
- val_pred = model.predict(session, val_instances)
- precision, recall, f1, _ = metrics.precision_recall_fscore_support(
- val_labels, val_pred, average='weighted')
- print(
- 'Epoch: %d/%d, Loss: %f, validation set: P: %.3f, R: %.3f, F1: %.3f\n' % (
- epoch + 1, model.hparams.num_epochs, epoch_loss,
- precision, recall, f1))
-
- # If the F1 is much smaller than the previous one, stop training. Else, if
- # it's bigger, save the model.
- if f1 < epoch_completed.best_f1 - 0.08:
- stop_training = True
-
- if f1 > epoch_completed.best_f1:
- saver = tf.train.Saver()
- checkpoint_filename = os.path.join(save_path, 'best.ckpt')
- print('Saving model in: %s' % checkpoint_filename)
- saver.save(session, checkpoint_filename)
- print('Model saved in file: %s' % checkpoint_filename)
- epoch_completed.best_f1 = f1
-
- return stop_training
-
-epoch_completed.best_f1 = 0
-
-if __name__ == '__main__':
- tf.app.run(main)
diff --git a/research/lexnet_nc/learn_path_embeddings.py b/research/lexnet_nc/learn_path_embeddings.py
deleted file mode 100755
index 480378f4aa010ee27f0387685bac488cedbb2ab9..0000000000000000000000000000000000000000
--- a/research/lexnet_nc/learn_path_embeddings.py
+++ /dev/null
@@ -1,186 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017, 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Trains the LexNET path-based model."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-
-import lexnet_common
-import path_model
-from sklearn import metrics
-import tensorflow as tf
-
-tf.flags.DEFINE_string('train', '', 'training dataset, tfrecs')
-tf.flags.DEFINE_string('val', '', 'validation dataset, tfrecs')
-tf.flags.DEFINE_string('test', '', 'test dataset, tfrecs')
-tf.flags.DEFINE_string('embeddings', '', 'embeddings, npy')
-tf.flags.DEFINE_string('relations', '', 'file containing relation labels')
-tf.flags.DEFINE_string('output_dir', '', 'output directory for path embeddings')
-tf.flags.DEFINE_string('logdir', '', 'directory for model training')
-FLAGS = tf.flags.FLAGS
-
-
-def main(_):
- # Pick up any one-off hyper-parameters.
- hparams = path_model.PathBasedModel.default_hparams()
-
- with open(FLAGS.relations) as fh:
- relations = fh.read().splitlines()
-
- hparams.num_classes = len(relations)
- print('Model will predict into %d classes' % hparams.num_classes)
-
- print('Running with hyper-parameters: {}'.format(hparams))
-
- # Load the instances
- print('Loading instances...')
- opts = tf.python_io.TFRecordOptions(
- compression_type=tf.python_io.TFRecordCompressionType.GZIP)
-
- train_instances = list(tf.python_io.tf_record_iterator(FLAGS.train, opts))
- val_instances = list(tf.python_io.tf_record_iterator(FLAGS.val, opts))
- test_instances = list(tf.python_io.tf_record_iterator(FLAGS.test, opts))
-
- # Load the word embeddings
- print('Loading word embeddings...')
- lemma_embeddings = lexnet_common.load_word_embeddings(FLAGS.embeddings)
-
- # Define the graph and the model
- with tf.Graph().as_default():
- with tf.variable_scope('lexnet'):
- options = tf.python_io.TFRecordOptions(
- compression_type=tf.python_io.TFRecordCompressionType.GZIP)
- reader = tf.TFRecordReader(options=options)
- _, train_instance = reader.read(
- tf.train.string_input_producer([FLAGS.train]))
- shuffled_train_instance = tf.train.shuffle_batch(
- [train_instance],
- batch_size=1,
- num_threads=1,
- capacity=len(train_instances),
- min_after_dequeue=100,
- )[0]
-
- train_model = path_model.PathBasedModel(
- hparams, lemma_embeddings, shuffled_train_instance)
-
- with tf.variable_scope('lexnet', reuse=True):
- val_instance = tf.placeholder(dtype=tf.string)
- val_model = path_model.PathBasedModel(
- hparams, lemma_embeddings, val_instance)
-
- # Initialize a session and start training
- best_model_saver = tf.train.Saver()
- f1_t = tf.placeholder(tf.float32)
- best_f1_t = tf.Variable(0.0, trainable=False, name='best_f1')
- assign_best_f1_op = tf.assign(best_f1_t, f1_t)
-
- supervisor = tf.train.Supervisor(
- logdir=FLAGS.logdir,
- global_step=train_model.global_step)
-
- with supervisor.managed_session() as session:
- # Load the labels
- print('Loading labels...')
- val_labels = train_model.load_labels(session, val_instances)
-
- # Train the model
- print('Training the model...')
-
- while True:
- step = session.run(train_model.global_step)
- epoch = (step + len(train_instances) - 1) // len(train_instances)
- if epoch > hparams.num_epochs:
- break
-
- print('Starting epoch %d (step %d)...' % (1 + epoch, step))
-
- epoch_loss = train_model.run_one_epoch(session, len(train_instances))
-
- best_f1 = session.run(best_f1_t)
- f1 = epoch_completed(val_model, session, epoch, epoch_loss,
- val_instances, val_labels, best_model_saver,
- FLAGS.logdir, best_f1)
-
- if f1 > best_f1:
- session.run(assign_best_f1_op, {f1_t: f1})
-
- if f1 < best_f1 - 0.08:
- tf.logging.info('Stopping training after %d epochs.\n' % epoch)
- break
-
- # Print the best performance on the validation set
- best_f1 = session.run(best_f1_t)
- print('Best performance on the validation set: F1=%.3f' % best_f1)
-
- # Save the path embeddings
- print('Computing the path embeddings...')
- instances = train_instances + val_instances + test_instances
- path_index, path_vectors = path_model.compute_path_embeddings(
- val_model, session, instances)
-
- if not os.path.exists(path_emb_dir):
- os.makedirs(path_emb_dir)
-
- path_model.save_path_embeddings(
- val_model, path_vectors, path_index, FLAGS.output_dir)
-
-
-def epoch_completed(model, session, epoch, epoch_loss,
- val_instances, val_labels, saver, save_path, best_f1):
- """Runs every time an epoch completes.
-
- Print the performance on the validation set, and update the saved model if
- its performance is better on the previous ones. If the performance dropped,
- tell the training to stop.
-
- Args:
- model: The currently trained path-based model.
- session: The current TensorFlow session.
- epoch: The epoch number.
- epoch_loss: The current epoch loss.
- val_instances: The validation set instances (evaluation between epochs).
- val_labels: The validation set labels (for evaluation between epochs).
- saver: tf.Saver object
- save_path: Where to save the model.
- best_f1: the best F1 achieved so far.
-
- Returns:
- The F1 achieved on the training set.
- """
- # Evaluate on the validation set
- val_pred = model.predict(session, val_instances)
- precision, recall, f1, _ = metrics.precision_recall_fscore_support(
- val_labels, val_pred, average='weighted')
- print(
- 'Epoch: %d/%d, Loss: %f, validation set: P: %.3f, R: %.3f, F1: %.3f\n' % (
- epoch + 1, model.hparams.num_epochs, epoch_loss,
- precision, recall, f1))
-
- if f1 > best_f1:
- save_filename = os.path.join(save_path, 'best.ckpt')
- print('Saving model in: %s' % save_filename)
- saver.save(session, save_filename)
- print('Model saved in file: %s' % save_filename)
-
- return f1
-
-
-if __name__ == '__main__':
- tf.app.run(main)
diff --git a/research/lexnet_nc/lexnet_common.py b/research/lexnet_nc/lexnet_common.py
deleted file mode 100644
index a2e8a104d00c1c2f90731f4045c3c8e69e370dbf..0000000000000000000000000000000000000000
--- a/research/lexnet_nc/lexnet_common.py
+++ /dev/null
@@ -1,197 +0,0 @@
-# Copyright 2017, 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Common stuff used with LexNET."""
-# pylint: disable=bad-whitespace
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import numpy as np
-from sklearn import metrics
-import tensorflow as tf
-
-# Part of speech tags used in the paths.
-POSTAGS = [
- 'PAD', 'VERB', 'CONJ', 'NOUN', 'PUNCT',
- 'ADP', 'ADJ', 'DET', 'ADV', 'PART',
- 'NUM', 'X', 'INTJ', 'SYM',
-]
-
-POSTAG_TO_ID = {tag: tid for tid, tag in enumerate(POSTAGS)}
-
-# Dependency labels used in the paths.
-DEPLABELS = [
- 'PAD', 'UNK', 'ROOT', 'abbrev', 'acomp', 'advcl',
- 'advmod', 'agent', 'amod', 'appos', 'attr', 'aux',
- 'auxpass', 'cc', 'ccomp', 'complm', 'conj', 'cop',
- 'csubj', 'csubjpass', 'dep', 'det', 'dobj', 'expl',
- 'infmod', 'iobj', 'mark', 'mwe', 'nc', 'neg',
- 'nn', 'npadvmod', 'nsubj', 'nsubjpass', 'num', 'number',
- 'p', 'parataxis', 'partmod', 'pcomp', 'pobj', 'poss',
- 'preconj', 'predet', 'prep', 'prepc', 'prt', 'ps',
- 'purpcl', 'quantmod', 'rcmod', 'ref', 'rel', 'suffix',
- 'title', 'tmod', 'xcomp', 'xsubj',
-]
-
-DEPLABEL_TO_ID = {label: lid for lid, label in enumerate(DEPLABELS)}
-
-# Direction codes used in the paths.
-DIRS = '_^V<>'
-DIR_TO_ID = {dir: did for did, dir in enumerate(DIRS)}
-
-
-def load_word_embeddings(embedding_filename):
- """Loads pretrained word embeddings from a binary file and returns the matrix.
-
- Adds the , , , and tokens to the beginning of the vocab.
-
- Args:
- embedding_filename: filename of the binary NPY data
-
- Returns:
- The word embeddings matrix
- """
- embeddings = np.load(embedding_filename)
- dim = embeddings.shape[1]
-
- # Four initially random vectors for the special tokens: , , ,
- special_embeddings = np.random.normal(0, 0.1, (4, dim))
- embeddings = np.vstack((special_embeddings, embeddings))
- embeddings = embeddings.astype(np.float32)
-
- return embeddings
-
-
-def full_evaluation(model, session, instances, labels, set_name, classes):
- """Prints a full evaluation on the current set.
-
- Performance (recall, precision and F1), classification report (per
- class performance), and confusion matrix).
-
- Args:
- model: The currently trained path-based model.
- session: The current TensorFlow session.
- instances: The current set instances.
- labels: The current set labels.
- set_name: The current set name (train/validation/test).
- classes: The class label names.
-
- Returns:
- The model's prediction for the given instances.
- """
-
- # Predict the labels
- pred = model.predict(session, instances)
-
- # Print the performance
- precision, recall, f1, _ = metrics.precision_recall_fscore_support(
- labels, pred, average='weighted')
-
- print('%s set: Precision: %.3f, Recall: %.3f, F1: %.3f' % (
- set_name, precision, recall, f1))
-
- # Print a classification report
- print('%s classification report:' % set_name)
- print(metrics.classification_report(labels, pred, target_names=classes))
-
- # Print the confusion matrix
- print('%s confusion matrix:' % set_name)
- cm = metrics.confusion_matrix(labels, pred, labels=range(len(classes)))
- cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis] * 100
- print_cm(cm, labels=classes)
- return pred
-
-
-def print_cm(cm, labels):
- """Pretty print for confusion matrices.
-
- From: https://gist.github.com/zachguo/10296432.
-
- Args:
- cm: The confusion matrix.
- labels: The class names.
- """
- columnwidth = 10
- empty_cell = ' ' * columnwidth
- short_labels = [label[:12].rjust(10, ' ') for label in labels]
-
- # Print header
- header = empty_cell + ' '
- header += ''.join([' %{0}s '.format(columnwidth) % label
- for label in short_labels])
-
- print(header)
-
- # Print rows
- for i, label1 in enumerate(short_labels):
- row = '%{0}s '.format(columnwidth) % label1[:10]
- for j in range(len(short_labels)):
- value = int(cm[i, j]) if not np.isnan(cm[i, j]) else 0
- cell = ' %{0}d '.format(10) % value
- row += cell + ' '
- print(row)
-
-
-def load_all_labels(records):
- """Reads TensorFlow examples from a RecordReader and returns only the labels.
-
- Args:
- records: a record list with TensorFlow examples.
-
- Returns:
- The labels
- """
- curr_features = tf.parse_example(records, {
- 'rel_id': tf.FixedLenFeature([1], dtype=tf.int64),
- })
-
- labels = tf.squeeze(curr_features['rel_id'], [-1])
- return labels
-
-
-def load_all_pairs(records):
- """Reads TensorFlow examples from a RecordReader and returns the word pairs.
-
- Args:
- records: a record list with TensorFlow examples.
-
- Returns:
- The word pairs
- """
- curr_features = tf.parse_example(records, {
- 'pair': tf.FixedLenFeature([1], dtype=tf.string)
- })
-
- word_pairs = curr_features['pair']
- return word_pairs
-
-
-def write_predictions(pairs, labels, predictions, classes, predictions_file):
- """Write the predictions to a file.
-
- Args:
- pairs: the word pairs (list of tuple of two strings).
- labels: the gold-standard labels for these pairs (array of rel ID).
- predictions: the predicted labels for these pairs (array of rel ID).
- classes: a list of relation names.
- predictions_file: where to save the predictions.
- """
- with open(predictions_file, 'w') as f_out:
- for pair, label, pred in zip(pairs, labels, predictions):
- w1, w2 = pair
- f_out.write('\t'.join([w1, w2, classes[label], classes[pred]]) + '\n')
diff --git a/research/lexnet_nc/lexnet_model.py b/research/lexnet_nc/lexnet_model.py
deleted file mode 100644
index b0f16b030b3bb3fee68b91122bcd03226ffcfa4a..0000000000000000000000000000000000000000
--- a/research/lexnet_nc/lexnet_model.py
+++ /dev/null
@@ -1,438 +0,0 @@
-# Copyright 2017, 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""The integrated LexNET model."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import lexnet_common
-import numpy as np
-import tensorflow as tf
-from six.moves import xrange
-
-
-class LexNETModel(object):
- """The LexNET model for classifying relationships between noun compounds."""
-
- @classmethod
- def default_hparams(cls):
- """Returns the default hyper-parameters."""
- return tf.contrib.training.HParams(
- batch_size=10,
- num_classes=37,
- num_epochs=30,
- input_keep_prob=0.9,
- input='integrated', # dist/ dist-nc/ path/ integrated/ integrated-nc
- learn_relata=False,
- corpus='wiki_gigawords',
- random_seed=133, # zero means no random seed
- relata_embeddings_file='glove/glove.6B.300d.bin',
- nc_embeddings_file='nc_glove/vecs.6B.300d.bin',
- path_embeddings_file='path_embeddings/tratz/fine_grained/wiki',
- hidden_layers=1,
- path_dim=60)
-
- def __init__(self, hparams, relata_embeddings, path_embeddings, nc_embeddings,
- path_to_index):
- """Initialize the LexNET classifier.
-
- Args:
- hparams: the hyper-parameters.
- relata_embeddings: word embeddings for the distributional component.
- path_embeddings: embeddings for the paths.
- nc_embeddings: noun compound embeddings.
- path_to_index: a mapping from string path to an index in the path
- embeddings matrix.
- """
- self.hparams = hparams
-
- self.path_embeddings = path_embeddings
- self.relata_embeddings = relata_embeddings
- self.nc_embeddings = nc_embeddings
-
- self.vocab_size, self.relata_dim = 0, 0
- self.path_to_index = None
- self.path_dim = 0
-
- # Set the random seed
- if hparams.random_seed > 0:
- tf.set_random_seed(hparams.random_seed)
-
- # Get the vocabulary size and relata dim
- if self.hparams.input in ['dist', 'dist-nc', 'integrated', 'integrated-nc']:
- self.vocab_size, self.relata_dim = self.relata_embeddings.shape
-
- # Create the mapping from string path to an index in the embeddings matrix
- if self.hparams.input in ['path', 'integrated', 'integrated-nc']:
- self.path_to_index = tf.contrib.lookup.HashTable(
- tf.contrib.lookup.KeyValueTensorInitializer(
- tf.constant(path_to_index.keys()),
- tf.constant(path_to_index.values()),
- key_dtype=tf.string, value_dtype=tf.int32), 0)
-
- self.path_dim = self.path_embeddings.shape[1]
-
- # Create the network
- self.__create_computation_graph__()
-
- def __create_computation_graph__(self):
- """Initialize the model and define the graph."""
- network_input = 0
-
- # Define the network inputs
- # Distributional x and y
- if self.hparams.input in ['dist', 'dist-nc', 'integrated', 'integrated-nc']:
- network_input += 2 * self.relata_dim
- self.relata_lookup = tf.get_variable(
- 'relata_lookup',
- initializer=self.relata_embeddings,
- dtype=tf.float32,
- trainable=self.hparams.learn_relata)
-
- # Path-based
- if self.hparams.input in ['path', 'integrated', 'integrated-nc']:
- network_input += self.path_dim
-
- self.path_initial_value_t = tf.placeholder(tf.float32, None)
-
- self.path_lookup = tf.get_variable(
- name='path_lookup',
- dtype=tf.float32,
- trainable=False,
- shape=self.path_embeddings.shape)
-
- self.initialize_path_op = tf.assign(
- self.path_lookup, self.path_initial_value_t, validate_shape=False)
-
- # Distributional noun compound
- if self.hparams.input in ['dist-nc', 'integrated-nc']:
- network_input += self.relata_dim
-
- self.nc_initial_value_t = tf.placeholder(tf.float32, None)
-
- self.nc_lookup = tf.get_variable(
- name='nc_lookup',
- dtype=tf.float32,
- trainable=False,
- shape=self.nc_embeddings.shape)
-
- self.initialize_nc_op = tf.assign(
- self.nc_lookup, self.nc_initial_value_t, validate_shape=False)
-
- hidden_dim = network_input // 2
-
- # Define the MLP
- if self.hparams.hidden_layers == 0:
- self.weights1 = tf.get_variable(
- 'W1',
- shape=[network_input, self.hparams.num_classes],
- dtype=tf.float32)
- self.bias1 = tf.get_variable(
- 'b1',
- shape=[self.hparams.num_classes],
- dtype=tf.float32)
-
- elif self.hparams.hidden_layers == 1:
-
- self.weights1 = tf.get_variable(
- 'W1',
- shape=[network_input, hidden_dim],
- dtype=tf.float32)
- self.bias1 = tf.get_variable(
- 'b1',
- shape=[hidden_dim],
- dtype=tf.float32)
-
- self.weights2 = tf.get_variable(
- 'W2',
- shape=[hidden_dim, self.hparams.num_classes],
- dtype=tf.float32)
- self.bias2 = tf.get_variable(
- 'b2',
- shape=[self.hparams.num_classes],
- dtype=tf.float32)
-
- else:
- raise ValueError('Only 0 or 1 hidden layers are supported')
-
- # Define the variables
- self.instances = tf.placeholder(dtype=tf.string,
- shape=[self.hparams.batch_size])
-
- (self.x_embedding_id,
- self.y_embedding_id,
- self.nc_embedding_id,
- self.path_embedding_id,
- self.path_counts,
- self.labels) = parse_tensorflow_examples(
- self.instances, self.hparams.batch_size, self.path_to_index)
-
- # Create the MLP
- self.__mlp__()
-
- self.instances_to_load = tf.placeholder(dtype=tf.string, shape=[None])
- self.labels_to_load = lexnet_common.load_all_labels(self.instances_to_load)
- self.pairs_to_load = lexnet_common.load_all_pairs(self.instances_to_load)
-
- def load_labels(self, session, instances):
- """Loads the labels for these instances.
-
- Args:
- session: The current TensorFlow session,
- instances: The instances for which to load the labels.
-
- Returns:
- the labels of these instances.
- """
- return session.run(self.labels_to_load,
- feed_dict={self.instances_to_load: instances})
-
- def load_pairs(self, session, instances):
- """Loads the word pairs for these instances.
-
- Args:
- session: The current TensorFlow session,
- instances: The instances for which to load the labels.
-
- Returns:
- the word pairs of these instances.
- """
- word_pairs = session.run(self.pairs_to_load,
- feed_dict={self.instances_to_load: instances})
- return [pair[0].split('::') for pair in word_pairs]
-
- def __train_single_batch__(self, session, batch_instances):
- """Train a single batch.
-
- Args:
- session: The current TensorFlow session.
- batch_instances: TensorFlow examples containing the training intances
-
- Returns:
- The cost for the current batch.
- """
- cost, _ = session.run([self.cost, self.train_op],
- feed_dict={self.instances: batch_instances})
-
- return cost
-
- def fit(self, session, inputs, on_epoch_completed, val_instances, val_labels,
- save_path):
- """Train the model.
-
- Args:
- session: The current TensorFlow session.
- inputs:
- on_epoch_completed: A method to call after each epoch.
- val_instances: The validation set instances (evaluation between epochs).
- val_labels: The validation set labels (for evaluation between epochs).
- save_path: Where to save the model.
- """
- for epoch in range(self.hparams.num_epochs):
-
- losses = []
- epoch_indices = list(np.random.permutation(len(inputs)))
-
- # If the number of instances doesn't divide by batch_size, enlarge it
- # by duplicating training examples
- mod = len(epoch_indices) % self.hparams.batch_size
- if mod > 0:
- epoch_indices.extend([np.random.randint(0, high=len(inputs))] * mod)
-
- # Define the batches
- n_batches = len(epoch_indices) // self.hparams.batch_size
-
- for minibatch in range(n_batches):
-
- batch_indices = epoch_indices[minibatch * self.hparams.batch_size:(
- minibatch + 1) * self.hparams.batch_size]
- batch_instances = [inputs[i] for i in batch_indices]
-
- loss = self.__train_single_batch__(session, batch_instances)
- losses.append(loss)
-
- epoch_loss = np.nanmean(losses)
-
- if on_epoch_completed:
- should_stop = on_epoch_completed(self, session, epoch, epoch_loss,
- val_instances, val_labels, save_path)
- if should_stop:
- print('Stopping training after %d epochs.' % epoch)
- return
-
- def predict(self, session, inputs):
- """Predict the classification of the test set.
-
- Args:
- session: The current TensorFlow session.
- inputs: the train paths, x, y and/or nc vectors
-
- Returns:
- The test predictions.
- """
- predictions, _ = zip(*self.predict_with_score(session, inputs))
- return np.array(predictions)
-
- def predict_with_score(self, session, inputs):
- """Predict the classification of the test set.
-
- Args:
- session: The current TensorFlow session.
- inputs: the test paths, x, y and/or nc vectors
-
- Returns:
- The test predictions along with their scores.
- """
- test_pred = [0] * len(inputs)
-
- for chunk in xrange(0, len(test_pred), self.hparams.batch_size):
-
- # Initialize the variables with the current batch data
- batch_indices = list(
- range(chunk, min(chunk + self.hparams.batch_size, len(test_pred))))
-
- # If the batch is too small, add a few other examples
- if len(batch_indices) < self.hparams.batch_size:
- batch_indices += [0] * (self.hparams.batch_size-len(batch_indices))
-
- batch_instances = [inputs[i] for i in batch_indices]
-
- predictions, scores = session.run(
- [self.predictions, self.scores],
- feed_dict={self.instances: batch_instances})
-
- for index_in_batch, index_in_dataset in enumerate(batch_indices):
- prediction = predictions[index_in_batch]
- score = scores[index_in_batch][prediction]
- test_pred[index_in_dataset] = (prediction, score)
-
- return test_pred
-
- def __mlp__(self):
- """Performs the MLP operations.
-
- Returns: the prediction object to be computed in a Session
- """
- # Define the operations
-
- # Network input
- vec_inputs = []
-
- # Distributional component
- if self.hparams.input in ['dist', 'dist-nc', 'integrated', 'integrated-nc']:
- for emb_id in [self.x_embedding_id, self.y_embedding_id]:
- vec_inputs.append(tf.nn.embedding_lookup(self.relata_lookup, emb_id))
-
- # Noun compound component
- if self.hparams.input in ['dist-nc', 'integrated-nc']:
- vec = tf.nn.embedding_lookup(self.nc_lookup, self.nc_embedding_id)
- vec_inputs.append(vec)
-
- # Path-based component
- if self.hparams.input in ['path', 'integrated', 'integrated-nc']:
-
- # Get the current paths for each batch instance
- self.path_embeddings = tf.nn.embedding_lookup(self.path_lookup,
- self.path_embedding_id)
-
- # self.path_embeddings is of shape
- # [batch_size, max_path_per_instance, output_dim]
- # We need to multiply it by path counts
- # ([batch_size, max_path_per_instance]).
- # Start by duplicating path_counts along the output_dim axis.
- self.path_freq = tf.tile(tf.expand_dims(self.path_counts, -1),
- [1, 1, self.path_dim])
-
- # Compute the averaged path vector for each instance.
- # First, multiply the path embeddings and frequencies element-wise.
- self.weighted = tf.multiply(self.path_freq, self.path_embeddings)
-
- # Second, take the sum to get a tensor of shape [batch_size, output_dim].
- self.pair_path_embeddings = tf.reduce_sum(self.weighted, 1)
-
- # Finally, divide by the total number of paths.
- # The number of paths for each pair has a shape [batch_size, 1],
- # We duplicate it output_dim times along the second axis.
- self.num_paths = tf.clip_by_value(
- tf.reduce_sum(self.path_counts, 1), 1, np.inf)
- self.num_paths = tf.tile(tf.expand_dims(self.num_paths, -1),
- [1, self.path_dim])
-
- # And finally, divide pair_path_embeddings by num_paths element-wise.
- self.pair_path_embeddings = tf.div(
- self.pair_path_embeddings, self.num_paths)
- vec_inputs.append(self.pair_path_embeddings)
-
- # Concatenate the inputs and feed to the MLP
- self.input_vec = tf.nn.dropout(
- tf.concat(vec_inputs, 1),
- keep_prob=self.hparams.input_keep_prob)
-
- h = tf.matmul(self.input_vec, self.weights1)
- self.output = h
-
- if self.hparams.hidden_layers == 1:
- self.output = tf.matmul(tf.nn.tanh(h), self.weights2)
-
- self.scores = self.output
- self.predictions = tf.argmax(self.scores, axis=1)
-
- # Define the loss function and the optimization algorithm
- self.cross_entropies = tf.nn.sparse_softmax_cross_entropy_with_logits(
- logits=self.scores, labels=self.labels)
- self.cost = tf.reduce_sum(self.cross_entropies, name='cost')
- self.global_step = tf.Variable(0, name='global_step', trainable=False)
- self.optimizer = tf.train.AdamOptimizer()
- self.train_op = self.optimizer.minimize(
- self.cost, global_step=self.global_step)
-
-
-def parse_tensorflow_examples(record, batch_size, path_to_index):
- """Reads TensorFlow examples from a RecordReader.
-
- Args:
- record: a record with TensorFlow examples.
- batch_size: the number of instances in a minibatch
- path_to_index: mapping from string path to index in the embeddings matrix.
-
- Returns:
- The word embeddings IDs, paths and counts
- """
- features = tf.parse_example(
- record, {
- 'x_embedding_id': tf.FixedLenFeature([1], dtype=tf.int64),
- 'y_embedding_id': tf.FixedLenFeature([1], dtype=tf.int64),
- 'nc_embedding_id': tf.FixedLenFeature([1], dtype=tf.int64),
- 'reprs': tf.FixedLenSequenceFeature(
- shape=(), dtype=tf.string, allow_missing=True),
- 'counts': tf.FixedLenSequenceFeature(
- shape=(), dtype=tf.int64, allow_missing=True),
- 'rel_id': tf.FixedLenFeature([1], dtype=tf.int64)
- })
-
- x_embedding_id = tf.squeeze(features['x_embedding_id'], [-1])
- y_embedding_id = tf.squeeze(features['y_embedding_id'], [-1])
- nc_embedding_id = tf.squeeze(features['nc_embedding_id'], [-1])
- labels = tf.squeeze(features['rel_id'], [-1])
- path_counts = tf.to_float(tf.reshape(features['counts'], [batch_size, -1]))
-
- path_embedding_id = None
- if path_to_index:
- path_embedding_id = path_to_index.lookup(features['reprs'])
-
- return (
- x_embedding_id, y_embedding_id, nc_embedding_id,
- path_embedding_id, path_counts, labels)
diff --git a/research/lexnet_nc/path_model.py b/research/lexnet_nc/path_model.py
deleted file mode 100644
index c283841775d673baa8a4bc8c438d65f288a2c555..0000000000000000000000000000000000000000
--- a/research/lexnet_nc/path_model.py
+++ /dev/null
@@ -1,547 +0,0 @@
-# Copyright 2017, 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""LexNET Path-based Model."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-import itertools
-import os
-
-import lexnet_common
-import numpy as np
-import tensorflow as tf
-
-
-class PathBasedModel(object):
- """The LexNET path-based model for classifying semantic relations."""
-
- @classmethod
- def default_hparams(cls):
- """Returns the default hyper-parameters."""
- return tf.contrib.training.HParams(
- max_path_len=8,
- num_classes=37,
- num_epochs=30,
- input_keep_prob=0.9,
- learning_rate=0.001,
- learn_lemmas=False,
- random_seed=133, # zero means no random seed
- lemma_embeddings_file='glove/glove.6B.50d.bin',
- num_pos=len(lexnet_common.POSTAGS),
- num_dep=len(lexnet_common.DEPLABELS),
- num_directions=len(lexnet_common.DIRS),
- lemma_dim=50,
- pos_dim=4,
- dep_dim=5,
- dir_dim=1)
-
- def __init__(self, hparams, lemma_embeddings, instance):
- """Initialize the LexNET classifier.
-
- Args:
- hparams: the hyper-parameters.
- lemma_embeddings: word embeddings for the path-based component.
- instance: string tensor containing the input instance
- """
- self.hparams = hparams
- self.lemma_embeddings = lemma_embeddings
- self.instance = instance
- self.vocab_size, self.lemma_dim = self.lemma_embeddings.shape
-
- # Set the random seed
- if hparams.random_seed > 0:
- tf.set_random_seed(hparams.random_seed)
-
- # Create the network
- self.__create_computation_graph__()
-
- def __create_computation_graph__(self):
- """Initialize the model and define the graph."""
- self.lstm_input_dim = sum([self.hparams.lemma_dim, self.hparams.pos_dim,
- self.hparams.dep_dim, self.hparams.dir_dim])
- self.lstm_output_dim = self.lstm_input_dim
-
- network_input = self.lstm_output_dim
- self.lemma_lookup = tf.get_variable(
- 'lemma_lookup',
- initializer=self.lemma_embeddings,
- dtype=tf.float32,
- trainable=self.hparams.learn_lemmas)
- self.pos_lookup = tf.get_variable(
- 'pos_lookup',
- shape=[self.hparams.num_pos, self.hparams.pos_dim],
- dtype=tf.float32)
- self.dep_lookup = tf.get_variable(
- 'dep_lookup',
- shape=[self.hparams.num_dep, self.hparams.dep_dim],
- dtype=tf.float32)
- self.dir_lookup = tf.get_variable(
- 'dir_lookup',
- shape=[self.hparams.num_directions, self.hparams.dir_dim],
- dtype=tf.float32)
-
- self.weights1 = tf.get_variable(
- 'W1',
- shape=[network_input, self.hparams.num_classes],
- dtype=tf.float32)
- self.bias1 = tf.get_variable(
- 'b1',
- shape=[self.hparams.num_classes],
- dtype=tf.float32)
-
- # Define the variables
- (self.batch_paths,
- self.path_counts,
- self.seq_lengths,
- self.path_strings,
- self.batch_labels) = _parse_tensorflow_example(
- self.instance, self.hparams.max_path_len, self.hparams.input_keep_prob)
-
- # Create the LSTM
- self.__lstm__()
-
- # Create the MLP
- self.__mlp__()
-
- self.instances_to_load = tf.placeholder(dtype=tf.string, shape=[None])
- self.labels_to_load = lexnet_common.load_all_labels(self.instances_to_load)
-
- def load_labels(self, session, batch_instances):
- """Loads the labels of the current instances.
-
- Args:
- session: the current TensorFlow session.
- batch_instances: the dataset instances.
-
- Returns:
- the labels.
- """
- return session.run(self.labels_to_load,
- feed_dict={self.instances_to_load: batch_instances})
-
- def run_one_epoch(self, session, num_steps):
- """Train the model.
-
- Args:
- session: The current TensorFlow session.
- num_steps: The number of steps in each epoch.
-
- Returns:
- The mean loss for the epoch.
-
- Raises:
- ArithmeticError: if the loss becomes non-finite.
- """
- losses = []
-
- for step in range(num_steps):
- curr_loss, _ = session.run([self.cost, self.train_op])
- if not np.isfinite(curr_loss):
- raise ArithmeticError('nan loss at step %d' % step)
-
- losses.append(curr_loss)
-
- return np.mean(losses)
-
- def predict(self, session, inputs):
- """Predict the classification of the test set.
-
- Args:
- session: The current TensorFlow session.
- inputs: the train paths, x, y and/or nc vectors
-
- Returns:
- The test predictions.
- """
- predictions, _ = zip(*self.predict_with_score(session, inputs))
- return np.array(predictions)
-
- def predict_with_score(self, session, inputs):
- """Predict the classification of the test set.
-
- Args:
- session: The current TensorFlow session.
- inputs: the test paths, x, y and/or nc vectors
-
- Returns:
- The test predictions along with their scores.
- """
- test_pred = [0] * len(inputs)
-
- for index, instance in enumerate(inputs):
-
- prediction, scores = session.run(
- [self.predictions, self.scores],
- feed_dict={self.instance: instance})
-
- test_pred[index] = (prediction, scores[prediction])
-
- return test_pred
-
- def __mlp__(self):
- """Performs the MLP operations.
-
- Returns: the prediction object to be computed in a Session
- """
- # Feed the paths to the MLP: path_embeddings is
- # [num_batch_paths, output_dim], and when we multiply it by W
- # ([output_dim, num_classes]), we get a matrix of class distributions:
- # [num_batch_paths, num_classes].
- self.distributions = tf.matmul(self.path_embeddings, self.weights1)
-
- # Now, compute weighted average on the class distributions, using the path
- # frequency as weights.
-
- # First, reshape path_freq to the same shape of distributions
- self.path_freq = tf.tile(tf.expand_dims(self.path_counts, -1),
- [1, self.hparams.num_classes])
-
- # Second, multiply the distributions and frequencies element-wise.
- self.weighted = tf.multiply(self.path_freq, self.distributions)
-
- # Finally, take the average to get a tensor of shape [1, num_classes].
- self.weighted_sum = tf.reduce_sum(self.weighted, 0)
- self.num_paths = tf.clip_by_value(tf.reduce_sum(self.path_counts),
- 1, np.inf)
- self.num_paths = tf.tile(tf.expand_dims(self.num_paths, -1),
- [self.hparams.num_classes])
- self.scores = tf.div(self.weighted_sum, self.num_paths)
- self.predictions = tf.argmax(self.scores)
-
- # Define the loss function and the optimization algorithm
- self.cross_entropies = tf.nn.sparse_softmax_cross_entropy_with_logits(
- logits=self.scores, labels=tf.reduce_mean(self.batch_labels))
- self.cost = tf.reduce_sum(self.cross_entropies, name='cost')
- self.global_step = tf.Variable(0, name='global_step', trainable=False)
- self.optimizer = tf.train.AdamOptimizer()
- self.train_op = self.optimizer.minimize(self.cost,
- global_step=self.global_step)
-
- def __lstm__(self):
- """Defines the LSTM operations.
-
- Returns:
- A matrix of path embeddings.
- """
- lookup_tables = [self.lemma_lookup, self.pos_lookup,
- self.dep_lookup, self.dir_lookup]
-
- # Split the edges to components: list of 4 tensors
- # [num_batch_paths, max_path_len, 1]
- self.edge_components = tf.split(self.batch_paths, 4, axis=2)
-
- # Look up the components embeddings and concatenate them back together
- self.path_matrix = tf.concat([
- tf.squeeze(tf.nn.embedding_lookup(lookup_table, component), 2)
- for lookup_table, component in
- zip(lookup_tables, self.edge_components)
- ], axis=2)
-
- self.sequence_lengths = tf.reshape(self.seq_lengths, [-1])
-
- # Define the LSTM.
- # The input is [num_batch_paths, max_path_len, input_dim].
- lstm_cell = tf.contrib.rnn.BasicLSTMCell(self.lstm_output_dim)
-
- # The output is [num_batch_paths, max_path_len, output_dim].
- self.lstm_outputs, _ = tf.nn.dynamic_rnn(
- lstm_cell, self.path_matrix, dtype=tf.float32,
- sequence_length=self.sequence_lengths)
-
- # Slice the last *relevant* output for each instance ->
- # [num_batch_paths, output_dim]
- self.path_embeddings = _extract_last_relevant(self.lstm_outputs,
- self.sequence_lengths)
-
-
-def _parse_tensorflow_example(record, max_path_len, input_keep_prob):
- """Reads TensorFlow examples from a RecordReader.
-
- Args:
- record: a record with TensorFlow example.
- max_path_len: the maximum path length.
- input_keep_prob: 1 - the word dropout probability
-
- Returns:
- The paths and counts
- """
- features = tf.parse_single_example(record, {
- 'lemmas':
- tf.FixedLenSequenceFeature(
- shape=(), dtype=tf.int64, allow_missing=True),
- 'postags':
- tf.FixedLenSequenceFeature(
- shape=(), dtype=tf.int64, allow_missing=True),
- 'deplabels':
- tf.FixedLenSequenceFeature(
- shape=(), dtype=tf.int64, allow_missing=True),
- 'dirs':
- tf.FixedLenSequenceFeature(
- shape=(), dtype=tf.int64, allow_missing=True),
- 'counts':
- tf.FixedLenSequenceFeature(
- shape=(), dtype=tf.int64, allow_missing=True),
- 'pathlens':
- tf.FixedLenSequenceFeature(
- shape=(), dtype=tf.int64, allow_missing=True),
- 'reprs':
- tf.FixedLenSequenceFeature(
- shape=(), dtype=tf.string, allow_missing=True),
- 'rel_id':
- tf.FixedLenFeature([], dtype=tf.int64)
- })
-
- path_counts = tf.to_float(features['counts'])
- seq_lengths = features['pathlens']
-
- # Concatenate the edge components to create a path tensor:
- # [max_paths_per_ins, max_path_length, 4]
- lemmas = _word_dropout(
- tf.reshape(features['lemmas'], [-1, max_path_len]), input_keep_prob)
-
- paths = tf.stack(
- [lemmas] + [
- tf.reshape(features[f], [-1, max_path_len])
- for f in ('postags', 'deplabels', 'dirs')
- ],
- axis=-1)
-
- path_strings = features['reprs']
-
- # Add an empty path to pairs with no paths
- paths = tf.cond(
- tf.shape(paths)[0] > 0,
- lambda: paths,
- lambda: tf.zeros([1, max_path_len, 4], dtype=tf.int64))
-
- # Paths are left-padded. We reverse them to make them right-padded.
- #paths = tf.reverse(paths, axis=[1])
-
- path_counts = tf.cond(
- tf.shape(path_counts)[0] > 0,
- lambda: path_counts,
- lambda: tf.constant([1.0], dtype=tf.float32))
-
- seq_lengths = tf.cond(
- tf.shape(seq_lengths)[0] > 0,
- lambda: seq_lengths,
- lambda: tf.constant([1], dtype=tf.int64))
-
- # Duplicate the label for each path
- labels = tf.ones_like(path_counts, dtype=tf.int64) * features['rel_id']
-
- return paths, path_counts, seq_lengths, path_strings, labels
-
-
-def _extract_last_relevant(output, seq_lengths):
- """Get the last relevant LSTM output cell for each batch instance.
-
- Args:
- output: the LSTM outputs - a tensor with shape
- [num_paths, output_dim, max_path_len]
- seq_lengths: the sequences length per instance
-
- Returns:
- The last relevant LSTM output cell for each batch instance.
- """
- max_length = int(output.get_shape()[1])
- path_lengths = tf.clip_by_value(seq_lengths - 1, 0, max_length)
- relevant = tf.reduce_sum(tf.multiply(output, tf.expand_dims(
- tf.one_hot(path_lengths, max_length), -1)), 1)
- return relevant
-
-
-def _word_dropout(words, input_keep_prob):
- """Drops words with probability 1 - input_keep_prob.
-
- Args:
- words: a list of lemmas from the paths.
- input_keep_prob: the probability to keep the word.
-
- Returns:
- The revised list where some of the words are ed.
- """
- # Create the mask: (-1) to drop, 1 to keep
- prob = tf.random_uniform(tf.shape(words), 0, 1)
- condition = tf.less(prob, (1 - input_keep_prob))
- mask = tf.where(condition,
- tf.negative(tf.ones_like(words)), tf.ones_like(words))
-
- # We need to keep zeros (), and change other numbers to 1 ()
- # if their mask is -1. First, we multiply the mask and the words.
- # Zeros will stay zeros, and words to drop will become negative.
- # Then, we change negative values to 1.
- masked_words = tf.multiply(mask, words)
- condition = tf.less(masked_words, 0)
- dropped_words = tf.where(condition, tf.ones_like(words), words)
- return dropped_words
-
-
-def compute_path_embeddings(model, session, instances):
- """Compute the path embeddings for all the distinct paths.
-
- Args:
- model: The trained path-based model.
- session: The current TensorFlow session.
- instances: All the train, test and validation instances.
-
- Returns:
- The path to ID index and the path embeddings.
- """
- # Get an index for each distinct path
- path_index = collections.defaultdict(itertools.count(0).next)
- path_vectors = {}
-
- for instance in instances:
- curr_path_embeddings, curr_path_strings = session.run(
- [model.path_embeddings, model.path_strings],
- feed_dict={model.instance: instance})
-
- for i, path in enumerate(curr_path_strings):
- if not path:
- continue
-
- # Set a new/existing index for the path
- index = path_index[path]
-
- # Save its vector
- path_vectors[index] = curr_path_embeddings[i, :]
-
- print('Number of distinct paths: %d' % len(path_index))
- return path_index, path_vectors
-
-
-def save_path_embeddings(model, path_vectors, path_index, embeddings_base_path):
- """Saves the path embeddings.
-
- Args:
- model: The trained path-based model.
- path_vectors: The path embeddings.
- path_index: A map from path to ID.
- embeddings_base_path: The base directory where the embeddings are.
- """
- index_range = range(max(path_index.values()) + 1)
- path_matrix = [path_vectors[i] for i in index_range]
- path_matrix = np.vstack(path_matrix)
-
- # Save the path embeddings
- path_vector_filename = os.path.join(
- embeddings_base_path, '%d_path_vectors' % model.lstm_output_dim)
- with open(path_vector_filename, 'w') as f_out:
- np.save(f_out, path_matrix)
-
- index_to_path = {i: p for p, i in path_index.iteritems()}
- path_vocab = [index_to_path[i] for i in index_range]
-
- # Save the path vocabulary
- path_vocab_filename = os.path.join(
- embeddings_base_path, '%d_path_vocab' % model.lstm_output_dim)
- with open(path_vocab_filename, 'w') as f_out:
- f_out.write('\n'.join(path_vocab))
- f_out.write('\n')
-
- print('Saved path embeddings.')
-
-
-def load_path_embeddings(path_embeddings_dir, path_dim):
- """Loads pretrained path embeddings from a binary file and returns the matrix.
-
- Args:
- path_embeddings_dir: The directory for the path embeddings.
- path_dim: The dimension of the path embeddings, used as prefix to the
- path_vocab and path_vectors files.
-
- Returns:
- The path embeddings matrix and the path_to_index dictionary.
- """
- prefix = path_embeddings_dir + '/%d' % path_dim + '_'
- with open(prefix + 'path_vocab') as f_in:
- vocab = f_in.read().splitlines()
-
- vocab_size = len(vocab)
- embedding_file = prefix + 'path_vectors'
-
- print('Embedding file "%s" has %d paths' % (embedding_file, vocab_size))
-
- with open(embedding_file) as f_in:
- embeddings = np.load(f_in)
-
- path_to_index = {p: i for i, p in enumerate(vocab)}
- return embeddings, path_to_index
-
-
-def get_indicative_paths(model, session, path_index, path_vectors, classes,
- save_dir, k=20, threshold=0.8):
- """Gets the most indicative paths for each class.
-
- Args:
- model: The trained path-based model.
- session: The current TensorFlow session.
- path_index: A map from path to ID.
- path_vectors: The path embeddings.
- classes: The class label names.
- save_dir: Where to save the paths.
- k: The k for top-k paths.
- threshold: The threshold above which to consider paths as indicative.
- """
- # Define graph variables for this operation
- p_path_embedding = tf.placeholder(dtype=tf.float32,
- shape=[1, model.lstm_output_dim])
- p_distributions = tf.nn.softmax(tf.matmul(p_path_embedding, model.weights1))
-
- # Treat each path as a pair instance with a single path, and get the
- # relation distribution for it. Then, take the top paths for each relation.
-
- # This dictionary contains a relation as a key, and the value is a list of
- # tuples of path index and score. A relation r will contain (p, s) if the
- # path p is classified to r with a confidence of s.
- prediction_per_relation = collections.defaultdict(list)
-
- index_to_path = {i: p for p, i in path_index.iteritems()}
-
- # Predict all the paths
- for index in range(len(path_index)):
- curr_path_vector = path_vectors[index]
-
- distribution = session.run(p_distributions,
- feed_dict={
- p_path_embedding: np.reshape(
- curr_path_vector,
- [1, model.lstm_output_dim])})
-
- distribution = distribution[0, :]
- prediction = np.argmax(distribution)
- prediction_per_relation[prediction].append(
- (index, distribution[prediction]))
-
- if index % 10000 == 0:
- print('Classified %d/%d (%3.2f%%) of the paths' % (
- index, len(path_index), 100 * index / len(path_index)))
-
- # Retrieve k-best scoring paths for each relation
- for relation_index, relation in enumerate(classes):
- curr_paths = sorted(prediction_per_relation[relation_index],
- key=lambda item: item[1], reverse=True)
- above_t = [(p, s) for (p, s) in curr_paths if s >= threshold]
- top_k = curr_paths[k+1]
- relation_paths = above_t if len(above_t) > len(top_k) else top_k
-
- paths_filename = os.path.join(save_dir, '%s.paths' % relation)
- with open(paths_filename, 'w') as f_out:
- for index, score in relation_paths:
- print('\t'.join([index_to_path[index], str(score)]), file=f_out)
diff --git a/research/lexnet_nc/sorted_paths_to_examples.py b/research/lexnet_nc/sorted_paths_to_examples.py
deleted file mode 100755
index c21d25d710ae793f6eefd889b98414c923e4fbe6..0000000000000000000000000000000000000000
--- a/research/lexnet_nc/sorted_paths_to_examples.py
+++ /dev/null
@@ -1,202 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017, 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Takes as input a sorted, tab-separated of paths to produce tf.Examples."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-import itertools
-import os
-import sys
-import tensorflow as tf
-
-import lexnet_common
-
-tf.flags.DEFINE_string('input', '', 'tab-separated input data')
-tf.flags.DEFINE_string('vocab', '', 'a text file containing lemma vocabulary')
-tf.flags.DEFINE_string('relations', '', 'a text file containing the relations')
-tf.flags.DEFINE_string('output_dir', '', 'output directory')
-tf.flags.DEFINE_string('splits', '', 'text file enumerating splits')
-tf.flags.DEFINE_string('default_split', '', 'default split for unlabeled pairs')
-tf.flags.DEFINE_string('compression', 'GZIP', 'compression for output records')
-tf.flags.DEFINE_integer('max_paths', 100, 'maximum number of paths per record')
-tf.flags.DEFINE_integer('max_pathlen', 8, 'maximum path length')
-FLAGS = tf.flags.FLAGS
-
-
-def _int64_features(value):
- return tf.train.Feature(int64_list=tf.train.Int64List(value=value))
-
-
-def _bytes_features(value):
- value = [v.encode('utf-8') if isinstance(v, unicode) else v for v in value]
- return tf.train.Feature(bytes_list=tf.train.BytesList(value=value))
-
-
-class CreateExampleFn(object):
-
- def __init__(self):
- # Read the vocabulary. N.B. that 0 = PAD, 1 = UNK, 2 = , 3 = , hence
- # the enumeration starting at 4.
- with tf.gfile.GFile(FLAGS.vocab) as fh:
- self.vocab = {w: ix for ix, w in enumerate(fh.read().splitlines(), start=4)}
-
- self.vocab.update({'': 0, '': 1, '': 2, '': 3})
-
- # Read the relations.
- with tf.gfile.GFile(FLAGS.relations) as fh:
- self.relations = {r: ix for ix, r in enumerate(fh.read().splitlines())}
-
- # Some hackery to map from SpaCy postags to Google's.
- lexnet_common.POSTAG_TO_ID['PROPN'] = lexnet_common.POSTAG_TO_ID['NOUN']
- lexnet_common.POSTAG_TO_ID['PRON'] = lexnet_common.POSTAG_TO_ID['NOUN']
- lexnet_common.POSTAG_TO_ID['CCONJ'] = lexnet_common.POSTAG_TO_ID['CONJ']
- #lexnet_common.DEPLABEL_TO_ID['relcl'] = lexnet_common.DEPLABEL_TO_ID['rel']
- #lexnet_common.DEPLABEL_TO_ID['compound'] = lexnet_common.DEPLABEL_TO_ID['xcomp']
- #lexnet_common.DEPLABEL_TO_ID['oprd'] = lexnet_common.DEPLABEL_TO_ID['UNK']
-
- def __call__(self, mod, head, rel, raw_paths):
- # Drop any really long paths.
- paths = []
- counts = []
- for raw, count in raw_paths.most_common(FLAGS.max_paths):
- path = raw.split('::')
- if len(path) <= FLAGS.max_pathlen:
- paths.append(path)
- counts.append(count)
-
- if not paths:
- return None
-
- # Compute the true length.
- pathlens = [len(path) for path in paths]
-
- # Pad each path out to max_pathlen so the LSTM can eat it.
- paths = (
- itertools.islice(
- itertools.chain(path, itertools.repeat('/PAD/PAD/_')),
- FLAGS.max_pathlen)
- for path in paths)
-
- # Split the lemma, POS, dependency label, and direction each into a
- # separate feature.
- lemmas, postags, deplabels, dirs = zip(
- *(part.split('/') for part in itertools.chain(*paths)))
-
- lemmas = [self.vocab.get(lemma, 1) for lemma in lemmas]
- postags = [lexnet_common.POSTAG_TO_ID[pos] for pos in postags]
- deplabels = [lexnet_common.DEPLABEL_TO_ID.get(dep, 1) for dep in deplabels]
- dirs = [lexnet_common.DIR_TO_ID.get(d, 0) for d in dirs]
-
- return tf.train.Example(features=tf.train.Features(feature={
- 'pair': _bytes_features(['::'.join((mod, head))]),
- 'rel': _bytes_features([rel]),
- 'rel_id': _int64_features([self.relations[rel]]),
- 'reprs': _bytes_features(raw_paths),
- 'pathlens': _int64_features(pathlens),
- 'counts': _int64_features(counts),
- 'lemmas': _int64_features(lemmas),
- 'dirs': _int64_features(dirs),
- 'deplabels': _int64_features(deplabels),
- 'postags': _int64_features(postags),
- 'x_embedding_id': _int64_features([self.vocab[mod]]),
- 'y_embedding_id': _int64_features([self.vocab[head]]),
- }))
-
-
-def main(_):
- # Read the splits file, if there is one.
- assignments = {}
- if FLAGS.splits:
- with tf.gfile.GFile(FLAGS.splits) as fh:
- parts = (line.split('\t') for line in fh.read().splitlines())
- assignments = {(mod, head): split for mod, head, split in parts}
-
- splits = set(assignments.itervalues())
- if FLAGS.default_split:
- default_split = FLAGS.default_split
- splits.add(FLAGS.default_split)
- elif splits:
- default_split = iter(splits).next()
- else:
- print('Please specify --splits, --default_split, or both', file=sys.stderr)
- return 1
-
- last_mod, last_head, last_label = None, None, None
- raw_paths = collections.Counter()
-
- # Keep track of pairs we've seen to ensure that we don't get unsorted data.
- seen_labeled_pairs = set()
-
- # Set up output compression
- compression_type = getattr(
- tf.python_io.TFRecordCompressionType, FLAGS.compression)
- options = tf.python_io.TFRecordOptions(compression_type=compression_type)
-
- writers = {
- split: tf.python_io.TFRecordWriter(
- os.path.join(FLAGS.output_dir, '%s.tfrecs.gz' % split),
- options=options)
- for split in splits}
-
- create_example = CreateExampleFn()
-
- in_fh = sys.stdin if not FLAGS.input else tf.gfile.GFile(FLAGS.input)
- for lineno, line in enumerate(in_fh, start=1):
- if lineno % 100 == 0:
- print('\rProcessed %d lines...' % lineno, end='', file=sys.stderr)
-
- parts = line.decode('utf-8').strip().split('\t')
- if len(parts) != 5:
- print('Skipping line %d: %d columns (expected 5)' % (
- lineno, len(parts)), file=sys.stderr)
-
- continue
-
- mod, head, label, raw_path, source = parts
- if mod == last_mod and head == last_head and label == last_label:
- raw_paths.update([raw_path])
- continue
-
- if last_mod and last_head and last_label and raw_paths:
- if (last_mod, last_head, last_label) in seen_labeled_pairs:
- print('It looks like the input data is not sorted; ignoring extra '
- 'record for (%s::%s, %s) at line %d' % (
- last_mod, last_head, last_label, lineno))
- else:
- ex = create_example(last_mod, last_head, last_label, raw_paths)
- if ex:
- split = assignments.get((last_mod, last_head), default_split)
- writers[split].write(ex.SerializeToString())
-
- seen_labeled_pairs.add((last_mod, last_head, last_label))
-
- last_mod, last_head, last_label = mod, head, label
- raw_paths = collections.Counter()
-
- if last_mod and last_head and last_label and raw_paths:
- ex = create_example(last_mod, last_head, last_label, raw_paths)
- if ex:
- split = assignments.get((last_mod, last_head), default_split)
- writers[split].write(ex.SerializeToString())
-
- for writer in writers.itervalues():
- writer.close()
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/lexnet_nc/text_embeddings_to_binary.py b/research/lexnet_nc/text_embeddings_to_binary.py
deleted file mode 100755
index 8226a7654e6da733ba1e8c46810a8ec8afd7a2c0..0000000000000000000000000000000000000000
--- a/research/lexnet_nc/text_embeddings_to_binary.py
+++ /dev/null
@@ -1,48 +0,0 @@
-#!/usr/bin/env python
-# Copyright 2017, 2018 Google, Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Converts a text embedding file into a binary format for quicker loading."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import tensorflow as tf
-
-tf.flags.DEFINE_string('input', '', 'text file containing embeddings')
-tf.flags.DEFINE_string('output_vocab', '', 'output file for vocabulary')
-tf.flags.DEFINE_string('output_npy', '', 'output file for binary')
-FLAGS = tf.flags.FLAGS
-
-def main(_):
- vecs = []
- vocab = []
- with tf.gfile.GFile(FLAGS.input) as fh:
- for line in fh:
- parts = line.strip().split()
- vocab.append(parts[0])
- vecs.append([float(x) for x in parts[1:]])
-
- with tf.gfile.GFile(FLAGS.output_vocab, 'w') as fh:
- fh.write('\n'.join(vocab))
- fh.write('\n')
-
- vecs = np.array(vecs, dtype=np.float32)
- np.save(FLAGS.output_npy, vecs, allow_pickle=False)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/lm_1b/BUILD b/research/lm_1b/BUILD
deleted file mode 100644
index ca5bc1f6ce4347a3b5f18d1bb59284aa9d07a567..0000000000000000000000000000000000000000
--- a/research/lm_1b/BUILD
+++ /dev/null
@@ -1,27 +0,0 @@
-package(default_visibility = [":internal"])
-
-licenses(["notice"]) # Apache 2.0
-
-exports_files(["LICENSE"])
-
-package_group(
- name = "internal",
- packages = [
- "//lm_1b/...",
- ],
-)
-
-py_library(
- name = "data_utils",
- srcs = ["data_utils.py"],
-)
-
-py_binary(
- name = "lm_1b_eval",
- srcs = [
- "lm_1b_eval.py",
- ],
- deps = [
- ":data_utils",
- ],
-)
diff --git a/research/lm_1b/README.md b/research/lm_1b/README.md
deleted file mode 100644
index f48afbfe23aff6681e641296e73b2c6b0e5a9b48..0000000000000000000000000000000000000000
--- a/research/lm_1b/README.md
+++ /dev/null
@@ -1,198 +0,0 @@
-
-
-
-
-Language Model on One Billion Word Benchmark
-
-Authors:
-
-Oriol Vinyals (vinyals@google.com, github: OriolVinyals),
-Xin Pan
-
-Paper Authors:
-
-Rafal Jozefowicz, Oriol Vinyals, Mike Schuster, Noam Shazeer, Yonghui Wu
-
-TL;DR
-
-This is a pretrained model on One Billion Word Benchmark.
-If you use this model in your publication, please cite the original paper:
-
-@article{jozefowicz2016exploring,
- title={Exploring the Limits of Language Modeling},
- author={Jozefowicz, Rafal and Vinyals, Oriol and Schuster, Mike
- and Shazeer, Noam and Wu, Yonghui},
- journal={arXiv preprint arXiv:1602.02410},
- year={2016}
-}
-
-Introduction
-
-In this release, we open source a model trained on the One Billion Word
-Benchmark (http://arxiv.org/abs/1312.3005), a large language corpus in English
-which was released in 2013. This dataset contains about one billion words, and
-has a vocabulary size of about 800K words. It contains mostly news data. Since
-sentences in the training set are shuffled, models can ignore the context and
-focus on sentence level language modeling.
-
-In the original release and subsequent work, people have used the same test set
-to train models on this dataset as a standard benchmark for language modeling.
-Recently, we wrote an article (http://arxiv.org/abs/1602.02410) describing a
-model hybrid between character CNN, a large and deep LSTM, and a specific
-Softmax architecture which allowed us to train the best model on this dataset
-thus far, almost halving the best perplexity previously obtained by others.
-
-Code Release
-
-The open-sourced components include:
-
-* TensorFlow GraphDef proto buffer text file.
-* TensorFlow pre-trained checkpoint shards.
-* Code used to evaluate the pre-trained model.
-* Vocabulary file.
-* Test set from LM-1B evaluation.
-
-The code supports 4 evaluation modes:
-
-* Given provided dataset, calculate the model's perplexity.
-* Given a prefix sentence, predict the next words.
-* Dump the softmax embedding, character-level CNN word embeddings.
-* Give a sentence, dump the embedding from the LSTM state.
-
-Results
-
-Model | Test Perplexity | Number of Params [billions]
-------|-----------------|----------------------------
-Sigmoid-RNN-2048 [Blackout] | 68.3 | 4.1
-Interpolated KN 5-gram, 1.1B n-grams [chelba2013one] | 67.6 | 1.76
-Sparse Non-Negative Matrix LM [shazeer2015sparse] | 52.9 | 33
-RNN-1024 + MaxEnt 9-gram features [chelba2013one] | 51.3 | 20
-LSTM-512-512 | 54.1 | 0.82
-LSTM-1024-512 | 48.2 | 0.82
-LSTM-2048-512 | 43.7 | 0.83
-LSTM-8192-2048 (No Dropout) | 37.9 | 3.3
-LSTM-8192-2048 (50\% Dropout) | 32.2 | 3.3
-2-Layer LSTM-8192-1024 (BIG LSTM) | 30.6 | 1.8
-(THIS RELEASE) BIG LSTM+CNN Inputs | 30.0 | 1.04
-
-How To Run
-
-Prerequisites:
-
-* Install TensorFlow.
-* Install Bazel.
-* Download the data files:
- * Model GraphDef file:
- [link](http://download.tensorflow.org/models/LM_LSTM_CNN/graph-2016-09-10.pbtxt)
- * Model Checkpoint sharded file:
- [1](http://download.tensorflow.org/models/LM_LSTM_CNN/all_shards-2016-09-10/ckpt-base)
- [2](http://download.tensorflow.org/models/LM_LSTM_CNN/all_shards-2016-09-10/ckpt-char-embedding)
- [3](http://download.tensorflow.org/models/LM_LSTM_CNN/all_shards-2016-09-10/ckpt-lstm)
- [4](http://download.tensorflow.org/models/LM_LSTM_CNN/all_shards-2016-09-10/ckpt-softmax0)
- [5](http://download.tensorflow.org/models/LM_LSTM_CNN/all_shards-2016-09-10/ckpt-softmax1)
- [6](http://download.tensorflow.org/models/LM_LSTM_CNN/all_shards-2016-09-10/ckpt-softmax2)
- [7](http://download.tensorflow.org/models/LM_LSTM_CNN/all_shards-2016-09-10/ckpt-softmax3)
- [8](http://download.tensorflow.org/models/LM_LSTM_CNN/all_shards-2016-09-10/ckpt-softmax4)
- [9](http://download.tensorflow.org/models/LM_LSTM_CNN/all_shards-2016-09-10/ckpt-softmax5)
- [10](http://download.tensorflow.org/models/LM_LSTM_CNN/all_shards-2016-09-10/ckpt-softmax6)
- [11](http://download.tensorflow.org/models/LM_LSTM_CNN/all_shards-2016-09-10/ckpt-softmax7)
- [12](http://download.tensorflow.org/models/LM_LSTM_CNN/all_shards-2016-09-10/ckpt-softmax8)
- * Vocabulary file:
- [link](http://download.tensorflow.org/models/LM_LSTM_CNN/vocab-2016-09-10.txt)
- * test dataset: link
- [link](http://download.tensorflow.org/models/LM_LSTM_CNN/test/news.en.heldout-00000-of-00050)
-* It is recommended to run on a modern desktop instead of a laptop.
-
-```shell
-# 1. Clone the code to your workspace.
-# 2. Download the data to your workspace.
-# 3. Create an empty WORKSPACE file in your workspace.
-# 4. Create an empty output directory in your workspace.
-# Example directory structure below:
-$ ls -R
-.:
-data lm_1b output WORKSPACE
-
-./data:
-ckpt-base ckpt-lstm ckpt-softmax1 ckpt-softmax3 ckpt-softmax5
-ckpt-softmax7 graph-2016-09-10.pbtxt vocab-2016-09-10.txt
-ckpt-char-embedding ckpt-softmax0 ckpt-softmax2 ckpt-softmax4 ckpt-softmax6
-ckpt-softmax8 news.en.heldout-00000-of-00050
-
-./lm_1b:
-BUILD data_utils.py lm_1b_eval.py README.md
-
-./output:
-
-# Build the codes.
-$ bazel build -c opt lm_1b/...
-# Run sample mode:
-$ bazel-bin/lm_1b/lm_1b_eval --mode sample \
- --prefix "I love that I" \
- --pbtxt data/graph-2016-09-10.pbtxt \
- --vocab_file data/vocab-2016-09-10.txt \
- --ckpt 'data/ckpt-*'
-...(omitted some TensorFlow output)
-I love
-I love that
-I love that I
-I love that I find
-I love that I find that
-I love that I find that amazing
-...(omitted)
-
-# Run eval mode:
-$ bazel-bin/lm_1b/lm_1b_eval --mode eval \
- --pbtxt data/graph-2016-09-10.pbtxt \
- --vocab_file data/vocab-2016-09-10.txt \
- --input_data data/news.en.heldout-00000-of-00050 \
- --ckpt 'data/ckpt-*'
-...(omitted some TensorFlow output)
-Loaded step 14108582.
-# perplexity is high initially because words without context are harder to
-# predict.
-Eval Step: 0, Average Perplexity: 2045.512297.
-Eval Step: 1, Average Perplexity: 229.478699.
-Eval Step: 2, Average Perplexity: 208.116787.
-Eval Step: 3, Average Perplexity: 338.870601.
-Eval Step: 4, Average Perplexity: 228.950107.
-Eval Step: 5, Average Perplexity: 197.685857.
-Eval Step: 6, Average Perplexity: 156.287063.
-Eval Step: 7, Average Perplexity: 124.866189.
-Eval Step: 8, Average Perplexity: 147.204975.
-Eval Step: 9, Average Perplexity: 90.124864.
-Eval Step: 10, Average Perplexity: 59.897914.
-Eval Step: 11, Average Perplexity: 42.591137.
-...(omitted)
-Eval Step: 4529, Average Perplexity: 29.243668.
-Eval Step: 4530, Average Perplexity: 29.302362.
-Eval Step: 4531, Average Perplexity: 29.285674.
-...(omitted. At convergence, it should be around 30.)
-
-# Run dump_emb mode:
-$ bazel-bin/lm_1b/lm_1b_eval --mode dump_emb \
- --pbtxt data/graph-2016-09-10.pbtxt \
- --vocab_file data/vocab-2016-09-10.txt \
- --ckpt 'data/ckpt-*' \
- --save_dir output
-...(omitted some TensorFlow output)
-Finished softmax weights
-Finished word embedding 0/793471
-Finished word embedding 1/793471
-Finished word embedding 2/793471
-...(omitted)
-$ ls output/
-embeddings_softmax.npy ...
-
-# Run dump_lstm_emb mode:
-$ bazel-bin/lm_1b/lm_1b_eval --mode dump_lstm_emb \
- --pbtxt data/graph-2016-09-10.pbtxt \
- --vocab_file data/vocab-2016-09-10.txt \
- --ckpt 'data/ckpt-*' \
- --sentence "I love who I am ." \
- --save_dir output
-$ ls output/
-lstm_emb_step_0.npy lstm_emb_step_2.npy lstm_emb_step_4.npy
-lstm_emb_step_6.npy lstm_emb_step_1.npy lstm_emb_step_3.npy
-lstm_emb_step_5.npy
-```
diff --git a/research/lm_1b/data_utils.py b/research/lm_1b/data_utils.py
deleted file mode 100644
index ad8d3391ef6db07c1d6c234450a6d23a8e19a178..0000000000000000000000000000000000000000
--- a/research/lm_1b/data_utils.py
+++ /dev/null
@@ -1,279 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""A library for loading 1B word benchmark dataset."""
-
-import random
-
-import numpy as np
-import tensorflow as tf
-
-
-class Vocabulary(object):
- """Class that holds a vocabulary for the dataset."""
-
- def __init__(self, filename):
- """Initialize vocabulary.
-
- Args:
- filename: Vocabulary file name.
- """
-
- self._id_to_word = []
- self._word_to_id = {}
- self._unk = -1
- self._bos = -1
- self._eos = -1
-
- with tf.gfile.Open(filename) as f:
- idx = 0
- for line in f:
- word_name = line.strip()
- if word_name == '':
- self._bos = idx
- elif word_name == '':
- self._eos = idx
- elif word_name == '':
- self._unk = idx
- if word_name == '!!!MAXTERMID':
- continue
-
- self._id_to_word.append(word_name)
- self._word_to_id[word_name] = idx
- idx += 1
-
- @property
- def bos(self):
- return self._bos
-
- @property
- def eos(self):
- return self._eos
-
- @property
- def unk(self):
- return self._unk
-
- @property
- def size(self):
- return len(self._id_to_word)
-
- def word_to_id(self, word):
- if word in self._word_to_id:
- return self._word_to_id[word]
- return self.unk
-
- def id_to_word(self, cur_id):
- if cur_id < self.size:
- return self._id_to_word[cur_id]
- return 'ERROR'
-
- def decode(self, cur_ids):
- """Convert a list of ids to a sentence, with space inserted."""
- return ' '.join([self.id_to_word(cur_id) for cur_id in cur_ids])
-
- def encode(self, sentence):
- """Convert a sentence to a list of ids, with special tokens added."""
- word_ids = [self.word_to_id(cur_word) for cur_word in sentence.split()]
- return np.array([self.bos] + word_ids + [self.eos], dtype=np.int32)
-
-
-class CharsVocabulary(Vocabulary):
- """Vocabulary containing character-level information."""
-
- def __init__(self, filename, max_word_length):
- super(CharsVocabulary, self).__init__(filename)
- self._max_word_length = max_word_length
- chars_set = set()
-
- for word in self._id_to_word:
- chars_set |= set(word)
-
- free_ids = []
- for i in range(256):
- if chr(i) in chars_set:
- continue
- free_ids.append(chr(i))
-
- if len(free_ids) < 5:
- raise ValueError('Not enough free char ids: %d' % len(free_ids))
-
- self.bos_char = free_ids[0] #
- self.eos_char = free_ids[1] #
- self.bow_char = free_ids[2] #
- self.eow_char = free_ids[3] #
- self.pad_char = free_ids[4] #
-
- chars_set |= {self.bos_char, self.eos_char, self.bow_char, self.eow_char,
- self.pad_char}
-
- self._char_set = chars_set
- num_words = len(self._id_to_word)
-
- self._word_char_ids = np.zeros([num_words, max_word_length], dtype=np.int32)
-
- self.bos_chars = self._convert_word_to_char_ids(self.bos_char)
- self.eos_chars = self._convert_word_to_char_ids(self.eos_char)
-
- for i, word in enumerate(self._id_to_word):
- self._word_char_ids[i] = self._convert_word_to_char_ids(word)
-
- @property
- def word_char_ids(self):
- return self._word_char_ids
-
- @property
- def max_word_length(self):
- return self._max_word_length
-
- def _convert_word_to_char_ids(self, word):
- code = np.zeros([self.max_word_length], dtype=np.int32)
- code[:] = ord(self.pad_char)
-
- if len(word) > self.max_word_length - 2:
- word = word[:self.max_word_length-2]
- cur_word = self.bow_char + word + self.eow_char
- for j in range(len(cur_word)):
- code[j] = ord(cur_word[j])
- return code
-
- def word_to_char_ids(self, word):
- if word in self._word_to_id:
- return self._word_char_ids[self._word_to_id[word]]
- else:
- return self._convert_word_to_char_ids(word)
-
- def encode_chars(self, sentence):
- chars_ids = [self.word_to_char_ids(cur_word)
- for cur_word in sentence.split()]
- return np.vstack([self.bos_chars] + chars_ids + [self.eos_chars])
-
-
-def get_batch(generator, batch_size, num_steps, max_word_length, pad=False):
- """Read batches of input."""
- cur_stream = [None] * batch_size
-
- inputs = np.zeros([batch_size, num_steps], np.int32)
- char_inputs = np.zeros([batch_size, num_steps, max_word_length], np.int32)
- global_word_ids = np.zeros([batch_size, num_steps], np.int32)
- targets = np.zeros([batch_size, num_steps], np.int32)
- weights = np.ones([batch_size, num_steps], np.float32)
-
- no_more_data = False
- while True:
- inputs[:] = 0
- char_inputs[:] = 0
- global_word_ids[:] = 0
- targets[:] = 0
- weights[:] = 0.0
-
- for i in range(batch_size):
- cur_pos = 0
-
- while cur_pos < num_steps:
- if cur_stream[i] is None or len(cur_stream[i][0]) <= 1:
- try:
- cur_stream[i] = list(generator.next())
- except StopIteration:
- # No more data, exhaust current streams and quit
- no_more_data = True
- break
-
- how_many = min(len(cur_stream[i][0]) - 1, num_steps - cur_pos)
- next_pos = cur_pos + how_many
-
- inputs[i, cur_pos:next_pos] = cur_stream[i][0][:how_many]
- char_inputs[i, cur_pos:next_pos] = cur_stream[i][1][:how_many]
- global_word_ids[i, cur_pos:next_pos] = cur_stream[i][2][:how_many]
- targets[i, cur_pos:next_pos] = cur_stream[i][0][1:how_many+1]
- weights[i, cur_pos:next_pos] = 1.0
-
- cur_pos = next_pos
- cur_stream[i][0] = cur_stream[i][0][how_many:]
- cur_stream[i][1] = cur_stream[i][1][how_many:]
- cur_stream[i][2] = cur_stream[i][2][how_many:]
-
- if pad:
- break
-
- if no_more_data and np.sum(weights) == 0:
- # There is no more data and this is an empty batch. Done!
- break
- yield inputs, char_inputs, global_word_ids, targets, weights
-
-
-class LM1BDataset(object):
- """Utility class for 1B word benchmark dataset.
-
- The current implementation reads the data from the tokenized text files.
- """
-
- def __init__(self, filepattern, vocab):
- """Initialize LM1BDataset reader.
-
- Args:
- filepattern: Dataset file pattern.
- vocab: Vocabulary.
- """
- self._vocab = vocab
- self._all_shards = tf.gfile.Glob(filepattern)
- tf.logging.info('Found %d shards at %s', len(self._all_shards), filepattern)
-
- def _load_random_shard(self):
- """Randomly select a file and read it."""
- return self._load_shard(random.choice(self._all_shards))
-
- def _load_shard(self, shard_name):
- """Read one file and convert to ids.
-
- Args:
- shard_name: file path.
-
- Returns:
- list of (id, char_id, global_word_id) tuples.
- """
- tf.logging.info('Loading data from: %s', shard_name)
- with tf.gfile.Open(shard_name) as f:
- sentences = f.readlines()
- chars_ids = [self.vocab.encode_chars(sentence) for sentence in sentences]
- ids = [self.vocab.encode(sentence) for sentence in sentences]
-
- global_word_ids = []
- current_idx = 0
- for word_ids in ids:
- current_size = len(word_ids) - 1 # without symbol
- cur_ids = np.arange(current_idx, current_idx + current_size)
- global_word_ids.append(cur_ids)
- current_idx += current_size
-
- tf.logging.info('Loaded %d words.', current_idx)
- tf.logging.info('Finished loading')
- return zip(ids, chars_ids, global_word_ids)
-
- def _get_sentence(self, forever=True):
- while True:
- ids = self._load_random_shard()
- for current_ids in ids:
- yield current_ids
- if not forever:
- break
-
- def get_batch(self, batch_size, num_steps, pad=False, forever=True):
- return get_batch(self._get_sentence(forever), batch_size, num_steps,
- self.vocab.max_word_length, pad=pad)
-
- @property
- def vocab(self):
- return self._vocab
diff --git a/research/lm_1b/lm_1b_eval.py b/research/lm_1b/lm_1b_eval.py
deleted file mode 100644
index ce8634757558c135ba137a9b9e09a733977adc3a..0000000000000000000000000000000000000000
--- a/research/lm_1b/lm_1b_eval.py
+++ /dev/null
@@ -1,308 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Eval pre-trained 1 billion word language model.
-"""
-import os
-import sys
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-from google.protobuf import text_format
-import data_utils
-
-FLAGS = tf.flags.FLAGS
-# General flags.
-tf.flags.DEFINE_string('mode', 'eval',
- 'One of [sample, eval, dump_emb, dump_lstm_emb]. '
- '"sample" mode samples future word predictions, using '
- 'FLAGS.prefix as prefix (prefix could be left empty). '
- '"eval" mode calculates perplexity of the '
- 'FLAGS.input_data. '
- '"dump_emb" mode dumps word and softmax embeddings to '
- 'FLAGS.save_dir. embeddings are dumped in the same '
- 'order as words in vocabulary. All words in vocabulary '
- 'are dumped.'
- 'dump_lstm_emb dumps lstm embeddings of FLAGS.sentence '
- 'to FLAGS.save_dir.')
-tf.flags.DEFINE_string('pbtxt', '',
- 'GraphDef proto text file used to construct model '
- 'structure.')
-tf.flags.DEFINE_string('ckpt', '',
- 'Checkpoint directory used to fill model values.')
-tf.flags.DEFINE_string('vocab_file', '', 'Vocabulary file.')
-tf.flags.DEFINE_string('save_dir', '',
- 'Used for "dump_emb" mode to save word embeddings.')
-# sample mode flags.
-tf.flags.DEFINE_string('prefix', '',
- 'Used for "sample" mode to predict next words.')
-tf.flags.DEFINE_integer('max_sample_words', 100,
- 'Sampling stops either when is met or this number '
- 'of steps has passed.')
-tf.flags.DEFINE_integer('num_samples', 3,
- 'Number of samples to generate for the prefix.')
-# dump_lstm_emb mode flags.
-tf.flags.DEFINE_string('sentence', '',
- 'Used as input for "dump_lstm_emb" mode.')
-# eval mode flags.
-tf.flags.DEFINE_string('input_data', '',
- 'Input data files for eval model.')
-tf.flags.DEFINE_integer('max_eval_steps', 1000000,
- 'Maximum mumber of steps to run "eval" mode.')
-
-
-# For saving demo resources, use batch size 1 and step 1.
-BATCH_SIZE = 1
-NUM_TIMESTEPS = 1
-MAX_WORD_LEN = 50
-
-
-def _LoadModel(gd_file, ckpt_file):
- """Load the model from GraphDef and Checkpoint.
-
- Args:
- gd_file: GraphDef proto text file.
- ckpt_file: TensorFlow Checkpoint file.
-
- Returns:
- TensorFlow session and tensors dict.
- """
- with tf.Graph().as_default():
- sys.stderr.write('Recovering graph.\n')
- with tf.gfile.FastGFile(gd_file, 'r') as f:
- s = f.read().decode()
- gd = tf.GraphDef()
- text_format.Merge(s, gd)
-
- tf.logging.info('Recovering Graph %s', gd_file)
- t = {}
- [t['states_init'], t['lstm/lstm_0/control_dependency'],
- t['lstm/lstm_1/control_dependency'], t['softmax_out'], t['class_ids_out'],
- t['class_weights_out'], t['log_perplexity_out'], t['inputs_in'],
- t['targets_in'], t['target_weights_in'], t['char_inputs_in'],
- t['all_embs'], t['softmax_weights'], t['global_step']
- ] = tf.import_graph_def(gd, {}, ['states_init',
- 'lstm/lstm_0/control_dependency:0',
- 'lstm/lstm_1/control_dependency:0',
- 'softmax_out:0',
- 'class_ids_out:0',
- 'class_weights_out:0',
- 'log_perplexity_out:0',
- 'inputs_in:0',
- 'targets_in:0',
- 'target_weights_in:0',
- 'char_inputs_in:0',
- 'all_embs_out:0',
- 'Reshape_3:0',
- 'global_step:0'], name='')
-
- sys.stderr.write('Recovering checkpoint %s\n' % ckpt_file)
- sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True))
- sess.run('save/restore_all', {'save/Const:0': ckpt_file})
- sess.run(t['states_init'])
-
- return sess, t
-
-
-def _EvalModel(dataset):
- """Evaluate model perplexity using provided dataset.
-
- Args:
- dataset: LM1BDataset object.
- """
- sess, t = _LoadModel(FLAGS.pbtxt, FLAGS.ckpt)
-
- current_step = t['global_step'].eval(session=sess)
- sys.stderr.write('Loaded step %d.\n' % current_step)
-
- data_gen = dataset.get_batch(BATCH_SIZE, NUM_TIMESTEPS, forever=False)
- sum_num = 0.0
- sum_den = 0.0
- perplexity = 0.0
- for i, (inputs, char_inputs, _, targets, weights) in enumerate(data_gen):
- input_dict = {t['inputs_in']: inputs,
- t['targets_in']: targets,
- t['target_weights_in']: weights}
- if 'char_inputs_in' in t:
- input_dict[t['char_inputs_in']] = char_inputs
- log_perp = sess.run(t['log_perplexity_out'], feed_dict=input_dict)
-
- if np.isnan(log_perp):
- sys.stderr.error('log_perplexity is Nan.\n')
- else:
- sum_num += log_perp * weights.mean()
- sum_den += weights.mean()
- if sum_den > 0:
- perplexity = np.exp(sum_num / sum_den)
-
- sys.stderr.write('Eval Step: %d, Average Perplexity: %f.\n' %
- (i, perplexity))
-
- if i > FLAGS.max_eval_steps:
- break
-
-
-def _SampleSoftmax(softmax):
- return min(np.sum(np.cumsum(softmax) < np.random.rand()), len(softmax) - 1)
-
-
-def _SampleModel(prefix_words, vocab):
- """Predict next words using the given prefix words.
-
- Args:
- prefix_words: Prefix words.
- vocab: Vocabulary. Contains max word chard id length and converts between
- words and ids.
- """
- targets = np.zeros([BATCH_SIZE, NUM_TIMESTEPS], np.int32)
- weights = np.ones([BATCH_SIZE, NUM_TIMESTEPS], np.float32)
-
- sess, t = _LoadModel(FLAGS.pbtxt, FLAGS.ckpt)
-
- if prefix_words.find('') != 0:
- prefix_words = ' ' + prefix_words
-
- prefix = [vocab.word_to_id(w) for w in prefix_words.split()]
- prefix_char_ids = [vocab.word_to_char_ids(w) for w in prefix_words.split()]
- for _ in xrange(FLAGS.num_samples):
- inputs = np.zeros([BATCH_SIZE, NUM_TIMESTEPS], np.int32)
- char_ids_inputs = np.zeros(
- [BATCH_SIZE, NUM_TIMESTEPS, vocab.max_word_length], np.int32)
- samples = prefix[:]
- char_ids_samples = prefix_char_ids[:]
- sent = ''
- while True:
- inputs[0, 0] = samples[0]
- char_ids_inputs[0, 0, :] = char_ids_samples[0]
- samples = samples[1:]
- char_ids_samples = char_ids_samples[1:]
-
- softmax = sess.run(t['softmax_out'],
- feed_dict={t['char_inputs_in']: char_ids_inputs,
- t['inputs_in']: inputs,
- t['targets_in']: targets,
- t['target_weights_in']: weights})
-
- sample = _SampleSoftmax(softmax[0])
- sample_char_ids = vocab.word_to_char_ids(vocab.id_to_word(sample))
-
- if not samples:
- samples = [sample]
- char_ids_samples = [sample_char_ids]
- sent += vocab.id_to_word(samples[0]) + ' '
- sys.stderr.write('%s\n' % sent)
-
- if (vocab.id_to_word(samples[0]) == '' or
- len(sent) > FLAGS.max_sample_words):
- break
-
-
-def _DumpEmb(vocab):
- """Dump the softmax weights and word embeddings to files.
-
- Args:
- vocab: Vocabulary. Contains vocabulary size and converts word to ids.
- """
- assert FLAGS.save_dir, 'Must specify FLAGS.save_dir for dump_emb.'
- inputs = np.zeros([BATCH_SIZE, NUM_TIMESTEPS], np.int32)
- targets = np.zeros([BATCH_SIZE, NUM_TIMESTEPS], np.int32)
- weights = np.ones([BATCH_SIZE, NUM_TIMESTEPS], np.float32)
-
- sess, t = _LoadModel(FLAGS.pbtxt, FLAGS.ckpt)
-
- softmax_weights = sess.run(t['softmax_weights'])
- fname = FLAGS.save_dir + '/embeddings_softmax.npy'
- with tf.gfile.Open(fname, mode='w') as f:
- np.save(f, softmax_weights)
- sys.stderr.write('Finished softmax weights\n')
-
- all_embs = np.zeros([vocab.size, 1024])
- for i in xrange(vocab.size):
- input_dict = {t['inputs_in']: inputs,
- t['targets_in']: targets,
- t['target_weights_in']: weights}
- if 'char_inputs_in' in t:
- input_dict[t['char_inputs_in']] = (
- vocab.word_char_ids[i].reshape([-1, 1, MAX_WORD_LEN]))
- embs = sess.run(t['all_embs'], input_dict)
- all_embs[i, :] = embs
- sys.stderr.write('Finished word embedding %d/%d\n' % (i, vocab.size))
-
- fname = FLAGS.save_dir + '/embeddings_char_cnn.npy'
- with tf.gfile.Open(fname, mode='w') as f:
- np.save(f, all_embs)
- sys.stderr.write('Embedding file saved\n')
-
-
-def _DumpSentenceEmbedding(sentence, vocab):
- """Predict next words using the given prefix words.
-
- Args:
- sentence: Sentence words.
- vocab: Vocabulary. Contains max word chard id length and converts between
- words and ids.
- """
- targets = np.zeros([BATCH_SIZE, NUM_TIMESTEPS], np.int32)
- weights = np.ones([BATCH_SIZE, NUM_TIMESTEPS], np.float32)
-
- sess, t = _LoadModel(FLAGS.pbtxt, FLAGS.ckpt)
-
- if sentence.find('') != 0:
- sentence = ' ' + sentence
-
- word_ids = [vocab.word_to_id(w) for w in sentence.split()]
- char_ids = [vocab.word_to_char_ids(w) for w in sentence.split()]
-
- inputs = np.zeros([BATCH_SIZE, NUM_TIMESTEPS], np.int32)
- char_ids_inputs = np.zeros(
- [BATCH_SIZE, NUM_TIMESTEPS, vocab.max_word_length], np.int32)
- for i in xrange(len(word_ids)):
- inputs[0, 0] = word_ids[i]
- char_ids_inputs[0, 0, :] = char_ids[i]
-
- # Add 'lstm/lstm_0/control_dependency' if you want to dump previous layer
- # LSTM.
- lstm_emb = sess.run(t['lstm/lstm_1/control_dependency'],
- feed_dict={t['char_inputs_in']: char_ids_inputs,
- t['inputs_in']: inputs,
- t['targets_in']: targets,
- t['target_weights_in']: weights})
-
- fname = os.path.join(FLAGS.save_dir, 'lstm_emb_step_%d.npy' % i)
- with tf.gfile.Open(fname, mode='w') as f:
- np.save(f, lstm_emb)
- sys.stderr.write('LSTM embedding step %d file saved\n' % i)
-
-
-def main(unused_argv):
- vocab = data_utils.CharsVocabulary(FLAGS.vocab_file, MAX_WORD_LEN)
-
- if FLAGS.mode == 'eval':
- dataset = data_utils.LM1BDataset(FLAGS.input_data, vocab)
- _EvalModel(dataset)
- elif FLAGS.mode == 'sample':
- _SampleModel(FLAGS.prefix, vocab)
- elif FLAGS.mode == 'dump_emb':
- _DumpEmb(vocab)
- elif FLAGS.mode == 'dump_lstm_emb':
- _DumpSentenceEmbedding(FLAGS.sentence, vocab)
- else:
- raise Exception('Mode not supported.')
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/lm_commonsense/README.md b/research/lm_commonsense/README.md
deleted file mode 100644
index 78c8f53ca226f09c4b185490d6966f98bf584889..0000000000000000000000000000000000000000
--- a/research/lm_commonsense/README.md
+++ /dev/null
@@ -1,170 +0,0 @@
-
-
-
-
-# A Simple Method for Commonsense Reasoning
-
-This repository contains code to reproduce results from [*A Simple Method for Commonsense Reasoning*](https://arxiv.org/abs/1806.02847).
-
-Authors and contact:
-
-* Trieu H. Trinh (thtrieu@google.com, github: thtrieu)
-* Quoc V. Le (qvl@google.com)
-
-## TL;DR
-
-Commonsense reasoning is a long-standing challenge for deep learning. For example,
-it is difficult to use neural networks to tackle the Winograd Schema dataset - a difficult subset of Pronoun Disambiguation problems. In this work, we use language models to score substitued sentences to decide the correct reference of the ambiguous pronoun (see Figure below for an example).
-
-
-
-This simple unsupervised method achieves new state-of-the-art (*as of June 1st, 2018*) results on both benchmark PDP-60 and WSC-273 (See Table below), without using rule-based reasoning nor expensive annotated knowledge bases.
-
-| Commonsense-reasoning test | Previous best result | Ours |
-| ----------------------------|:----------------------:|:-----:|
-| Pronoun Disambiguation | 66.7% | 70% |
-| Winograd Schema Challenge | 52.8% | 63.7% |
-
-
-
-## Citation
-
-If you use our released models below in your publication, please cite the original paper:
-
-@article{TBD}
-
-
-## Requirements
-* Python >=2.6
-* Tensorflow >= v1.4
-* Numpy >= 1.12.1
-
-## Details of this release
-
-The open-sourced components include:
-
-* Test sets from Pronoun Disambiguation Problem (PDP-60) and Winograd Schema Challenges (WSC-273).
-* Tensorflow metagraph and checkpoints of 14 language models (See Appendix A in the paper).
-* A vocabulary file.
-* Code to reproduce results from the original paper.
-
-## How to run
-
-### 1. Download data files
-
-Download all files from the [Google Cloud Storage of this project](https://console.cloud.google.com/storage/browser/commonsense-reasoning/). The easiest way is to install and use `gsutil cp` command-line tool (See [install gsutil](https://cloud.google.com/storage/docs/gsutil_install)).
-
-
-```shell
-# Download everything from the project gs://commonsense-reasoning
-$ gsutil cp -R gs://commonsense-reasoning/* .
-Copying gs://commonsense-reasoning/reproduce/vocab.txt...
-Copying gs://commonsense-reasoning/reproduce/commonsense_test/pdp60.json...
-Copying gs://commonsense-reasoning/reproduce/commonsense_test/wsc273.json...
-
-...(omitted)
-```
-
-All downloaded content should be in `./reproduce/`. This includes two tests `pdp60.json` and `wsc273.json`, a vocabulary file `vocab.txt` and checkpoints for all 14 language models, each includes three files (`.data`, `.index` and `.meta`). All checkpoint names start with `ckpt-best` since they are saved at the best perplexity on a hold-out text corpus.
-
-```shell
-# Check for the content
-$ ls reproduce/*
-reproduce/vocab.txt
-
-reproduce/commonsense_test:
-pdp60.json wsc273.json
-
-reproduce/lm01:
-ckpt-best.data-00000-of-00001 ckpt-best.index ckpt-best.meta
-
-reproduce/lm02:
-ckpt-best.data-00000-of-00001 ckpt-best.index ckpt-best.meta
-
-reproduce/lm03:
-ckpt-best.data-00000-of-00001 ckpt-best.index ckpt-best.meta
-
-reproduce/lm04:
-ckpt-best.data-00000-of-00001 ckpt-best.index ckpt-best.meta
-
-reproduce/lm05:
-ckpt-best.data-00000-of-00001 ckpt-best.index ckpt-best.meta
-
-reproduce/lm06:
-ckpt-best.data-00000-of-00001 ckpt-best.index ckpt-best.meta
-
-reproduce/lm07:
-ckpt-best.data-00000-of-00001 ckpt-best.index ckpt-best.meta
-
-reproduce/lm08:
-ckpt-best.data-00000-of-00001 ckpt-best.index ckpt-best.meta
-
-reproduce/lm09:
-ckpt-best.data-00000-of-00001 ckpt-best.index ckpt-best.meta
-
-reproduce/lm10:
-ckpt-best.data-00000-of-00001 ckpt-best.index ckpt-best.meta
-
-reproduce/lm11:
-ckpt-best.data-00000-of-00001 ckpt-best.index ckpt-best.meta
-
-reproduce/lm12:
-ckpt-best.data-00000-of-00001 ckpt-best.index ckpt-best.meta
-
-reproduce/lm13:
-ckpt-best.data-00000-of-00001 ckpt-best.index ckpt-best.meta
-
-reproduce/lm14:
-ckpt-best.data-00000-of-00001 ckpt-best.index ckpt-best.meta
-```
-
-### 2. Run evaluation code
-
-To reproduce results from the paper, simply run `eval.py` script.
-
-```shell
-$ python eval.py --data_dir=reproduce
-
-Restored from ./reproduce/lm01
-Reset RNN states.
-Processing patch (1, 1) / (2, 4)
-Probs for
-[['Then' 'Dad' 'figured' ..., 'man' "'s" 'board-bill']
- ['Then' 'Dad' 'figured' ..., 'man' "'s" 'board-bill']
- ['Always' 'before' ',' ..., 'now' ',' 'for']
- ...,
- ['Mark' 'was' 'close' ..., 'promising' 'him' ',']
- ['Mark' 'was' 'close' ..., 'promising' 'him' ',']
- ['Mark' 'was' 'close' ..., 'promising' 'him' ',']]
-=
-[[ 1.64250596e-05 1.77780055e-06 4.14267970e-06 ..., 1.87315454e-03
- 1.57723188e-01 6.31845817e-02]
- [ 1.64250596e-05 1.77780055e-06 4.14267970e-06 ..., 1.87315454e-03
- 1.57723188e-01 6.31845817e-02]
- [ 1.28243030e-07 3.80435935e-03 1.12383246e-01 ..., 9.67682712e-03
- 2.17407525e-01 1.08243264e-01]
- ...,
- [ 1.15557734e-04 2.92792241e-03 3.46455898e-04 ..., 2.72328052e-05
- 3.37066874e-02 7.89367408e-02]
- [ 1.15557734e-04 2.92792241e-03 3.46455898e-04 ..., 2.72328052e-05
- 3.37066874e-02 7.89367408e-02]
- [ 1.15557734e-04 2.92792241e-03 3.46455898e-04 ..., 2.72328052e-05
- 3.37066874e-02 7.89367408e-02]]
-Processing patch (1, 2) / (2, 4)
-
-...(omitted)
-
-Accuracy of 1 LM(s) on pdp60 = 0.6
-
-...(omitted)
-
-Accuracy of 5 LM(s) on pdp60 = 0.7
-
-...(omitted)
-
-Accuracy of 10 LM(s) on wsc273 = 0.615
-
-...(omitted)
-
-Accuracy of 14 LM(s) on wsc273 = 0.637
-```
diff --git a/research/lm_commonsense/eval.py b/research/lm_commonsense/eval.py
deleted file mode 100644
index e5b7ff98b50a5af4e066d3d9f82c1acae81c3e93..0000000000000000000000000000000000000000
--- a/research/lm_commonsense/eval.py
+++ /dev/null
@@ -1,190 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import pickle as pkl
-import numpy as np
-import tensorflow as tf
-import utils
-
-tf.app.flags.DEFINE_string(
- 'data_dir', 'reproduce',
- 'Path to directory containing data and model checkpoints.')
-
-
-FLAGS = tf.app.flags.FLAGS
-
-
-class EnsembleLM(object):
- """Ensemble of language models."""
-
- def __init__(self, test_data_name='wsc273'):
- vocab_file = os.path.join(FLAGS.data_dir, 'vocab.txt')
- self.vocab = utils.CharsVocabulary(vocab_file, 50)
- assert test_data_name in ['pdp60', 'wsc273'], (
- 'Test data must be pdp60 or wsc273, got {}'.format(test_data_name))
- self.test_data_name = test_data_name
-
- test_data = utils.parse_commonsense_reasoning_test(test_data_name)
- self.question_ids, self.sentences, self.labels = test_data
- self.all_probs = [] # aggregate single-model prediction here.
-
- def add_single_model(self, model_name='lm1'):
- """Add a single model into the current ensemble."""
- # Create single LM
- single_lm = SingleRecurrentLanguageModel(self.vocab, model_name)
-
- # Add the single LM prediction.
- probs = single_lm.assign_probs(self.sentences, self.test_data_name)
- self.all_probs.append(probs)
- print('Done adding {}'.format(model_name))
-
- def evaluate(self):
- """Evaluate the current ensemble."""
- # Attach word probabilities and correctness label to each substitution
- ensembled_probs = sum(self.all_probs) / len(self.all_probs)
- scorings = []
- for i, sentence in enumerate(self.sentences):
- correctness = self.labels[i]
- word_probs = ensembled_probs[i, :len(sentence)]
- joint_prob = np.prod(word_probs, dtype=np.float64)
-
- scorings.append(dict(
- correctness=correctness,
- sentence=sentence,
- joint_prob=joint_prob,
- word_probs=word_probs))
- scoring_mode = 'full' if self.test_data_name == 'pdp60' else 'partial'
- return utils.compare_substitutions(
- self.question_ids, scorings, scoring_mode)
-
-
-class SingleRecurrentLanguageModel(object):
- """Single Recurrent Language Model."""
-
- def __init__(self, vocab, model_name='lm01'):
- self.vocab = vocab
- self.log_dir = os.path.join(FLAGS.data_dir, model_name)
-
- def reset(self):
- self.sess.run(self.tensors['states_init'])
-
- def _score(self, word_patch):
- """Score a matrix of shape (batch_size, num_timesteps+1) str tokens."""
- word_ids = np.array(
- [[self.vocab.word_to_id(word) for word in row]
- for row in word_patch])
- char_ids = np.array(
- [[self.vocab.word_to_char_ids(word) for word in row]
- for row in word_patch])
- print('Probs for \n{}\n='.format(np.array(word_patch)[:, 1:]))
-
- input_ids, target_ids = word_ids[:, :-1], word_ids[:, 1:]
- input_char_ids = char_ids[:, :-1, :]
-
- softmax = self.sess.run(self.tensors['softmax_out'], feed_dict={
- self.tensors['inputs_in']: input_ids,
- self.tensors['char_inputs_in']: input_char_ids
- })
-
- batch_size, num_timesteps = self.shape
- softmax = softmax.reshape((num_timesteps, batch_size, -1))
- softmax = np.transpose(softmax, [1, 0, 2])
- probs = np.array([[softmax[row, col, target_ids[row, col]]
- for col in range(num_timesteps)]
- for row in range(batch_size)])
- print(probs)
- return probs
-
- def _score_patches(self, word_patches):
- """Score a 2D matrix of word_patches and stitch results together."""
- batch_size, num_timesteps = self.shape
- nrow, ncol = len(word_patches), len(word_patches[0])
- max_len = num_timesteps * ncol
- probs = np.zeros([0, max_len]) # accumulate results into this.
-
- # Loop through the 2D matrix of word_patches and score each.
- for i, row in enumerate(word_patches):
- print('Reset RNN states.')
- self.reset() # reset states before processing each row.
- row_probs = np.zeros([batch_size, 0])
- for j, word_patch in enumerate(row):
- print('Processing patch '
- '({}, {}) / ({}, {})'.format(i+1, j+1, nrow, ncol))
- patch_probs = (self._score(word_patch) if word_patch else
- np.zeros([batch_size, num_timesteps]))
- row_probs = np.concatenate([row_probs, patch_probs], 1)
- probs = np.concatenate([probs, row_probs], 0)
- return probs
-
- def assign_probs(self, sentences, test_data_name='wsc273'):
- """Return prediction accuracy using this LM for a test."""
-
- probs_cache = os.path.join(self.log_dir, '{}.probs'.format(test_data_name))
- if os.path.exists(probs_cache):
- print('Reading cached result from {}'.format(probs_cache))
- with tf.gfile.Open(probs_cache, 'r') as f:
- probs = pkl.load(f)
- else:
- tf.reset_default_graph()
- self.sess = tf.Session()
- # Build the graph.
- saver = tf.train.import_meta_graph(
- os.path.join(self.log_dir, 'ckpt-best.meta'))
- saver.restore(self.sess, os.path.join(self.log_dir, 'ckpt-best'))
- print('Restored from {}'.format(self.log_dir))
- graph = tf.get_default_graph()
- self.tensors = dict(
- inputs_in=graph.get_tensor_by_name('test_inputs_in:0'),
- char_inputs_in=graph.get_tensor_by_name('test_char_inputs_in:0'),
- softmax_out=graph.get_tensor_by_name('SotaRNN_1/softmax_out:0'),
- states_init=graph.get_operation_by_name('SotaRNN_1/states_init'))
- self.shape = self.tensors['inputs_in'].shape.as_list()
-
- # Cut sentences into patches of shape processable by the LM.
- batch_size, num_timesteps = self.shape
- word_patches = utils.cut_to_patches(sentences, batch_size, num_timesteps)
- probs = self._score_patches(word_patches)
-
- # Cache the probs since they are expensive to evaluate
- with tf.gfile.Open(probs_cache, 'w') as f:
- pkl.dump(probs, f)
- return probs
-
-
-def evaluate_ensemble(test_data_name, number_of_lms):
- ensemble = EnsembleLM(test_data_name)
- model_list = ['lm{:02d}'.format(i+1) for i in range(number_of_lms)]
- for model_name in model_list:
- ensemble.add_single_model(model_name)
- accuracy = ensemble.evaluate()
- print('Accuracy of {} LM(s) on {} = {}'.format(
- number_of_lms, test_data_name, accuracy))
-
-
-def main(_):
- evaluate_ensemble('pdp60', 1) # 60%
- evaluate_ensemble('pdp60', 5) # 70%
- evaluate_ensemble('wsc273', 10) # 61.5%
- evaluate_ensemble('wsc273', 14) # 63.7%
-
-
-if __name__ == '__main__':
- tf.app.run(main)
diff --git a/research/lm_commonsense/method.jpg b/research/lm_commonsense/method.jpg
deleted file mode 100644
index ee8a5506fccca3cbb67f7bda0ccef78303cb228b..0000000000000000000000000000000000000000
Binary files a/research/lm_commonsense/method.jpg and /dev/null differ
diff --git a/research/lm_commonsense/utils.py b/research/lm_commonsense/utils.py
deleted file mode 100644
index d75f2b0fb72716860ea6d438e6b8ca2732d13c84..0000000000000000000000000000000000000000
--- a/research/lm_commonsense/utils.py
+++ /dev/null
@@ -1,368 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import json
-import os
-import numpy as np
-import tensorflow as tf
-
-FLAGS = tf.flags.FLAGS
-
-
-class Vocabulary(object):
- """Class that holds a vocabulary for the dataset."""
-
- def __init__(self, filename):
-
- self._id_to_word = []
- self._word_to_id = {}
- self._unk = -1
- self._bos = -1
- self._eos = -1
-
- with tf.gfile.Open(filename) as f:
- idx = 0
- for line in f:
- word_name = line.strip()
- if word_name == '':
- self._bos = idx
- elif word_name == '':
- self._eos = idx
- elif word_name == '':
- self._unk = idx
- if word_name == '!!!MAXTERMID':
- continue
-
- self._id_to_word.append(word_name)
- self._word_to_id[word_name] = idx
- idx += 1
-
- @property
- def bos(self):
- return self._bos
-
- @property
- def eos(self):
- return self._eos
-
- @property
- def unk(self):
- return self._unk
-
- @property
- def size(self):
- return len(self._id_to_word)
-
- def word_to_id(self, word):
- if word in self._word_to_id:
- return self._word_to_id[word]
- else:
- if word.lower() in self._word_to_id:
- return self._word_to_id[word.lower()]
- return self.unk
-
- def id_to_word(self, cur_id):
- if cur_id < self.size:
- return self._id_to_word[int(cur_id)]
- return ''
-
- def decode(self, cur_ids):
- return ' '.join([self.id_to_word(cur_id) for cur_id in cur_ids])
-
- def encode(self, sentence):
- word_ids = [self.word_to_id(cur_word) for cur_word in sentence.split()]
- return np.array([self.bos] + word_ids + [self.eos], dtype=np.int32)
-
-
-class CharsVocabulary(Vocabulary):
- """Vocabulary containing character-level information."""
-
- def __init__(self, filename, max_word_length):
- super(CharsVocabulary, self).__init__(filename)
-
- self._max_word_length = max_word_length
- chars_set = set()
-
- for word in self._id_to_word:
- chars_set |= set(word)
-
- free_ids = []
- for i in range(256):
- if chr(i) in chars_set:
- continue
- free_ids.append(chr(i))
-
- if len(free_ids) < 5:
- raise ValueError('Not enough free char ids: %d' % len(free_ids))
-
- self.bos_char = free_ids[0] #
- self.eos_char = free_ids[1] #
- self.bow_char = free_ids[2] #
- self.eow_char = free_ids[3] #
- self.pad_char = free_ids[4] #
-
- chars_set |= {self.bos_char, self.eos_char, self.bow_char, self.eow_char,
- self.pad_char}
-
- self._char_set = chars_set
- num_words = len(self._id_to_word)
-
- self._word_char_ids = np.zeros([num_words, max_word_length], dtype=np.int32)
-
- self.bos_chars = self._convert_word_to_char_ids(self.bos_char)
- self.eos_chars = self._convert_word_to_char_ids(self.eos_char)
-
- for i, word in enumerate(self._id_to_word):
- if i == self.bos:
- self._word_char_ids[i] = self.bos_chars
- elif i == self.eos:
- self._word_char_ids[i] = self.eos_chars
- else:
- self._word_char_ids[i] = self._convert_word_to_char_ids(word)
-
- @property
- def max_word_length(self):
- return self._max_word_length
-
- def _convert_word_to_char_ids(self, word):
- code = np.zeros([self.max_word_length], dtype=np.int32)
- code[:] = ord(self.pad_char)
-
- if len(word) > self.max_word_length - 2:
- word = word[:self.max_word_length-2]
- cur_word = self.bow_char + word + self.eow_char
- for j in range(len(cur_word)):
- code[j] = ord(cur_word[j])
- return code
-
- def word_to_char_ids(self, word):
- if word in self._word_to_id:
- return self._word_char_ids[self._word_to_id[word]]
- else:
- return self._convert_word_to_char_ids(word)
-
- def encode_chars(self, sentence):
- chars_ids = [self.word_to_char_ids(cur_word)
- for cur_word in sentence.split()]
- return np.vstack([self.bos_chars] + chars_ids + [self.eos_chars])
-
-
-_SPECIAL_CHAR_MAP = {
- '\xe2\x80\x98': '\'',
- '\xe2\x80\x99': '\'',
- '\xe2\x80\x9c': '"',
- '\xe2\x80\x9d': '"',
- '\xe2\x80\x93': '-',
- '\xe2\x80\x94': '-',
- '\xe2\x88\x92': '-',
- '\xce\x84': '\'',
- '\xc2\xb4': '\'',
- '`': '\''
-}
-
-_START_SPECIAL_CHARS = ['.', ',', '?', '!', ';', ':', '[', ']', '\'', '+', '/',
- '\xc2\xa3', '$', '~', '*', '%', '{', '}', '#', '&', '-',
- '"', '(', ')', '='] + list(_SPECIAL_CHAR_MAP.keys())
-_SPECIAL_CHARS = _START_SPECIAL_CHARS + [
- '\'s', '\'m', '\'t', '\'re', '\'d', '\'ve', '\'ll']
-
-
-def tokenize(sentence):
- """Tokenize a sentence."""
- sentence = str(sentence)
- words = sentence.strip().split()
- tokenized = [] # return this
-
- for word in words:
- if word.lower() in ['mr.', 'ms.']:
- tokenized.append(word)
- continue
-
- # Split special chars at the start of word
- will_split = True
- while will_split:
- will_split = False
- for char in _START_SPECIAL_CHARS:
- if word.startswith(char):
- tokenized.append(char)
- word = word[len(char):]
- will_split = True
-
- # Split special chars at the end of word
- special_end_tokens = []
- will_split = True
- while will_split:
- will_split = False
- for char in _SPECIAL_CHARS:
- if word.endswith(char):
- special_end_tokens = [char] + special_end_tokens
- word = word[:-len(char)]
- will_split = True
-
- if word:
- tokenized.append(word)
- tokenized += special_end_tokens
-
- # Add necessary end of sentence token.
- if tokenized[-1] not in ['.', '!', '?']:
- tokenized += ['.']
- return tokenized
-
-
-def parse_commonsense_reasoning_test(test_data_name):
- """Read JSON test data."""
- with tf.gfile.Open(os.path.join(
- FLAGS.data_dir, 'commonsense_test',
- '{}.json'.format(test_data_name)), 'r') as f:
- data = json.load(f)
-
- question_ids = [d['question_id'] for d in data]
- sentences = [tokenize(d['substitution']) for d in data]
- labels = [d['correctness'] for d in data]
-
- return question_ids, sentences, labels
-
-
-PAD = ''
-
-
-def cut_to_patches(sentences, batch_size, num_timesteps):
- """Cut sentences into patches of shape (batch_size, num_timesteps).
-
- Args:
- sentences: a list of sentences, each sentence is a list of str token.
- batch_size: batch size
- num_timesteps: number of backprop step
-
- Returns:
- patches: A 2D matrix,
- each entry is a matrix of shape (batch_size, num_timesteps).
- """
- preprocessed = [['']+sentence+[''] for sentence in sentences]
- max_len = max([len(sent) for sent in preprocessed])
-
- # Pad to shape [height, width]
- # where height is a multiple of batch_size
- # and width is a multiple of num_timesteps
- nrow = int(np.ceil(len(preprocessed) * 1.0 / batch_size))
- ncol = int(np.ceil(max_len * 1.0 / num_timesteps))
- height, width = nrow * batch_size, ncol * num_timesteps + 1
- preprocessed = [sent + [PAD] * (width - len(sent)) for sent in preprocessed]
- preprocessed += [[PAD] * width] * (height - len(preprocessed))
-
- # Cut preprocessed into patches of shape [batch_size, num_timesteps]
- patches = []
- for row in range(nrow):
- patches.append([])
- for col in range(ncol):
- patch = [sent[col * num_timesteps:
- (col+1) * num_timesteps + 1]
- for sent in preprocessed[row * batch_size:
- (row+1) * batch_size]]
- if np.all(np.array(patch)[:, 1:] == PAD):
- patch = None # no need to process this patch.
- patches[-1].append(patch)
- return patches
-
-
-def _substitution_mask(sent1, sent2):
- """Binary mask identifying substituted part in two sentences.
-
- Example sentence and their mask:
- First sentence = "I like the cat 's color"
- 0 0 0 1 0 0
- Second sentence = "I like the yellow dog 's color"
- 0 0 0 1 1 0 0
-
- Args:
- sent1: first sentence
- sent2: second sentence
-
- Returns:
- mask1: mask for first sentence
- mask2: mask for second sentence
- """
- mask1_start, mask2_start = [], []
- while sent1[0] == sent2[0]:
- sent1 = sent1[1:]
- sent2 = sent2[1:]
- mask1_start.append(0.)
- mask2_start.append(0.)
-
- mask1_end, mask2_end = [], []
- while sent1[-1] == sent2[-1]:
- if (len(sent1) == 1) or (len(sent2) == 1):
- break
- sent1 = sent1[:-1]
- sent2 = sent2[:-1]
- mask1_end = [0.] + mask1_end
- mask2_end = [0.] + mask2_end
-
- assert sent1 or sent2, 'Two sentences are identical.'
- return (mask1_start + [1.] * len(sent1) + mask1_end,
- mask2_start + [1.] * len(sent2) + mask2_end)
-
-
-def _convert_to_partial(scoring1, scoring2):
- """Convert full scoring into partial scoring."""
- mask1, mask2 = _substitution_mask(
- scoring1['sentence'], scoring2['sentence'])
-
- def _partial_score(scoring, mask):
- word_probs = [max(_) for _ in zip(scoring['word_probs'], mask)]
- scoring.update(word_probs=word_probs,
- joint_prob=np.prod(word_probs))
-
- _partial_score(scoring1, mask1)
- _partial_score(scoring2, mask2)
-
-
-def compare_substitutions(question_ids, scorings, mode='full'):
- """Return accuracy by comparing two consecutive scorings."""
- prediction_correctness = []
- # Compare two consecutive substitutions
- for i in range(len(scorings) // 2):
- scoring1, scoring2 = scorings[2*i: 2*i+2]
- if mode == 'partial': # fix joint prob into partial prob
- _convert_to_partial(scoring1, scoring2)
-
- prediction_correctness.append(
- (scoring2['joint_prob'] > scoring1['joint_prob']) ==
- scoring2['correctness'])
-
- # Two consecutive substitutions always belong to the same question
- question_ids = [qid for i, qid in enumerate(question_ids) if i % 2 == 0]
- assert len(question_ids) == len(prediction_correctness)
- num_questions = len(set(question_ids))
-
- # Question is correctly answered only if
- # all predictions of the same question_id is correct
- num_correct_answer = 0
- previous_qid = None
- correctly_answered = False
- for predict, qid in zip(prediction_correctness, question_ids):
- if qid != previous_qid:
- previous_qid = qid
- num_correct_answer += int(correctly_answered)
- correctly_answered = True
- correctly_answered = correctly_answered and predict
- num_correct_answer += int(correctly_answered)
-
- return num_correct_answer / num_questions
diff --git a/research/maskgan/README.md b/research/maskgan/README.md
deleted file mode 100644
index 10ee8a4c4dd546983469b07e2fb8207fc200534d..0000000000000000000000000000000000000000
--- a/research/maskgan/README.md
+++ /dev/null
@@ -1,111 +0,0 @@
-
-
-
-
-# MaskGAN: Better Text Generation via Filling in the ______
-
-Code for [*MaskGAN: Better Text Generation via Filling in the
-______*](https://arxiv.org/abs/1801.07736) published at ICLR 2018.
-
-## Requirements
-
-* TensorFlow >= v1.5
-
-## Instructions
-
-Warning: The open-source version of this code is still in the process of being
-tested. Pretraining may not work correctly.
-
-For training on PTB:
-
-1. Follow instructions here ([Tensorflow RNN Language Model Tutorial](https://www.tensorflow.org/tutorials/sequences/recurrent)) to train a language model on PTB dataset.
-Copy PTB data downloaded from the above tensorflow RNN tutorial to folder "/tmp/ptb". It should contain following three files: ptb.train.txt, ptb.test.txt, ptb.valid.txt
-Make folder /tmp/pretrain-lm and copy checkpoints from above Tensorflow RNN tutorial under this folder.
-
-
-2. Run MaskGAN in MLE pretraining mode. If step 1 was not run*, set
-`language_model_ckpt_dir` to empty.
-
-```bash
-python train_mask_gan.py \
- --data_dir='/tmp/ptb' \
- --batch_size=20 \
- --sequence_length=20 \
- --base_directory='/tmp/maskGAN' \
- --hparams="gen_rnn_size=650,dis_rnn_size=650,gen_num_layers=2,dis_num_layers=2,gen_learning_rate=0.00074876,dis_learning_rate=5e-4,baseline_decay=0.99,dis_train_iterations=1,gen_learning_rate_decay=0.95" \
- --mode='TRAIN' \
- --max_steps=100000 \
- --language_model_ckpt_dir=/tmp/pretrain-lm/ \
- --generator_model='seq2seq_vd' \
- --discriminator_model='rnn_zaremba' \
- --is_present_rate=0.5 \
- --summaries_every=10 \
- --print_every=250 \
- --max_num_to_print=3 \
- --gen_training_strategy=cross_entropy \
- --seq2seq_share_embedding
-```
-
-3. Run MaskGAN in GAN mode. If step 2 was not run, set `maskgan_ckpt` to empty.
-```bash
-python train_mask_gan.py \
- --data_dir='/tmp/ptb' \
- --batch_size=128 \
- --sequence_length=20 \
- --base_directory='/tmp/maskGAN' \
- --mask_strategy=contiguous \
- --maskgan_ckpt='/tmp/maskGAN' \
- --hparams="gen_rnn_size=650,dis_rnn_size=650,gen_num_layers=2,dis_num_layers=2,gen_learning_rate=0.000038877,gen_learning_rate_decay=1.0,gen_full_learning_rate_steps=2000000,gen_vd_keep_prob=0.33971,rl_discount_rate=0.89072,dis_learning_rate=5e-4,baseline_decay=0.99,dis_train_iterations=2,dis_pretrain_learning_rate=0.005,critic_learning_rate=5.1761e-7,dis_vd_keep_prob=0.71940" \
- --mode='TRAIN' \
- --max_steps=100000 \
- --generator_model='seq2seq_vd' \
- --discriminator_model='seq2seq_vd' \
- --is_present_rate=0.5 \
- --summaries_every=250 \
- --print_every=250 \
- --max_num_to_print=3 \
- --gen_training_strategy='reinforce' \
- --seq2seq_share_embedding=true \
- --baseline_method=critic \
- --attention_option=luong
-```
-
-4. Generate samples:
-```bash
-python generate_samples.py \
- --data_dir /tmp/ptb/ \
- --data_set=ptb \
- --batch_size=256 \
- --sequence_length=20 \
- --base_directory /tmp/imdbsample/ \
- --hparams="gen_rnn_size=650,dis_rnn_size=650,gen_num_layers=2,gen_vd_keep_prob=0.33971" \
- --generator_model=seq2seq_vd \
- --discriminator_model=seq2seq_vd \
- --is_present_rate=0.0 \
- --maskgan_ckpt=/tmp/maskGAN \
- --seq2seq_share_embedding=True \
- --dis_share_embedding=True \
- --attention_option=luong \
- --mask_strategy=contiguous \
- --baseline_method=critic \
- --number_epochs=4
-```
-
-
-* While trying to run Step 2, the following error appears:
- NotFoundError (see above for traceback): Restoring from checkpoint failed. This is most likely due to a Variable name or other graph key that is missing from the checkpoint. Please ensure that you have not altered the graph expected based on the checkpoint. Original error:
-
- Key critic/rnn/biases not found in checkpoint
- [[node save/RestoreV2 (defined at train_mask_gan.py:431) ]]
-
- This is an issue with seq2seq model because it uses the attention mechanism.
- The issue arises if you saved the model with an earlier version (seq2seq is old) and restore with a recent one (saver.restore got updated).
- The naming convention for LSTM parameters changed, e.g. cell_0/basic_lstm_cell/weights became cell_0/basic_lstm_cell/kernel.
- Which is why you cannot restore them if you try to restore old checkpoints with recent TF.
- The below script will help rename the variables and everything will work as expected.
- https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/rnn/python/tools/checkpoint_convert.py
-
-## Contact for Issues
-
-* Liam Fedus, @liamb315
-* Andrew M. Dai, @a-dai
diff --git a/research/maskgan/data/__init__.py b/research/maskgan/data/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/maskgan/data/imdb_loader.py b/research/maskgan/data/imdb_loader.py
deleted file mode 100644
index 8169b3336b4ac0e1a36e35dbaed4c01f38f1ec02..0000000000000000000000000000000000000000
--- a/research/maskgan/data/imdb_loader.py
+++ /dev/null
@@ -1,136 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""IMDB data loader and helpers."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-# Dependency imports
-import numpy as np
-
-import tensorflow as tf
-
-FLAGS = tf.app.flags.FLAGS
-tf.app.flags.DEFINE_boolean('prefix_label', True, 'Vocabulary file.')
-
-np.set_printoptions(precision=3)
-np.set_printoptions(suppress=True)
-
-EOS_INDEX = 88892
-
-
-def _read_words(filename, use_prefix=True):
- all_words = []
- sequence_example = tf.train.SequenceExample()
- for r in tf.python_io.tf_record_iterator(filename):
- sequence_example.ParseFromString(r)
-
- if FLAGS.prefix_label and use_prefix:
- label = sequence_example.context.feature['class'].int64_list.value[0]
- review_words = [EOS_INDEX + 1 + label]
- else:
- review_words = []
- review_words.extend([
- f.int64_list.value[0]
- for f in sequence_example.feature_lists.feature_list['token_id'].feature
- ])
- all_words.append(review_words)
- return all_words
-
-
-def build_vocab(vocab_file):
- word_to_id = {}
-
- with tf.gfile.GFile(vocab_file, 'r') as f:
- index = 0
- for word in f:
- word_to_id[word.strip()] = index
- index += 1
- word_to_id[''] = EOS_INDEX
-
- return word_to_id
-
-
-def imdb_raw_data(data_path=None):
- """Load IMDB raw data from data directory "data_path".
- Reads IMDB tf record files containing integer ids,
- and performs mini-batching of the inputs.
- Args:
- data_path: string path to the directory where simple-examples.tgz has
- been extracted.
- Returns:
- tuple (train_data, valid_data)
- where each of the data objects can be passed to IMDBIterator.
- """
-
- train_path = os.path.join(data_path, 'train_lm.tfrecords')
- valid_path = os.path.join(data_path, 'test_lm.tfrecords')
-
- train_data = _read_words(train_path)
- valid_data = _read_words(valid_path)
- return train_data, valid_data
-
-
-def imdb_iterator(raw_data, batch_size, num_steps, epoch_size_override=None):
- """Iterate on the raw IMDB data.
-
- This generates batch_size pointers into the raw IMDB data, and allows
- minibatch iteration along these pointers.
-
- Args:
- raw_data: one of the raw data outputs from imdb_raw_data.
- batch_size: int, the batch size.
- num_steps: int, the number of unrolls.
-
- Yields:
- Pairs of the batched data, each a matrix of shape [batch_size, num_steps].
- The second element of the tuple is the same data time-shifted to the
- right by one. The third is a set of weights with 1 indicating a word was
- present and 0 not.
-
- Raises:
- ValueError: if batch_size or num_steps are too high.
- """
- del epoch_size_override
- data_len = len(raw_data)
- num_batches = data_len // batch_size - 1
-
- for batch in range(num_batches):
- x = np.zeros([batch_size, num_steps], dtype=np.int32)
- y = np.zeros([batch_size, num_steps], dtype=np.int32)
- w = np.zeros([batch_size, num_steps], dtype=np.float)
-
- for i in range(batch_size):
- data_index = batch * batch_size + i
- example = raw_data[data_index]
-
- if len(example) > num_steps:
- final_x = example[:num_steps]
- final_y = example[1:(num_steps + 1)]
- w[i] = 1
-
- else:
- to_fill_in = num_steps - len(example)
- final_x = example + [EOS_INDEX] * to_fill_in
- final_y = final_x[1:] + [EOS_INDEX]
- w[i] = [1] * len(example) + [0] * to_fill_in
-
- x[i] = final_x
- y[i] = final_y
-
- yield (x, y, w)
diff --git a/research/maskgan/data/ptb_loader.py b/research/maskgan/data/ptb_loader.py
deleted file mode 100644
index 43105952a667f968faf12a4561f85964f0a123ae..0000000000000000000000000000000000000000
--- a/research/maskgan/data/ptb_loader.py
+++ /dev/null
@@ -1,123 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""PTB data loader and helpers."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-import os
-# Dependency imports
-import numpy as np
-
-import tensorflow as tf
-
-EOS_INDEX = 0
-
-
-def _read_words(filename):
- with tf.gfile.GFile(filename, "r") as f:
- return f.read().decode("utf-8").replace("\n", "").split()
-
-
-def build_vocab(filename):
- data = _read_words(filename)
-
- counter = collections.Counter(data)
- count_pairs = sorted(counter.items(), key=lambda x: (-x[1], x[0]))
-
- words, _ = list(zip(*count_pairs))
- word_to_id = dict(zip(words, range(len(words))))
- print(":", word_to_id[""])
- global EOS_INDEX
- EOS_INDEX = word_to_id[""]
-
- return word_to_id
-
-
-def _file_to_word_ids(filename, word_to_id):
- data = _read_words(filename)
- return [word_to_id[word] for word in data if word in word_to_id]
-
-
-def ptb_raw_data(data_path=None):
- """Load PTB raw data from data directory "data_path".
- Reads PTB text files, converts strings to integer ids,
- and performs mini-batching of the inputs.
- The PTB dataset comes from Tomas Mikolov's webpage:
- http://www.fit.vutbr.cz/~imikolov/rnnlm/simple-examples.tgz
- Args:
- data_path: string path to the directory where simple-examples.tgz has
- been extracted.
- Returns:
- tuple (train_data, valid_data, test_data, vocabulary)
- where each of the data objects can be passed to PTBIterator.
- """
-
- train_path = os.path.join(data_path, "ptb.train.txt")
- valid_path = os.path.join(data_path, "ptb.valid.txt")
- test_path = os.path.join(data_path, "ptb.test.txt")
-
- word_to_id = build_vocab(train_path)
- train_data = _file_to_word_ids(train_path, word_to_id)
- valid_data = _file_to_word_ids(valid_path, word_to_id)
- test_data = _file_to_word_ids(test_path, word_to_id)
- vocabulary = len(word_to_id)
- return train_data, valid_data, test_data, vocabulary
-
-
-def ptb_iterator(raw_data, batch_size, num_steps, epoch_size_override=None):
- """Iterate on the raw PTB data.
-
- This generates batch_size pointers into the raw PTB data, and allows
- minibatch iteration along these pointers.
-
- Args:
- raw_data: one of the raw data outputs from ptb_raw_data.
- batch_size: int, the batch size.
- num_steps: int, the number of unrolls.
-
- Yields:
- Pairs of the batched data, each a matrix of shape [batch_size, num_steps].
- The second element of the tuple is the same data time-shifted to the
- right by one.
-
- Raises:
- ValueError: if batch_size or num_steps are too high.
- """
- raw_data = np.array(raw_data, dtype=np.int32)
-
- data_len = len(raw_data)
- batch_len = data_len // batch_size
- data = np.full([batch_size, batch_len], EOS_INDEX, dtype=np.int32)
- for i in range(batch_size):
- data[i] = raw_data[batch_len * i:batch_len * (i + 1)]
-
- if epoch_size_override:
- epoch_size = epoch_size_override
- else:
- epoch_size = (batch_len - 1) // num_steps
-
- if epoch_size == 0:
- raise ValueError("epoch_size == 0, decrease batch_size or num_steps")
-
- # print("Number of batches per epoch: %d" % epoch_size)
- for i in range(epoch_size):
- x = data[:, i * num_steps:(i + 1) * num_steps]
- y = data[:, i * num_steps + 1:(i + 1) * num_steps + 1]
- w = np.ones_like(x)
- yield (x, y, w)
diff --git a/research/maskgan/generate_samples.py b/research/maskgan/generate_samples.py
deleted file mode 100644
index d4215ebc75a074b316010eb60189bf7428dfcfc5..0000000000000000000000000000000000000000
--- a/research/maskgan/generate_samples.py
+++ /dev/null
@@ -1,281 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Generate samples from the MaskGAN.
-
-Launch command:
- python generate_samples.py
- --data_dir=/tmp/data/imdb --data_set=imdb
- --batch_size=256 --sequence_length=20 --base_directory=/tmp/imdb
- --hparams="gen_rnn_size=650,dis_rnn_size=650,gen_num_layers=2,
- gen_vd_keep_prob=1.0" --generator_model=seq2seq_vd
- --discriminator_model=seq2seq_vd --is_present_rate=0.5
- --maskgan_ckpt=/tmp/model.ckpt-45494
- --seq2seq_share_embedding=True --dis_share_embedding=True
- --attention_option=luong --mask_strategy=contiguous --baseline_method=critic
- --number_epochs=4
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from functools import partial
-import os
-# Dependency imports
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-import train_mask_gan
-from data import imdb_loader
-from data import ptb_loader
-
-# Data.
-from model_utils import helper
-from model_utils import model_utils
-
-SAMPLE_TRAIN = 'TRAIN'
-SAMPLE_VALIDATION = 'VALIDATION'
-
-## Sample Generation.
-## Binary and setup FLAGS.
-tf.app.flags.DEFINE_enum('sample_mode', 'TRAIN',
- [SAMPLE_TRAIN, SAMPLE_VALIDATION],
- 'Dataset to sample from.')
-tf.app.flags.DEFINE_string('output_path', '/tmp', 'Model output directory.')
-tf.app.flags.DEFINE_boolean(
- 'output_masked_logs', False,
- 'Whether to display for human evaluation (show masking).')
-tf.app.flags.DEFINE_integer('number_epochs', 1,
- 'The number of epochs to produce.')
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def get_iterator(data):
- """Return the data iterator."""
- if FLAGS.data_set == 'ptb':
- iterator = ptb_loader.ptb_iterator(data, FLAGS.batch_size,
- FLAGS.sequence_length,
- FLAGS.epoch_size_override)
- elif FLAGS.data_set == 'imdb':
- iterator = imdb_loader.imdb_iterator(data, FLAGS.batch_size,
- FLAGS.sequence_length)
- return iterator
-
-
-def convert_to_human_readable(id_to_word, arr, p, max_num_to_print):
- """Convert a np.array of indices into words using id_to_word dictionary.
- Return max_num_to_print results.
- """
-
- assert arr.ndim == 2
-
- samples = []
- for sequence_id in xrange(min(len(arr), max_num_to_print)):
- sample = []
- for i, index in enumerate(arr[sequence_id, :]):
- if p[sequence_id, i] == 1:
- sample.append(str(id_to_word[index]))
- else:
- sample.append('*' + str(id_to_word[index]))
- buffer_str = ' '.join(sample)
- samples.append(buffer_str)
- return samples
-
-
-def write_unmasked_log(log, id_to_word, sequence_eval):
- """Helper function for logging evaluated sequences without mask."""
- indices_arr = np.asarray(sequence_eval)
- samples = helper.convert_to_human_readable(id_to_word, indices_arr,
- FLAGS.batch_size)
- for sample in samples:
- log.write(sample + '\n')
- log.flush()
- return samples
-
-
-def write_masked_log(log, id_to_word, sequence_eval, present_eval):
- indices_arr = np.asarray(sequence_eval)
- samples = convert_to_human_readable(id_to_word, indices_arr, present_eval,
- FLAGS.batch_size)
- for sample in samples:
- log.write(sample + '\n')
- log.flush()
- return samples
-
-
-def generate_logs(sess, model, log, id_to_word, feed):
- """Impute Sequences using the model for a particular feed and send it to
- logs.
- """
- # Impute Sequences.
- [p, inputs_eval, sequence_eval] = sess.run(
- [model.present, model.inputs, model.fake_sequence], feed_dict=feed)
-
- # Add the 0th time-step for coherence.
- first_token = np.expand_dims(inputs_eval[:, 0], axis=1)
- sequence_eval = np.concatenate((first_token, sequence_eval), axis=1)
-
- # 0th token always present.
- p = np.concatenate((np.ones((FLAGS.batch_size, 1)), p), axis=1)
-
- if FLAGS.output_masked_logs:
- samples = write_masked_log(log, id_to_word, sequence_eval, p)
- else:
- samples = write_unmasked_log(log, id_to_word, sequence_eval)
- return samples
-
-
-def generate_samples(hparams, data, id_to_word, log_dir, output_file):
- """"Generate samples.
-
- Args:
- hparams: Hyperparameters for the MaskGAN.
- data: Data to evaluate.
- id_to_word: Dictionary of indices to words.
- log_dir: Log directory.
- output_file: Output file for the samples.
- """
- # Boolean indicating operational mode.
- is_training = False
-
- # Set a random seed to keep fixed mask.
- np.random.seed(0)
-
- with tf.Graph().as_default():
- # Construct the model.
- model = train_mask_gan.create_MaskGAN(hparams, is_training)
-
- ## Retrieve the initial savers.
- init_savers = model_utils.retrieve_init_savers(hparams)
-
- ## Initial saver function to supervisor.
- init_fn = partial(model_utils.init_fn, init_savers)
-
- is_chief = FLAGS.task == 0
-
- # Create the supervisor. It will take care of initialization, summaries,
- # checkpoints, and recovery.
- sv = tf.Supervisor(
- logdir=log_dir,
- is_chief=is_chief,
- saver=model.saver,
- global_step=model.global_step,
- recovery_wait_secs=30,
- summary_op=None,
- init_fn=init_fn)
-
- # Get an initialized, and possibly recovered session. Launch the
- # services: Checkpointing, Summaries, step counting.
- #
- # When multiple replicas of this program are running the services are
- # only launched by the 'chief' replica.
- with sv.managed_session(
- FLAGS.master, start_standard_services=False) as sess:
-
- # Generator statefulness over the epoch.
- [gen_initial_state_eval, fake_gen_initial_state_eval] = sess.run(
- [model.eval_initial_state, model.fake_gen_initial_state])
-
- for n in xrange(FLAGS.number_epochs):
- print('Epoch number: %d' % n)
- # print('Percent done: %.2f' % float(n) / float(FLAGS.number_epochs))
- iterator = get_iterator(data)
- for x, y, _ in iterator:
- if FLAGS.eval_language_model:
- is_present_rate = 0.
- else:
- is_present_rate = FLAGS.is_present_rate
- tf.logging.info(
- 'Evaluating on is_present_rate=%.3f.' % is_present_rate)
-
- model_utils.assign_percent_real(sess, model.percent_real_update,
- model.new_rate, is_present_rate)
-
- # Randomly mask out tokens.
- p = model_utils.generate_mask()
-
- eval_feed = {model.inputs: x, model.targets: y, model.present: p}
-
- if FLAGS.data_set == 'ptb':
- # Statefulness for *evaluation* Generator.
- for i, (c, h) in enumerate(model.eval_initial_state):
- eval_feed[c] = gen_initial_state_eval[i].c
- eval_feed[h] = gen_initial_state_eval[i].h
-
- # Statefulness for the Generator.
- for i, (c, h) in enumerate(model.fake_gen_initial_state):
- eval_feed[c] = fake_gen_initial_state_eval[i].c
- eval_feed[h] = fake_gen_initial_state_eval[i].h
-
- [gen_initial_state_eval, fake_gen_initial_state_eval, _] = sess.run(
- [
- model.eval_final_state, model.fake_gen_final_state,
- model.global_step
- ],
- feed_dict=eval_feed)
-
- generate_logs(sess, model, output_file, id_to_word, eval_feed)
- output_file.close()
- print('Closing output_file.')
- return
-
-
-def main(_):
- hparams = train_mask_gan.create_hparams()
- log_dir = FLAGS.base_directory
-
- tf.gfile.MakeDirs(FLAGS.output_path)
- output_file = tf.gfile.GFile(
- os.path.join(FLAGS.output_path, 'reviews.txt'), mode='w')
-
- # Load data set.
- if FLAGS.data_set == 'ptb':
- raw_data = ptb_loader.ptb_raw_data(FLAGS.data_dir)
- train_data, valid_data, _, _ = raw_data
- elif FLAGS.data_set == 'imdb':
- raw_data = imdb_loader.imdb_raw_data(FLAGS.data_dir)
- train_data, valid_data = raw_data
- else:
- raise NotImplementedError
-
- # Generating more data on train set.
- if FLAGS.sample_mode == SAMPLE_TRAIN:
- data_set = train_data
- elif FLAGS.sample_mode == SAMPLE_VALIDATION:
- data_set = valid_data
- else:
- raise NotImplementedError
-
- # Dictionary and reverse dictionry.
- if FLAGS.data_set == 'ptb':
- word_to_id = ptb_loader.build_vocab(
- os.path.join(FLAGS.data_dir, 'ptb.train.txt'))
- elif FLAGS.data_set == 'imdb':
- word_to_id = imdb_loader.build_vocab(
- os.path.join(FLAGS.data_dir, 'vocab.txt'))
- id_to_word = {v: k for k, v in word_to_id.iteritems()}
-
- FLAGS.vocab_size = len(id_to_word)
- print('Vocab size: %d' % FLAGS.vocab_size)
-
- generate_samples(hparams, data_set, id_to_word, log_dir, output_file)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/maskgan/losses/__init__.py b/research/maskgan/losses/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/maskgan/losses/losses.py b/research/maskgan/losses/losses.py
deleted file mode 100644
index 38d0e7b4d13cfae9652d8c70f08bfba5c478e150..0000000000000000000000000000000000000000
--- a/research/maskgan/losses/losses.py
+++ /dev/null
@@ -1,186 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Losses for Generator and Discriminator."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-
-def discriminator_loss(predictions, labels, missing_tokens):
- """Discriminator loss based on predictions and labels.
-
- Args:
- predictions: Discriminator linear predictions Tensor of shape [batch_size,
- sequence_length]
- labels: Labels for predictions, Tensor of shape [batch_size,
- sequence_length]
- missing_tokens: Indicator for the missing tokens. Evaluate the loss only
- on the tokens that were missing.
-
- Returns:
- loss: Scalar tf.float32 loss.
-
- """
- loss = tf.losses.sigmoid_cross_entropy(labels,
- predictions,
- weights=missing_tokens)
- loss = tf.Print(
- loss, [loss, labels, missing_tokens],
- message='loss, labels, missing_tokens',
- summarize=25,
- first_n=25)
- return loss
-
-
-def cross_entropy_loss_matrix(gen_labels, gen_logits):
- """Computes the cross entropy loss for G.
-
- Args:
- gen_labels: Labels for the correct token.
- gen_logits: Generator logits.
-
- Returns:
- loss_matrix: Loss matrix of shape [batch_size, sequence_length].
- """
- cross_entropy_loss = tf.nn.sparse_softmax_cross_entropy_with_logits(
- labels=gen_labels, logits=gen_logits)
- return cross_entropy_loss
-
-
-def GAN_loss_matrix(dis_predictions):
- """Computes the cross entropy loss for G.
-
- Args:
- dis_predictions: Discriminator predictions.
-
- Returns:
- loss_matrix: Loss matrix of shape [batch_size, sequence_length].
- """
- eps = tf.constant(1e-7, tf.float32)
- gan_loss_matrix = -tf.log(dis_predictions + eps)
- return gan_loss_matrix
-
-
-def generator_GAN_loss(predictions):
- """Generator GAN loss based on Discriminator predictions."""
- return -tf.log(tf.reduce_mean(predictions))
-
-
-def generator_blended_forward_loss(gen_logits, gen_labels, dis_predictions,
- is_real_input):
- """Computes the masked-loss for G. This will be a blend of cross-entropy
- loss where the true label is known and GAN loss where the true label has been
- masked.
-
- Args:
- gen_logits: Generator logits.
- gen_labels: Labels for the correct token.
- dis_predictions: Discriminator predictions.
- is_real_input: Tensor indicating whether the label is present.
-
- Returns:
- loss: Scalar tf.float32 total loss.
- """
- cross_entropy_loss = tf.nn.sparse_softmax_cross_entropy_with_logits(
- labels=gen_labels, logits=gen_logits)
- gan_loss = -tf.log(dis_predictions)
- loss_matrix = tf.where(is_real_input, cross_entropy_loss, gan_loss)
- return tf.reduce_mean(loss_matrix)
-
-
-def wasserstein_generator_loss(gen_logits, gen_labels, dis_values,
- is_real_input):
- """Computes the masked-loss for G. This will be a blend of cross-entropy
- loss where the true label is known and GAN loss where the true label is
- missing.
-
- Args:
- gen_logits: Generator logits.
- gen_labels: Labels for the correct token.
- dis_values: Discriminator values Tensor of shape [batch_size,
- sequence_length].
- is_real_input: Tensor indicating whether the label is present.
-
- Returns:
- loss: Scalar tf.float32 total loss.
- """
- cross_entropy_loss = tf.nn.sparse_softmax_cross_entropy_with_logits(
- labels=gen_labels, logits=gen_logits)
- # Maximize the dis_values (minimize the negative)
- gan_loss = -dis_values
- loss_matrix = tf.where(is_real_input, cross_entropy_loss, gan_loss)
- loss = tf.reduce_mean(loss_matrix)
- return loss
-
-
-def wasserstein_discriminator_loss(real_values, fake_values):
- """Wasserstein discriminator loss.
-
- Args:
- real_values: Value given by the Wasserstein Discriminator to real data.
- fake_values: Value given by the Wasserstein Discriminator to fake data.
-
- Returns:
- loss: Scalar tf.float32 loss.
-
- """
- real_avg = tf.reduce_mean(real_values)
- fake_avg = tf.reduce_mean(fake_values)
-
- wasserstein_loss = real_avg - fake_avg
- return wasserstein_loss
-
-
-def wasserstein_discriminator_loss_intrabatch(values, is_real_input):
- """Wasserstein discriminator loss. This is an odd variant where the value
- difference is between the real tokens and the fake tokens within a single
- batch.
-
- Args:
- values: Value given by the Wasserstein Discriminator of shape [batch_size,
- sequence_length] to an imputed batch (real and fake).
- is_real_input: tf.bool Tensor of shape [batch_size, sequence_length]. If
- true, it indicates that the label is known.
-
- Returns:
- wasserstein_loss: Scalar tf.float32 loss.
-
- """
- zero_tensor = tf.constant(0., dtype=tf.float32, shape=[])
-
- present = tf.cast(is_real_input, tf.float32)
- missing = tf.cast(1 - present, tf.float32)
-
- # Counts for real and fake tokens.
- real_count = tf.reduce_sum(present)
- fake_count = tf.reduce_sum(missing)
-
- # Averages for real and fake token values.
- real = tf.mul(values, present)
- fake = tf.mul(values, missing)
- real_avg = tf.reduce_sum(real) / real_count
- fake_avg = tf.reduce_sum(fake) / fake_count
-
- # If there are no real or fake entries in the batch, we assign an average
- # value of zero.
- real_avg = tf.where(tf.equal(real_count, 0), zero_tensor, real_avg)
- fake_avg = tf.where(tf.equal(fake_count, 0), zero_tensor, fake_avg)
-
- wasserstein_loss = real_avg - fake_avg
- return wasserstein_loss
diff --git a/research/maskgan/model_utils/__init__.py b/research/maskgan/model_utils/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/maskgan/model_utils/helper.py b/research/maskgan/model_utils/helper.py
deleted file mode 100644
index 36115b484a007cda715b038e5cf52cbdd0b072ba..0000000000000000000000000000000000000000
--- a/research/maskgan/model_utils/helper.py
+++ /dev/null
@@ -1,158 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Random helper functions for converting between indices and one-hot encodings
-as well as printing/logging helpers.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-
-def variable_summaries(var, name):
- """Attach a lot of summaries to a Tensor."""
- mean = tf.reduce_mean(var)
- tf.summary.scalar('mean/' + name, mean)
- with tf.name_scope('stddev'):
- stddev = tf.sqrt(tf.reduce_sum(tf.square(var - mean)))
- tf.summary.scalar('sttdev/' + name, stddev)
- tf.summary.scalar('max/' + name, tf.reduce_max(var))
- tf.summary.scalar('min/' + name, tf.reduce_min(var))
- tf.summary.histogram(name, var)
-
-
-def zip_seq_pred_crossent(id_to_word, sequences, predictions, cross_entropy):
- """Zip together the sequences, predictions, cross entropy."""
- indices = convert_to_indices(sequences)
-
- batch_of_metrics = []
-
- for ind_batch, pred_batch, crossent_batch in zip(indices, predictions,
- cross_entropy):
- metrics = []
-
- for index, pred, crossent in zip(ind_batch, pred_batch, crossent_batch):
- metrics.append([str(id_to_word[index]), pred, crossent])
-
- batch_of_metrics.append(metrics)
- return batch_of_metrics
-
-
-def print_and_log(log, id_to_word, sequence_eval, max_num_to_print=5):
- """Helper function for printing and logging evaluated sequences."""
- indices_eval = convert_to_indices(sequence_eval)
- indices_arr = np.asarray(indices_eval)
- samples = convert_to_human_readable(id_to_word, indices_arr, max_num_to_print)
-
- for i, sample in enumerate(samples):
- print('Sample', i, '. ', sample)
- log.write('\nSample ' + str(i) + '. ' + sample)
- log.write('\n')
- print('\n')
- log.flush()
-
-
-def convert_to_human_readable(id_to_word, arr, max_num_to_print):
- """Convert a np.array of indices into words using id_to_word dictionary.
- Return max_num_to_print results.
- """
- assert arr.ndim == 2
-
- samples = []
- for sequence_id in xrange(min(len(arr), max_num_to_print)):
- buffer_str = ' '.join(
- [str(id_to_word[index]) for index in arr[sequence_id, :]])
- samples.append(buffer_str)
- return samples
-
-
-def index_to_vocab_array(indices, vocab_size, sequence_length):
- """Convert the indices into an array with vocab_size one-hot encoding."""
-
- # Extract properties of the indices.
- num_batches = len(indices)
- shape = list(indices.shape)
- shape.append(vocab_size)
-
- # Construct the vocab_size array.
- new_arr = np.zeros(shape)
-
- for n in xrange(num_batches):
- indices_batch = indices[n]
- new_arr_batch = new_arr[n]
-
- # We map all indices greater than the vocabulary size to an unknown
- # character.
- indices_batch = np.where(indices_batch < vocab_size, indices_batch,
- vocab_size - 1)
-
- # Convert indices to vocab_size dimensions.
- new_arr_batch[np.arange(sequence_length), indices_batch] = 1
- return new_arr
-
-
-def convert_to_indices(sequences):
- """Convert a list of size [batch_size, sequence_length, vocab_size] to
- a list of size [batch_size, sequence_length] where the vocab element is
- denoted by the index.
- """
- batch_of_indices = []
-
- for sequence in sequences:
- indices = []
- for embedding in sequence:
- indices.append(np.argmax(embedding))
- batch_of_indices.append(indices)
- return batch_of_indices
-
-
-def convert_and_zip(id_to_word, sequences, predictions):
- """Helper function for printing or logging. Retrieves list of sequences
- and predictions and zips them together.
- """
- indices = convert_to_indices(sequences)
-
- batch_of_indices_predictions = []
-
- for index_batch, pred_batch in zip(indices, predictions):
- indices_predictions = []
-
- for index, pred in zip(index_batch, pred_batch):
- indices_predictions.append([str(id_to_word[index]), pred])
- batch_of_indices_predictions.append(indices_predictions)
- return batch_of_indices_predictions
-
-
-def recursive_length(item):
- """Recursively determine the total number of elements in nested list."""
- if type(item) == list:
- return sum(recursive_length(subitem) for subitem in item)
- else:
- return 1.
-
-
-def percent_correct(real_sequence, fake_sequences):
- """Determine the percent of tokens correctly generated within a batch."""
- identical = 0.
- for fake_sequence in fake_sequences:
- for real, fake in zip(real_sequence, fake_sequence):
- if real == fake:
- identical += 1.
- return identical / recursive_length(fake_sequences)
diff --git a/research/maskgan/model_utils/model_construction.py b/research/maskgan/model_utils/model_construction.py
deleted file mode 100644
index 8dfa1df343984d903ace5984a90c36cc0b67dbe3..0000000000000000000000000000000000000000
--- a/research/maskgan/model_utils/model_construction.py
+++ /dev/null
@@ -1,234 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Model construction."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-# Dependency imports
-
-import tensorflow as tf
-from models import bidirectional
-from models import bidirectional_vd
-
-from models import bidirectional_zaremba
-from models import cnn
-from models import critic_vd
-from models import feedforward
-from models import rnn
-from models import rnn_nas
-from models import rnn_vd
-from models import rnn_zaremba
-from models import seq2seq
-from models import seq2seq_nas
-from models import seq2seq_vd
-from models import seq2seq_zaremba
-
-FLAGS = tf.app.flags.FLAGS
-
-
-# TODO(adai): IMDB labels placeholder to model.
-def create_generator(hparams,
- inputs,
- targets,
- present,
- is_training,
- is_validating,
- reuse=None):
- """Create the Generator model specified by the FLAGS and hparams.
-
- Args;
- hparams: Hyperparameters for the MaskGAN.
- inputs: tf.int32 Tensor of the sequence input of shape [batch_size,
- sequence_length].
- present: tf.bool Tensor indicating the presence or absence of the token
- of shape [batch_size, sequence_length].
- is_training: Whether the model is training.
- is_validating: Whether the model is being run in validation mode for
- calculating the perplexity.
- reuse (Optional): Whether to reuse the model.
-
- Returns:
- Tuple of the (sequence, logits, log_probs) of the Generator. Sequence
- and logits have shape [batch_size, sequence_length, vocab_size]. The
- log_probs will have shape [batch_size, sequence_length]. Log_probs
- corresponds to the log probability of selecting the words.
- """
- if FLAGS.generator_model == 'rnn':
- (sequence, logits, log_probs, initial_state, final_state) = rnn.generator(
- hparams,
- inputs,
- targets,
- present,
- is_training=is_training,
- is_validating=is_validating,
- reuse=reuse)
- elif FLAGS.generator_model == 'rnn_zaremba':
- (sequence, logits, log_probs, initial_state,
- final_state) = rnn_zaremba.generator(
- hparams,
- inputs,
- targets,
- present,
- is_training=is_training,
- is_validating=is_validating,
- reuse=reuse)
- elif FLAGS.generator_model == 'seq2seq':
- (sequence, logits, log_probs, initial_state,
- final_state) = seq2seq.generator(
- hparams,
- inputs,
- targets,
- present,
- is_training=is_training,
- is_validating=is_validating,
- reuse=reuse)
- elif FLAGS.generator_model == 'seq2seq_zaremba':
- (sequence, logits, log_probs, initial_state,
- final_state) = seq2seq_zaremba.generator(
- hparams,
- inputs,
- targets,
- present,
- is_training=is_training,
- is_validating=is_validating,
- reuse=reuse)
- elif FLAGS.generator_model == 'rnn_nas':
- (sequence, logits, log_probs, initial_state,
- final_state) = rnn_nas.generator(
- hparams,
- inputs,
- targets,
- present,
- is_training=is_training,
- is_validating=is_validating,
- reuse=reuse)
- elif FLAGS.generator_model == 'seq2seq_nas':
- (sequence, logits, log_probs, initial_state,
- final_state) = seq2seq_nas.generator(
- hparams,
- inputs,
- targets,
- present,
- is_training=is_training,
- is_validating=is_validating,
- reuse=reuse)
- elif FLAGS.generator_model == 'seq2seq_vd':
- (sequence, logits, log_probs, initial_state, final_state,
- encoder_states) = seq2seq_vd.generator(
- hparams,
- inputs,
- targets,
- present,
- is_training=is_training,
- is_validating=is_validating,
- reuse=reuse)
- else:
- raise NotImplementedError
- return (sequence, logits, log_probs, initial_state, final_state,
- encoder_states)
-
-
-def create_discriminator(hparams,
- sequence,
- is_training,
- reuse=None,
- initial_state=None,
- inputs=None,
- present=None):
- """Create the Discriminator model specified by the FLAGS and hparams.
-
- Args:
- hparams: Hyperparameters for the MaskGAN.
- sequence: tf.int32 Tensor sequence of shape [batch_size, sequence_length]
- is_training: Whether the model is training.
- reuse (Optional): Whether to reuse the model.
-
- Returns:
- predictions: tf.float32 Tensor of predictions of shape [batch_size,
- sequence_length]
- """
- if FLAGS.discriminator_model == 'cnn':
- predictions = cnn.discriminator(
- hparams, sequence, is_training=is_training, reuse=reuse)
- elif FLAGS.discriminator_model == 'fnn':
- predictions = feedforward.discriminator(
- hparams, sequence, is_training=is_training, reuse=reuse)
- elif FLAGS.discriminator_model == 'rnn':
- predictions = rnn.discriminator(
- hparams, sequence, is_training=is_training, reuse=reuse)
- elif FLAGS.discriminator_model == 'bidirectional':
- predictions = bidirectional.discriminator(
- hparams, sequence, is_training=is_training, reuse=reuse)
- elif FLAGS.discriminator_model == 'bidirectional_zaremba':
- predictions = bidirectional_zaremba.discriminator(
- hparams, sequence, is_training=is_training, reuse=reuse)
- elif FLAGS.discriminator_model == 'seq2seq_vd':
- predictions = seq2seq_vd.discriminator(
- hparams,
- inputs,
- present,
- sequence,
- is_training=is_training,
- reuse=reuse)
- elif FLAGS.discriminator_model == 'rnn_zaremba':
- predictions = rnn_zaremba.discriminator(
- hparams, sequence, is_training=is_training, reuse=reuse)
- elif FLAGS.discriminator_model == 'rnn_nas':
- predictions = rnn_nas.discriminator(
- hparams, sequence, is_training=is_training, reuse=reuse)
- elif FLAGS.discriminator_model == 'rnn_vd':
- predictions = rnn_vd.discriminator(
- hparams,
- sequence,
- is_training=is_training,
- reuse=reuse,
- initial_state=initial_state)
- elif FLAGS.discriminator_model == 'bidirectional_vd':
- predictions = bidirectional_vd.discriminator(
- hparams,
- sequence,
- is_training=is_training,
- reuse=reuse,
- initial_state=initial_state)
- else:
- raise NotImplementedError
- return predictions
-
-
-def create_critic(hparams, sequence, is_training, reuse=None):
- """Create the Critic model specified by the FLAGS and hparams.
-
- Args:
- hparams: Hyperparameters for the MaskGAN.
- sequence: tf.int32 Tensor sequence of shape [batch_size, sequence_length]
- is_training: Whether the model is training.
- reuse (Optional): Whether to reuse the model.
-
- Returns:
- values: tf.float32 Tensor of predictions of shape [batch_size,
- sequence_length]
- """
- if FLAGS.baseline_method == 'critic':
- if FLAGS.discriminator_model == 'seq2seq_vd':
- values = critic_vd.critic_seq2seq_vd_derivative(
- hparams, sequence, is_training, reuse=reuse)
- else:
- raise NotImplementedError
- else:
- raise NotImplementedError
- return values
diff --git a/research/maskgan/model_utils/model_losses.py b/research/maskgan/model_utils/model_losses.py
deleted file mode 100644
index c8f337dc48b4f1efb1cf8604327376ddaa9994ea..0000000000000000000000000000000000000000
--- a/research/maskgan/model_utils/model_losses.py
+++ /dev/null
@@ -1,327 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Model loss construction."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-# Dependency imports
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-# Useful for REINFORCE baseline.
-from losses import losses
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def create_dis_loss(fake_predictions, real_predictions, targets_present):
- """Compute Discriminator loss across real/fake."""
-
- missing = tf.cast(targets_present, tf.int32)
- missing = 1 - missing
- missing = tf.cast(missing, tf.bool)
-
- real_labels = tf.ones([FLAGS.batch_size, FLAGS.sequence_length])
- dis_loss_real = tf.losses.sigmoid_cross_entropy(
- real_labels, real_predictions, weights=missing)
- dis_loss_fake = tf.losses.sigmoid_cross_entropy(
- targets_present, fake_predictions, weights=missing)
-
- dis_loss = (dis_loss_fake + dis_loss_real) / 2.
- return dis_loss, dis_loss_fake, dis_loss_real
-
-
-def create_critic_loss(cumulative_rewards, estimated_values, present):
- """Compute Critic loss in estimating the value function. This should be an
- estimate only for the missing elements."""
- missing = tf.cast(present, tf.int32)
- missing = 1 - missing
- missing = tf.cast(missing, tf.bool)
-
- loss = tf.losses.mean_squared_error(
- labels=cumulative_rewards, predictions=estimated_values, weights=missing)
- return loss
-
-
-def create_masked_cross_entropy_loss(targets, present, logits):
- """Calculate the cross entropy loss matrices for the masked tokens."""
- cross_entropy_losses = losses.cross_entropy_loss_matrix(targets, logits)
-
- # Zeros matrix.
- zeros_losses = tf.zeros(
- shape=[FLAGS.batch_size, FLAGS.sequence_length], dtype=tf.float32)
-
- missing_ce_loss = tf.where(present, zeros_losses, cross_entropy_losses)
-
- return missing_ce_loss
-
-
-def calculate_reinforce_objective(hparams,
- log_probs,
- dis_predictions,
- present,
- estimated_values=None):
- """Calculate the REINFORCE objectives. The REINFORCE objective should
- only be on the tokens that were missing. Specifically, the final Generator
- reward should be based on the Discriminator predictions on missing tokens.
- The log probaibilities should be only for missing tokens and the baseline
- should be calculated only on the missing tokens.
-
- For this model, we optimize the reward is the log of the *conditional*
- probability the Discriminator assigns to the distribution. Specifically, for
- a Discriminator D which outputs probability of real, given the past context,
-
- r_t = log D(x_t|x_0,x_1,...x_{t-1})
-
- And the policy for Generator G is the log-probability of taking action x2
- given the past context.
-
-
- Args:
- hparams: MaskGAN hyperparameters.
- log_probs: tf.float32 Tensor of log probailities of the tokens selected by
- the Generator. Shape [batch_size, sequence_length].
- dis_predictions: tf.float32 Tensor of the predictions from the
- Discriminator. Shape [batch_size, sequence_length].
- present: tf.bool Tensor indicating which tokens are present. Shape
- [batch_size, sequence_length].
- estimated_values: tf.float32 Tensor of estimated state values of tokens.
- Shape [batch_size, sequence_length]
-
- Returns:
- final_gen_objective: Final REINFORCE objective for the sequence.
- rewards: tf.float32 Tensor of rewards for sequence of shape [batch_size,
- sequence_length]
- advantages: tf.float32 Tensor of advantages for sequence of shape
- [batch_size, sequence_length]
- baselines: tf.float32 Tensor of baselines for sequence of shape
- [batch_size, sequence_length]
- maintain_averages_op: ExponentialMovingAverage apply average op to
- maintain the baseline.
- """
- # Final Generator objective.
- final_gen_objective = 0.
- gamma = hparams.rl_discount_rate
- eps = 1e-7
-
- # Generator rewards are log-probabilities.
- eps = tf.constant(1e-7, tf.float32)
- dis_predictions = tf.nn.sigmoid(dis_predictions)
- rewards = tf.log(dis_predictions + eps)
-
- # Apply only for missing elements.
- zeros = tf.zeros_like(present, dtype=tf.float32)
- log_probs = tf.where(present, zeros, log_probs)
- rewards = tf.where(present, zeros, rewards)
-
- # Unstack Tensors into lists.
- rewards_list = tf.unstack(rewards, axis=1)
- log_probs_list = tf.unstack(log_probs, axis=1)
- missing = 1. - tf.cast(present, tf.float32)
- missing_list = tf.unstack(missing, axis=1)
-
- # Cumulative Discounted Returns. The true value function V*(s).
- cumulative_rewards = []
- for t in xrange(FLAGS.sequence_length):
- cum_value = tf.zeros(shape=[FLAGS.batch_size])
- for s in xrange(t, FLAGS.sequence_length):
- cum_value += missing_list[s] * np.power(gamma, (s - t)) * rewards_list[s]
- cumulative_rewards.append(cum_value)
- cumulative_rewards = tf.stack(cumulative_rewards, axis=1)
-
- ## REINFORCE with different baselines.
- # We create a separate critic functionality for the Discriminator. This
- # will need to operate unidirectionally and it may take in the past context.
- if FLAGS.baseline_method == 'critic':
-
- # Critic loss calculated from the estimated value function \hat{V}(s)
- # versus the true value function V*(s).
- critic_loss = create_critic_loss(cumulative_rewards, estimated_values,
- present)
-
- # Baselines are coming from the critic's estimated state values.
- baselines = tf.unstack(estimated_values, axis=1)
-
- ## Calculate the Advantages, A(s,a) = Q(s,a) - \hat{V}(s).
- advantages = []
- for t in xrange(FLAGS.sequence_length):
- log_probability = log_probs_list[t]
- cum_advantage = tf.zeros(shape=[FLAGS.batch_size])
-
- for s in xrange(t, FLAGS.sequence_length):
- cum_advantage += missing_list[s] * np.power(gamma,
- (s - t)) * rewards_list[s]
- cum_advantage -= baselines[t]
- # Clip advantages.
- cum_advantage = tf.clip_by_value(cum_advantage, -FLAGS.advantage_clipping,
- FLAGS.advantage_clipping)
- advantages.append(missing_list[t] * cum_advantage)
- final_gen_objective += tf.multiply(
- log_probability, missing_list[t] * tf.stop_gradient(cum_advantage))
-
- maintain_averages_op = None
- baselines = tf.stack(baselines, axis=1)
- advantages = tf.stack(advantages, axis=1)
-
- # Split the batch into half. Use half for MC estimates for REINFORCE.
- # Use the other half to establish a baseline.
- elif FLAGS.baseline_method == 'dis_batch':
- # TODO(liamfedus): Recheck.
- [rewards_half, baseline_half] = tf.split(
- rewards, num_or_size_splits=2, axis=0)
- [log_probs_half, _] = tf.split(log_probs, num_or_size_splits=2, axis=0)
- [reward_present_half, baseline_present_half] = tf.split(
- present, num_or_size_splits=2, axis=0)
-
- # Unstack to lists.
- baseline_list = tf.unstack(baseline_half, axis=1)
- baseline_missing = 1. - tf.cast(baseline_present_half, tf.float32)
- baseline_missing_list = tf.unstack(baseline_missing, axis=1)
-
- baselines = []
- for t in xrange(FLAGS.sequence_length):
- # Calculate baseline only for missing tokens.
- num_missing = tf.reduce_sum(baseline_missing_list[t])
-
- avg_baseline = tf.reduce_sum(
- baseline_missing_list[t] * baseline_list[t], keep_dims=True) / (
- num_missing + eps)
- baseline = tf.tile(avg_baseline, multiples=[FLAGS.batch_size / 2])
- baselines.append(baseline)
-
- # Unstack to lists.
- rewards_list = tf.unstack(rewards_half, axis=1)
- log_probs_list = tf.unstack(log_probs_half, axis=1)
- reward_missing = 1. - tf.cast(reward_present_half, tf.float32)
- reward_missing_list = tf.unstack(reward_missing, axis=1)
-
- ## Calculate the Advantages, A(s,a) = Q(s,a) - \hat{V}(s).
- advantages = []
- for t in xrange(FLAGS.sequence_length):
- log_probability = log_probs_list[t]
- cum_advantage = tf.zeros(shape=[FLAGS.batch_size / 2])
-
- for s in xrange(t, FLAGS.sequence_length):
- cum_advantage += reward_missing_list[s] * np.power(gamma, (s - t)) * (
- rewards_list[s] - baselines[s])
- # Clip advantages.
- cum_advantage = tf.clip_by_value(cum_advantage, -FLAGS.advantage_clipping,
- FLAGS.advantage_clipping)
- advantages.append(reward_missing_list[t] * cum_advantage)
- final_gen_objective += tf.multiply(
- log_probability,
- reward_missing_list[t] * tf.stop_gradient(cum_advantage))
-
- # Cumulative Discounted Returns. The true value function V*(s).
- cumulative_rewards = []
- for t in xrange(FLAGS.sequence_length):
- cum_value = tf.zeros(shape=[FLAGS.batch_size / 2])
- for s in xrange(t, FLAGS.sequence_length):
- cum_value += reward_missing_list[s] * np.power(gamma, (
- s - t)) * rewards_list[s]
- cumulative_rewards.append(cum_value)
- cumulative_rewards = tf.stack(cumulative_rewards, axis=1)
-
- rewards = rewards_half
- critic_loss = None
- maintain_averages_op = None
- baselines = tf.stack(baselines, axis=1)
- advantages = tf.stack(advantages, axis=1)
-
- # Exponential Moving Average baseline.
- elif FLAGS.baseline_method == 'ema':
- # TODO(liamfedus): Recheck.
- # Lists of rewards and Log probabilities of the actions taken only for
- # missing tokens.
- ema = tf.train.ExponentialMovingAverage(decay=hparams.baseline_decay)
- maintain_averages_op = ema.apply(rewards_list)
-
- baselines = []
- for r in rewards_list:
- baselines.append(ema.average(r))
-
- ## Calculate the Advantages, A(s,a) = Q(s,a) - \hat{V}(s).
- advantages = []
- for t in xrange(FLAGS.sequence_length):
- log_probability = log_probs_list[t]
-
- # Calculate the forward advantage only on the missing tokens.
- cum_advantage = tf.zeros(shape=[FLAGS.batch_size])
- for s in xrange(t, FLAGS.sequence_length):
- cum_advantage += missing_list[s] * np.power(gamma, (s - t)) * (
- rewards_list[s] - baselines[s])
- # Clip advantages.
- cum_advantage = tf.clip_by_value(cum_advantage, -FLAGS.advantage_clipping,
- FLAGS.advantage_clipping)
- advantages.append(missing_list[t] * cum_advantage)
- final_gen_objective += tf.multiply(
- log_probability, missing_list[t] * tf.stop_gradient(cum_advantage))
-
- critic_loss = None
- baselines = tf.stack(baselines, axis=1)
- advantages = tf.stack(advantages, axis=1)
-
- elif FLAGS.baseline_method is None:
- num_missing = tf.reduce_sum(missing)
- final_gen_objective += tf.reduce_sum(rewards) / (num_missing + eps)
- baselines = tf.zeros_like(rewards)
- critic_loss = None
- maintain_averages_op = None
- advantages = cumulative_rewards
-
- else:
- raise NotImplementedError
-
- return [
- final_gen_objective, log_probs, rewards, advantages, baselines,
- maintain_averages_op, critic_loss, cumulative_rewards
- ]
-
-
-def calculate_log_perplexity(logits, targets, present):
- """Calculate the average log perplexity per *missing* token.
-
- Args:
- logits: tf.float32 Tensor of the logits of shape [batch_size,
- sequence_length, vocab_size].
- targets: tf.int32 Tensor of the sequence target of shape [batch_size,
- sequence_length].
- present: tf.bool Tensor indicating the presence or absence of the token
- of shape [batch_size, sequence_length].
-
- Returns:
- avg_log_perplexity: Scalar indicating the average log perplexity per
- missing token in the batch.
- """
- # logits = tf.Print(logits, [logits], message='logits:', summarize=50)
- # targets = tf.Print(targets, [targets], message='targets:', summarize=50)
- eps = 1e-12
- logits = tf.reshape(logits, [-1, FLAGS.vocab_size])
-
- # Only calculate log-perplexity on missing tokens.
- weights = tf.cast(present, tf.float32)
- weights = 1. - weights
- weights = tf.reshape(weights, [-1])
- num_missing = tf.reduce_sum(weights)
-
- log_perplexity = tf.contrib.legacy_seq2seq.sequence_loss_by_example(
- [logits], [tf.reshape(targets, [-1])], [weights])
-
- avg_log_perplexity = tf.reduce_sum(log_perplexity) / (num_missing + eps)
- return avg_log_perplexity
diff --git a/research/maskgan/model_utils/model_optimization.py b/research/maskgan/model_utils/model_optimization.py
deleted file mode 100644
index caae271fe8bed390f032763972a43312f7a8ce9b..0000000000000000000000000000000000000000
--- a/research/maskgan/model_utils/model_optimization.py
+++ /dev/null
@@ -1,194 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Model optimization."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-# Dependency imports
-
-import tensorflow as tf
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def create_dis_pretrain_op(hparams, dis_loss, global_step):
- """Create a train op for pretraining."""
- with tf.name_scope('pretrain_generator'):
- optimizer = tf.train.AdamOptimizer(hparams.dis_pretrain_learning_rate)
- dis_vars = [
- v for v in tf.trainable_variables() if v.op.name.startswith('dis')
- ]
- if FLAGS.dis_update_share_embedding and FLAGS.dis_share_embedding:
- shared_embedding = [
- v for v in tf.trainable_variables()
- if v.op.name == 'gen/decoder/rnn/embedding'
- ][0]
- dis_vars.append(shared_embedding)
- dis_grads = tf.gradients(dis_loss, dis_vars)
- dis_grads_clipped, _ = tf.clip_by_global_norm(dis_grads,
- FLAGS.grad_clipping)
- dis_pretrain_op = optimizer.apply_gradients(
- zip(dis_grads_clipped, dis_vars), global_step=global_step)
- return dis_pretrain_op
-
-
-def create_gen_pretrain_op(hparams, cross_entropy_loss, global_step):
- """Create a train op for pretraining."""
- with tf.name_scope('pretrain_generator'):
- optimizer = tf.train.AdamOptimizer(hparams.gen_pretrain_learning_rate)
- gen_vars = [
- v for v in tf.trainable_variables() if v.op.name.startswith('gen')
- ]
- gen_grads = tf.gradients(cross_entropy_loss, gen_vars)
- gen_grads_clipped, _ = tf.clip_by_global_norm(gen_grads,
- FLAGS.grad_clipping)
- gen_pretrain_op = optimizer.apply_gradients(
- zip(gen_grads_clipped, gen_vars), global_step=global_step)
- return gen_pretrain_op
-
-
-def create_gen_train_op(hparams, learning_rate, gen_loss, global_step, mode):
- """Create Generator train op."""
- del hparams
- with tf.name_scope('train_generator'):
- if FLAGS.generator_optimizer == 'sgd':
- gen_optimizer = tf.train.GradientDescentOptimizer(learning_rate)
- elif FLAGS.generator_optimizer == 'adam':
- gen_optimizer = tf.train.AdamOptimizer(learning_rate)
- else:
- raise NotImplementedError
- gen_vars = [
- v for v in tf.trainable_variables() if v.op.name.startswith('gen')
- ]
- print('Optimizing Generator vars.')
- for v in gen_vars:
- print(v)
- if mode == 'MINIMIZE':
- gen_grads = tf.gradients(gen_loss, gen_vars)
- elif mode == 'MAXIMIZE':
- gen_grads = tf.gradients(-gen_loss, gen_vars)
- else:
- raise ValueError("Must be one of 'MINIMIZE' or 'MAXIMIZE'")
- gen_grads_clipped, _ = tf.clip_by_global_norm(gen_grads,
- FLAGS.grad_clipping)
- gen_train_op = gen_optimizer.apply_gradients(
- zip(gen_grads_clipped, gen_vars), global_step=global_step)
- return gen_train_op, gen_grads_clipped, gen_vars
-
-
-def create_reinforce_gen_train_op(hparams, learning_rate, final_gen_reward,
- averages_op, global_step):
- """Create the Generator train_op when using REINFORCE.
-
- Args:
- hparams: MaskGAN hyperparameters.
- learning_rate: tf.Variable scalar learning rate.
- final_gen_objective: Scalar final REINFORCE objective for the sequence.
- averages_op: ExponentialMovingAverage apply average op to
- maintain the baseline.
- global_step: global_step tf.Variable.
-
- Returns:
- gen_train_op: Generator training op.
- """
- del hparams
- with tf.name_scope('train_generator'):
- if FLAGS.generator_optimizer == 'sgd':
- gen_optimizer = tf.train.GradientDescentOptimizer(learning_rate)
- elif FLAGS.generator_optimizer == 'adam':
- gen_optimizer = tf.train.AdamOptimizer(learning_rate)
- else:
- raise NotImplementedError
- gen_vars = [
- v for v in tf.trainable_variables() if v.op.name.startswith('gen')
- ]
- print('\nOptimizing Generator vars:')
- for v in gen_vars:
- print(v)
-
- # Maximize reward.
- gen_grads = tf.gradients(-final_gen_reward, gen_vars)
- gen_grads_clipped, _ = tf.clip_by_global_norm(gen_grads,
- FLAGS.grad_clipping)
- maximize_op = gen_optimizer.apply_gradients(
- zip(gen_grads_clipped, gen_vars), global_step=global_step)
-
- # Group maintain averages op.
- if averages_op:
- gen_train_op = tf.group(maximize_op, averages_op)
- else:
- gen_train_op = maximize_op
-
- return [gen_train_op, gen_grads, gen_vars]
-
-
-def create_dis_train_op(hparams, dis_loss, global_step):
- """Create Discriminator train op."""
- with tf.name_scope('train_discriminator'):
- dis_optimizer = tf.train.AdamOptimizer(hparams.dis_learning_rate)
- dis_vars = [
- v for v in tf.trainable_variables() if v.op.name.startswith('dis')
- ]
- if FLAGS.dis_update_share_embedding and FLAGS.dis_share_embedding:
- shared_embedding = [
- v for v in tf.trainable_variables()
- if v.op.name == 'gen/decoder/rnn/embedding'
- ][0]
- dis_vars.append(shared_embedding)
- print('\nOptimizing Discriminator vars:')
- for v in dis_vars:
- print(v)
- dis_grads = tf.gradients(dis_loss, dis_vars)
- dis_grads_clipped, _ = tf.clip_by_global_norm(dis_grads,
- FLAGS.grad_clipping)
- dis_train_op = dis_optimizer.apply_gradients(
- zip(dis_grads_clipped, dis_vars), global_step=global_step)
- return dis_train_op, dis_grads_clipped, dis_vars
-
-
-def create_critic_train_op(hparams, critic_loss, global_step):
- """Create Discriminator train op."""
- with tf.name_scope('train_critic'):
- critic_optimizer = tf.train.AdamOptimizer(hparams.critic_learning_rate)
- output_vars = [
- v for v in tf.trainable_variables() if v.op.name.startswith('critic')
- ]
-
- if FLAGS.critic_update_dis_vars:
- if FLAGS.discriminator_model == 'bidirectional_vd':
- critic_vars = [
- v for v in tf.trainable_variables()
- if v.op.name.startswith('dis/rnn')
- ]
- elif FLAGS.discriminator_model == 'seq2seq_vd':
- critic_vars = [
- v for v in tf.trainable_variables()
- if v.op.name.startswith('dis/decoder/rnn/multi_rnn_cell')
- ]
- critic_vars.extend(output_vars)
- else:
- critic_vars = output_vars
- print('\nOptimizing Critic vars:')
- for v in critic_vars:
- print(v)
- critic_grads = tf.gradients(critic_loss, critic_vars)
- critic_grads_clipped, _ = tf.clip_by_global_norm(critic_grads,
- FLAGS.grad_clipping)
- critic_train_op = critic_optimizer.apply_gradients(
- zip(critic_grads_clipped, critic_vars), global_step=global_step)
- return critic_train_op, critic_grads_clipped, critic_vars
diff --git a/research/maskgan/model_utils/model_utils.py b/research/maskgan/model_utils/model_utils.py
deleted file mode 100644
index 0e3183582e0f17b7d4ca54450231ea9bad039e40..0000000000000000000000000000000000000000
--- a/research/maskgan/model_utils/model_utils.py
+++ /dev/null
@@ -1,291 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Model utilities."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-# Dependency imports
-import numpy as np
-
-import tensorflow as tf
-from model_utils import variable_mapping
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def generate_mask():
- """Generate the mask to be fed into the model."""
- if FLAGS.mask_strategy == 'random':
- p = np.random.choice(
- [True, False],
- size=[FLAGS.batch_size, FLAGS.sequence_length],
- p=[FLAGS.is_present_rate, 1. - FLAGS.is_present_rate])
-
- elif FLAGS.mask_strategy == 'contiguous':
- masked_length = int((1 - FLAGS.is_present_rate) * FLAGS.sequence_length) - 1
- # Determine location to start masking.
- start_mask = np.random.randint(
- 1, FLAGS.sequence_length - masked_length + 1, size=FLAGS.batch_size)
- p = np.full([FLAGS.batch_size, FLAGS.sequence_length], True, dtype=bool)
-
- # Create contiguous masked section to be False.
- for i, index in enumerate(start_mask):
- p[i, index:index + masked_length] = False
-
- else:
- raise NotImplementedError
-
- return p
-
-
-def assign_percent_real(session, percent_real_update, new_rate, current_rate):
- """Run assign operation where the we load the current_rate of percent
- real into a Tensorflow variable.
-
- Args:
- session: Current tf.Session.
- percent_real_update: tf.assign operation.
- new_rate: tf.placeholder for the new rate.
- current_rate: Percent of tokens that are currently real. Fake tokens
- are the ones being imputed by the Generator.
- """
- session.run(percent_real_update, feed_dict={new_rate: current_rate})
-
-
-def assign_learning_rate(session, lr_update, lr_placeholder, new_lr):
- """Run assign operation where the we load the current_rate of percent
- real into a Tensorflow variable.
-
- Args:
- session: Current tf.Session.
- lr_update: tf.assign operation.
- lr_placeholder: tf.placeholder for the new learning rate.
- new_lr: New learning rate to use.
- """
- session.run(lr_update, feed_dict={lr_placeholder: new_lr})
-
-
-def clip_weights(variables, c_lower, c_upper):
- """Clip a list of weights to be within a certain range.
-
- Args:
- variables: List of tf.Variable weights.
- c_lower: Lower bound for weights.
- c_upper: Upper bound for weights.
- """
- clip_ops = []
-
- for var in variables:
- clipped_var = tf.clip_by_value(var, c_lower, c_upper)
-
- clip_ops.append(tf.assign(var, clipped_var))
- return tf.group(*clip_ops)
-
-
-def retrieve_init_savers(hparams):
- """Retrieve a dictionary of all the initial savers for the models.
-
- Args:
- hparams: MaskGAN hyperparameters.
- """
- ## Dictionary of init savers.
- init_savers = {}
-
- ## Load Generator weights from MaskGAN checkpoint.
- if FLAGS.maskgan_ckpt:
- gen_vars = [
- v for v in tf.trainable_variables() if v.op.name.startswith('gen')
- ]
- init_saver = tf.train.Saver(var_list=gen_vars)
- init_savers['init_saver'] = init_saver
-
- ## Load the Discriminator weights from the MaskGAN checkpoint if
- # the weights are compatible.
- if FLAGS.discriminator_model == 'seq2seq_vd':
- dis_variable_maps = variable_mapping.dis_seq2seq_vd(hparams)
- dis_init_saver = tf.train.Saver(var_list=dis_variable_maps)
- init_savers['dis_init_saver'] = dis_init_saver
-
- ## Load weights from language model checkpoint.
- if FLAGS.language_model_ckpt_dir:
- if FLAGS.maskgan_ckpt is None:
- ## Generator Variables/Savers.
- if FLAGS.generator_model == 'rnn_nas':
- gen_variable_maps = variable_mapping.rnn_nas(hparams, model='gen')
- gen_init_saver = tf.train.Saver(var_list=gen_variable_maps)
- init_savers['gen_init_saver'] = gen_init_saver
-
- elif FLAGS.generator_model == 'seq2seq_nas':
- # Encoder.
- gen_encoder_variable_maps = variable_mapping.gen_encoder_seq2seq_nas(
- hparams)
- gen_encoder_init_saver = tf.train.Saver(
- var_list=gen_encoder_variable_maps)
- # Decoder.
- gen_decoder_variable_maps = variable_mapping.gen_decoder_seq2seq_nas(
- hparams)
- gen_decoder_init_saver = tf.train.Saver(
- var_list=gen_decoder_variable_maps)
- init_savers['gen_encoder_init_saver'] = gen_encoder_init_saver
- init_savers['gen_decoder_init_saver'] = gen_decoder_init_saver
-
- # seq2seq_vd derived from the same code base as seq2seq_zaremba.
- elif (FLAGS.generator_model == 'seq2seq_zaremba' or
- FLAGS.generator_model == 'seq2seq_vd'):
- # Encoder.
- gen_encoder_variable_maps = variable_mapping.gen_encoder_seq2seq(
- hparams)
- gen_encoder_init_saver = tf.train.Saver(
- var_list=gen_encoder_variable_maps)
- # Decoder.
- gen_decoder_variable_maps = variable_mapping.gen_decoder_seq2seq(
- hparams)
- gen_decoder_init_saver = tf.train.Saver(
- var_list=gen_decoder_variable_maps)
- init_savers['gen_encoder_init_saver'] = gen_encoder_init_saver
- init_savers['gen_decoder_init_saver'] = gen_decoder_init_saver
-
- else:
- raise NotImplementedError
-
- ## Discriminator Variables/Savers.
- if FLAGS.discriminator_model == 'rnn_nas':
- dis_variable_maps = variable_mapping.rnn_nas(hparams, model='dis')
- dis_init_saver = tf.train.Saver(var_list=dis_variable_maps)
- init_savers['dis_init_saver'] = dis_init_saver
-
- # rnn_vd derived from the same code base as rnn_zaremba.
- elif (FLAGS.discriminator_model == 'rnn_zaremba' or
- FLAGS.discriminator_model == 'rnn_vd'):
- dis_variable_maps = variable_mapping.rnn_zaremba(hparams, model='dis')
- dis_init_saver = tf.train.Saver(var_list=dis_variable_maps)
- init_savers['dis_init_saver'] = dis_init_saver
-
- elif (FLAGS.discriminator_model == 'bidirectional_zaremba' or
- FLAGS.discriminator_model == 'bidirectional_vd'):
- dis_fwd_variable_maps = variable_mapping.dis_fwd_bidirectional(hparams)
- dis_bwd_variable_maps = variable_mapping.dis_bwd_bidirectional(hparams)
- # Savers for the forward/backward Discriminator components.
- dis_fwd_init_saver = tf.train.Saver(var_list=dis_fwd_variable_maps)
- dis_bwd_init_saver = tf.train.Saver(var_list=dis_bwd_variable_maps)
- init_savers['dis_fwd_init_saver'] = dis_fwd_init_saver
- init_savers['dis_bwd_init_saver'] = dis_bwd_init_saver
-
- elif FLAGS.discriminator_model == 'cnn':
- dis_variable_maps = variable_mapping.cnn()
- dis_init_saver = tf.train.Saver(var_list=dis_variable_maps)
- init_savers['dis_init_saver'] = dis_init_saver
-
- elif FLAGS.discriminator_model == 'seq2seq_vd':
- # Encoder.
- dis_encoder_variable_maps = variable_mapping.dis_encoder_seq2seq(hparams)
- dis_encoder_init_saver = tf.train.Saver(
- var_list=dis_encoder_variable_maps)
- # Decoder.
- dis_decoder_variable_maps = variable_mapping.dis_decoder_seq2seq(hparams)
- dis_decoder_init_saver = tf.train.Saver(
- var_list=dis_decoder_variable_maps)
- init_savers['dis_encoder_init_saver'] = dis_encoder_init_saver
- init_savers['dis_decoder_init_saver'] = dis_decoder_init_saver
-
- return init_savers
-
-
-def init_fn(init_savers, sess):
- """The init_fn to be passed to the Supervisor.
-
- Args:
- init_savers: Dictionary of init_savers. 'init_saver_name': init_saver.
- sess: tf.Session.
- """
- ## Load Generator weights from MaskGAN checkpoint.
- if FLAGS.maskgan_ckpt:
- print('Restoring Generator from %s.' % FLAGS.maskgan_ckpt)
- tf.logging.info('Restoring Generator from %s.' % FLAGS.maskgan_ckpt)
- print('Asserting Generator is a seq2seq-variant.')
- tf.logging.info('Asserting Generator is a seq2seq-variant.')
- assert FLAGS.generator_model.startswith('seq2seq')
- init_saver = init_savers['init_saver']
- init_saver.restore(sess, FLAGS.maskgan_ckpt)
-
- ## Load the Discriminator weights from the MaskGAN checkpoint if
- # the weights are compatible.
- if FLAGS.discriminator_model == 'seq2seq_vd':
- print('Restoring Discriminator from %s.' % FLAGS.maskgan_ckpt)
- tf.logging.info('Restoring Discriminator from %s.' % FLAGS.maskgan_ckpt)
- dis_init_saver = init_savers['dis_init_saver']
- dis_init_saver.restore(sess, FLAGS.maskgan_ckpt)
-
- ## Load weights from language model checkpoint.
- if FLAGS.language_model_ckpt_dir:
- if FLAGS.maskgan_ckpt is None:
- ## Generator Models.
- if FLAGS.generator_model == 'rnn_nas':
- load_ckpt = tf.train.latest_checkpoint(FLAGS.language_model_ckpt_dir)
- print('Restoring Generator from %s.' % load_ckpt)
- tf.logging.info('Restoring Generator from %s.' % load_ckpt)
- gen_init_saver = init_savers['gen_init_saver']
- gen_init_saver.restore(sess, load_ckpt)
-
- elif FLAGS.generator_model.startswith('seq2seq'):
- load_ckpt = tf.train.latest_checkpoint(FLAGS.language_model_ckpt_dir)
- print('Restoring Generator from %s.' % load_ckpt)
- tf.logging.info('Restoring Generator from %s.' % load_ckpt)
- gen_encoder_init_saver = init_savers['gen_encoder_init_saver']
- gen_decoder_init_saver = init_savers['gen_decoder_init_saver']
- gen_encoder_init_saver.restore(sess, load_ckpt)
- gen_decoder_init_saver.restore(sess, load_ckpt)
-
- ## Discriminator Models.
- if (FLAGS.discriminator_model == 'rnn_nas' or
- FLAGS.discriminator_model == 'rnn_zaremba' or
- FLAGS.discriminator_model == 'rnn_vd' or
- FLAGS.discriminator_model == 'cnn'):
- load_ckpt = tf.train.latest_checkpoint(FLAGS.language_model_ckpt_dir)
- print('Restoring Discriminator from %s.' % load_ckpt)
- tf.logging.info('Restoring Discriminator from %s.' % load_ckpt)
- dis_init_saver = init_savers['dis_init_saver']
- dis_init_saver.restore(sess, load_ckpt)
-
- elif (FLAGS.discriminator_model == 'bidirectional_zaremba' or
- FLAGS.discriminator_model == 'bidirectional_vd'):
- assert FLAGS.language_model_ckpt_dir_reversed is not None, (
- 'Need a reversed directory to fill in the backward components.')
- load_fwd_ckpt = tf.train.latest_checkpoint(FLAGS.language_model_ckpt_dir)
- load_bwd_ckpt = tf.train.latest_checkpoint(
- FLAGS.language_model_ckpt_dir_reversed)
- print('Restoring Discriminator from %s and %s.' % (load_fwd_ckpt,
- load_bwd_ckpt))
- tf.logging.info('Restoring Discriminator from %s and %s.' %
- (load_fwd_ckpt, load_bwd_ckpt))
- dis_fwd_init_saver = init_savers['dis_fwd_init_saver']
- dis_bwd_init_saver = init_savers['dis_bwd_init_saver']
- dis_fwd_init_saver.restore(sess, load_fwd_ckpt)
- dis_bwd_init_saver.restore(sess, load_bwd_ckpt)
-
- elif FLAGS.discriminator_model == 'seq2seq_vd':
- load_ckpt = tf.train.latest_checkpoint(FLAGS.language_model_ckpt_dir)
- print('Restoring Discriminator from %s.' % load_ckpt)
- tf.logging.info('Restoring Discriminator from %s.' % load_ckpt)
- dis_encoder_init_saver = init_savers['dis_encoder_init_saver']
- dis_decoder_init_saver = init_savers['dis_decoder_init_saver']
- dis_encoder_init_saver.restore(sess, load_ckpt)
- dis_decoder_init_saver.restore(sess, load_ckpt)
-
- else:
- return
diff --git a/research/maskgan/model_utils/n_gram.py b/research/maskgan/model_utils/n_gram.py
deleted file mode 100644
index b889dde849a60d95aa38c57cd8c864249233514f..0000000000000000000000000000000000000000
--- a/research/maskgan/model_utils/n_gram.py
+++ /dev/null
@@ -1,66 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""We calculate n-Grams from the training text. We will use this as an
-evaluation metric."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from six.moves import xrange
-
-
-def hash_function(input_tuple):
- """Hash function for a tuple."""
- return hash(input_tuple)
-
-
-def find_all_ngrams(dataset, n):
- """Generate a list of all ngrams."""
- return zip(*[dataset[i:] for i in xrange(n)])
-
-
-def construct_ngrams_dict(ngrams_list):
- """Construct a ngram dictionary which maps an ngram tuple to the number
- of times it appears in the text."""
- counts = {}
-
- for t in ngrams_list:
- key = hash_function(t)
- if key in counts:
- counts[key] += 1
- else:
- counts[key] = 1
- return counts
-
-
-def percent_unique_ngrams_in_train(train_ngrams_dict, gen_ngrams_dict):
- """Compute the percent of ngrams generated by the model that are
- present in the training text and are unique."""
-
- # *Total* number of n-grams produced by the generator.
- total_ngrams_produced = 0
-
- for _, value in gen_ngrams_dict.iteritems():
- total_ngrams_produced += value
-
- # The unique ngrams in the training set.
- unique_ngrams_in_train = 0.
-
- for key, _ in gen_ngrams_dict.iteritems():
- if key in train_ngrams_dict:
- unique_ngrams_in_train += 1
- return float(unique_ngrams_in_train) / float(total_ngrams_produced)
diff --git a/research/maskgan/model_utils/variable_mapping.py b/research/maskgan/model_utils/variable_mapping.py
deleted file mode 100644
index 0301b969716fe473ac98c2e3bba5c04662461954..0000000000000000000000000000000000000000
--- a/research/maskgan/model_utils/variable_mapping.py
+++ /dev/null
@@ -1,745 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-# Dependency imports
-
-import tensorflow as tf
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def rnn_nas(hparams, model):
- assert model == 'gen' or model == 'dis'
-
- # This logic is only valid for rnn_zaremba
- if model == 'gen':
- assert FLAGS.generator_model == 'rnn_nas'
- assert hparams.gen_num_layers == 2
-
- if model == 'dis':
- assert FLAGS.discriminator_model == 'rnn_nas'
- assert hparams.dis_num_layers == 2
-
- # Output variables only for the Generator. Discriminator output biases
- # will begin randomly initialized.
- if model == 'gen':
- softmax_b = [
- v for v in tf.trainable_variables() if v.op.name == 'gen/rnn/softmax_b'
- ][0]
-
- # Common elements to Generator and Discriminator.
- embedding = [
- v for v in tf.trainable_variables()
- if v.op.name == str(model) + '/rnn/embedding'
- ][0]
- lstm_w_0 = [
- v for v in tf.trainable_variables()
- if v.op.name ==
- str(model) + '/rnn/GenericMultiRNNCell/Cell0/Alien/rnn_builder/big_h_mat'
- ][0]
- lstm_b_0 = [
- v for v in tf.trainable_variables()
- if v.op.name == str(model) +
- '/rnn/GenericMultiRNNCell/Cell0/Alien/rnn_builder/big_inputs_mat'
- ][0]
- lstm_w_1 = [
- v for v in tf.trainable_variables()
- if v.op.name ==
- str(model) + '/rnn/GenericMultiRNNCell/Cell1/Alien/rnn_builder/big_h_mat'
- ][0]
- lstm_b_1 = [
- v for v in tf.trainable_variables()
- if v.op.name == str(model) +
- '/rnn/GenericMultiRNNCell/Cell1/Alien/rnn_builder/big_inputs_mat'
- ][0]
-
- # Dictionary mapping.
- if model == 'gen':
- variable_mapping = {
- 'Model/embeddings/input_embedding':
- embedding,
- 'Model/RNN/GenericMultiRNNCell/Cell0/Alien/rnn_builder/big_h_mat':
- lstm_w_0,
- 'Model/RNN/GenericMultiRNNCell/Cell0/Alien/rnn_builder/big_inputs_mat':
- lstm_b_0,
- 'Model/RNN/GenericMultiRNNCell/Cell1/Alien/rnn_builder/big_h_mat':
- lstm_w_1,
- 'Model/RNN/GenericMultiRNNCell/Cell1/Alien/rnn_builder/big_inputs_mat':
- lstm_b_1,
- 'Model/softmax_b':
- softmax_b
- }
- else:
- variable_mapping = {
- 'Model/embeddings/input_embedding':
- embedding,
- 'Model/RNN/GenericMultiRNNCell/Cell0/Alien/rnn_builder/big_h_mat':
- lstm_w_0,
- 'Model/RNN/GenericMultiRNNCell/Cell0/Alien/rnn_builder/big_inputs_mat':
- lstm_b_0,
- 'Model/RNN/GenericMultiRNNCell/Cell1/Alien/rnn_builder/big_h_mat':
- lstm_w_1,
- 'Model/RNN/GenericMultiRNNCell/Cell1/Alien/rnn_builder/big_inputs_mat':
- lstm_b_1
- }
-
- return variable_mapping
-
-
-def cnn():
- """Variable mapping for the CNN embedding.
-
- Returns:
- variable_mapping: Dictionary with Key: ckpt_name, Value: model_var.
- """
- # This logic is only valid for cnn
- assert FLAGS.discriminator_model == 'cnn'
-
- # Retrieve CNN embedding.
- embedding = [
- v for v in tf.trainable_variables() if v.op.name == 'dis/embedding'
- ][0]
-
- # Variable mapping.
- variable_mapping = {'Model/embedding': embedding}
-
- return variable_mapping
-
-
-def rnn_zaremba(hparams, model):
- """Returns the PTB Variable name to MaskGAN Variable dictionary mapping. This
- is a highly restrictive function just for testing. This will need to be
- generalized.
-
- Args:
- hparams: Hyperparameters for the MaskGAN.
- model: Model type, one of ['gen', 'dis'].
-
- Returns:
- variable_mapping: Dictionary with Key: ckpt_name, Value: model_var.
- """
- assert model == 'gen' or model == 'dis'
-
- # This logic is only valid for rnn_zaremba
- if model == 'gen':
- assert FLAGS.generator_model == 'rnn_zaremba'
- assert hparams.gen_num_layers == 2
-
- if model == 'dis':
- assert (FLAGS.discriminator_model == 'rnn_zaremba' or
- FLAGS.discriminator_model == 'rnn_vd')
- assert hparams.dis_num_layers == 2
-
- # Output variables only for the Generator. Discriminator output weights
- # and biases will begin randomly initialized.
- if model == 'gen':
- softmax_w = [
- v for v in tf.trainable_variables() if v.op.name == 'gen/rnn/softmax_w'
- ][0]
- softmax_b = [
- v for v in tf.trainable_variables() if v.op.name == 'gen/rnn/softmax_b'
- ][0]
-
- # Common elements to Generator and Discriminator.
- if not FLAGS.dis_share_embedding or model != 'dis':
- embedding = [
- v for v in tf.trainable_variables()
- if v.op.name == str(model) + '/rnn/embedding'
- ][0]
- lstm_w_0 = [
- v for v in tf.trainable_variables() if v.op.name == str(model) +
- '/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/kernel'
- ][0]
- lstm_b_0 = [
- v for v in tf.trainable_variables() if v.op.name == str(model) +
- '/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/bias'
- ][0]
- lstm_w_1 = [
- v for v in tf.trainable_variables() if v.op.name == str(model) +
- '/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/kernel'
- ][0]
- lstm_b_1 = [
- v for v in tf.trainable_variables() if v.op.name == str(model) +
- '/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/bias'
- ][0]
-
- # Dictionary mapping.
- if model == 'gen':
- variable_mapping = {
- 'Model/embedding': embedding,
- 'Model/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/kernel': lstm_w_0,
- 'Model/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/bias': lstm_b_0,
- 'Model/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/kernel': lstm_w_1,
- 'Model/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/bias': lstm_b_1,
- 'Model/softmax_w': softmax_w,
- 'Model/softmax_b': softmax_b
- }
- else:
- if FLAGS.dis_share_embedding:
- variable_mapping = {
- 'Model/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/kernel': lstm_w_0,
- 'Model/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/bias': lstm_b_0,
- 'Model/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/kernel': lstm_w_1,
- 'Model/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/bias': lstm_b_1
- }
- else:
- variable_mapping = {
- 'Model/embedding': embedding,
- 'Model/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/kernel': lstm_w_0,
- 'Model/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/bias': lstm_b_0,
- 'Model/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/kernel': lstm_w_1,
- 'Model/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/bias': lstm_b_1
- }
-
- return variable_mapping
-
-
-def gen_encoder_seq2seq_nas(hparams):
- """Returns the NAS Variable name to MaskGAN Variable
- dictionary mapping. This is a highly restrictive function just for testing.
- This is for the *unidirecitional* seq2seq_nas encoder.
-
- Args:
- hparams: Hyperparameters for the MaskGAN.
-
- Returns:
- variable_mapping: Dictionary with Key: ckpt_name, Value: model_varself.
- """
- assert FLAGS.generator_model == 'seq2seq_nas'
- assert hparams.gen_num_layers == 2
- ## Encoder forward variables.
-
- if not FLAGS.seq2seq_share_embedding:
- encoder_embedding = [
- v for v in tf.trainable_variables()
- if v.op.name == 'gen/encoder/rnn/embedding'
- ][0]
- encoder_lstm_w_0 = [
- v for v in tf.trainable_variables()
- if v.op.name ==
- 'gen/encoder/rnn/GenericMultiRNNCell/Cell0/Alien/rnn_builder/big_h_mat'
- ][0]
- encoder_lstm_b_0 = [
- v for v in tf.trainable_variables()
- if v.op.name ==
- 'gen/encoder/rnn/GenericMultiRNNCell/Cell0/Alien/rnn_builder/big_inputs_mat'
- ][0]
- encoder_lstm_w_1 = [
- v for v in tf.trainable_variables()
- if v.op.name ==
- 'gen/encoder/rnn/GenericMultiRNNCell/Cell1/Alien/rnn_builder/big_h_mat'
- ][0]
- encoder_lstm_b_1 = [
- v for v in tf.trainable_variables()
- if v.op.name ==
- 'gen/encoder/rnn/GenericMultiRNNCell/Cell1/Alien/rnn_builder/big_inputs_mat'
- ][0]
-
- if not FLAGS.seq2seq_share_embedding:
- variable_mapping = {
- 'Model/embeddings/input_embedding':
- encoder_embedding,
- 'Model/RNN/GenericMultiRNNCell/Cell0/Alien/rnn_builder/big_h_mat':
- encoder_lstm_w_0,
- 'Model/RNN/GenericMultiRNNCell/Cell0/Alien/rnn_builder/big_inputs_mat':
- encoder_lstm_b_0,
- 'Model/RNN/GenericMultiRNNCell/Cell1/Alien/rnn_builder/big_h_mat':
- encoder_lstm_w_1,
- 'Model/RNN/GenericMultiRNNCell/Cell1/Alien/rnn_builder/big_inputs_mat':
- encoder_lstm_b_1
- }
- else:
- variable_mapping = {
- 'Model/RNN/GenericMultiRNNCell/Cell0/Alien/rnn_builder/big_h_mat':
- encoder_lstm_w_0,
- 'Model/RNN/GenericMultiRNNCell/Cell0/Alien/rnn_builder/big_inputs_mat':
- encoder_lstm_b_0,
- 'Model/RNN/GenericMultiRNNCell/Cell1/Alien/rnn_builder/big_h_mat':
- encoder_lstm_w_1,
- 'Model/RNN/GenericMultiRNNCell/Cell1/Alien/rnn_builder/big_inputs_mat':
- encoder_lstm_b_1
- }
- return variable_mapping
-
-
-def gen_decoder_seq2seq_nas(hparams):
- assert FLAGS.generator_model == 'seq2seq_nas'
- assert hparams.gen_num_layers == 2
-
- decoder_embedding = [
- v for v in tf.trainable_variables()
- if v.op.name == 'gen/decoder/rnn/embedding'
- ][0]
- decoder_lstm_w_0 = [
- v for v in tf.trainable_variables()
- if v.op.name ==
- 'gen/decoder/rnn/GenericMultiRNNCell/Cell0/Alien/rnn_builder/big_h_mat'
- ][0]
- decoder_lstm_b_0 = [
- v for v in tf.trainable_variables()
- if v.op.name ==
- 'gen/decoder/rnn/GenericMultiRNNCell/Cell0/Alien/rnn_builder/big_inputs_mat'
- ][0]
- decoder_lstm_w_1 = [
- v for v in tf.trainable_variables()
- if v.op.name ==
- 'gen/decoder/rnn/GenericMultiRNNCell/Cell1/Alien/rnn_builder/big_h_mat'
- ][0]
- decoder_lstm_b_1 = [
- v for v in tf.trainable_variables()
- if v.op.name ==
- 'gen/decoder/rnn/GenericMultiRNNCell/Cell1/Alien/rnn_builder/big_inputs_mat'
- ][0]
-
- decoder_softmax_b = [
- v for v in tf.trainable_variables()
- if v.op.name == 'gen/decoder/rnn/softmax_b'
- ][0]
-
- variable_mapping = {
- 'Model/embeddings/input_embedding':
- decoder_embedding,
- 'Model/RNN/GenericMultiRNNCell/Cell0/Alien/rnn_builder/big_h_mat':
- decoder_lstm_w_0,
- 'Model/RNN/GenericMultiRNNCell/Cell0/Alien/rnn_builder/big_inputs_mat':
- decoder_lstm_b_0,
- 'Model/RNN/GenericMultiRNNCell/Cell1/Alien/rnn_builder/big_h_mat':
- decoder_lstm_w_1,
- 'Model/RNN/GenericMultiRNNCell/Cell1/Alien/rnn_builder/big_inputs_mat':
- decoder_lstm_b_1,
- 'Model/softmax_b':
- decoder_softmax_b
- }
-
- return variable_mapping
-
-
-def gen_encoder_seq2seq(hparams):
- """Returns the PTB Variable name to MaskGAN Variable
- dictionary mapping. This is a highly restrictive function just for testing.
- This is foe the *unidirecitional* seq2seq_zaremba encoder.
-
- Args:
- hparams: Hyperparameters for the MaskGAN.
-
- Returns:
- variable_mapping: Dictionary with Key: ckpt_name, Value: model_varself.
- """
- assert (FLAGS.generator_model == 'seq2seq_zaremba' or
- FLAGS.generator_model == 'seq2seq_vd')
- assert hparams.gen_num_layers == 2
-
- ## Encoder forward variables.
- if not FLAGS.seq2seq_share_embedding:
- encoder_embedding = [
- v for v in tf.trainable_variables()
- if v.op.name == 'gen/encoder/rnn/embedding'
- ][0]
- encoder_lstm_w_0 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'gen/encoder/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/kernel'
- ][0]
- encoder_lstm_b_0 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'gen/encoder/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/bias'
- ][0]
- encoder_lstm_w_1 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'gen/encoder/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/kernel'
- ][0]
- encoder_lstm_b_1 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'gen/encoder/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/bias'
- ][0]
-
- if FLAGS.data_set == 'ptb':
- model_str = 'Model'
- else:
- model_str = 'model'
-
- if not FLAGS.seq2seq_share_embedding:
- variable_mapping = {
- str(model_str) + '/embedding':
- encoder_embedding,
- str(model_str) + '/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/kernel':
- encoder_lstm_w_0,
- str(model_str) + '/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/bias':
- encoder_lstm_b_0,
- str(model_str) + '/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/kernel':
- encoder_lstm_w_1,
- str(model_str) + '/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/bias':
- encoder_lstm_b_1
- }
- else:
- variable_mapping = {
- str(model_str) + '/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/kernel':
- encoder_lstm_w_0,
- str(model_str) + '/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/bias':
- encoder_lstm_b_0,
- str(model_str) + '/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/kernel':
- encoder_lstm_w_1,
- str(model_str) + '/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/bias':
- encoder_lstm_b_1
- }
- return variable_mapping
-
-
-def gen_decoder_seq2seq(hparams):
- assert (FLAGS.generator_model == 'seq2seq_zaremba' or
- FLAGS.generator_model == 'seq2seq_vd')
- assert hparams.gen_num_layers == 2
-
- decoder_embedding = [
- v for v in tf.trainable_variables()
- if v.op.name == 'gen/decoder/rnn/embedding'
- ][0]
- decoder_lstm_w_0 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'gen/decoder/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/kernel'
- ][0]
- decoder_lstm_b_0 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'gen/decoder/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/bias'
- ][0]
- decoder_lstm_w_1 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'gen/decoder/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/kernel'
- ][0]
- decoder_lstm_b_1 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'gen/decoder/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/bias'
- ][0]
- decoder_softmax_b = [
- v for v in tf.trainable_variables()
- if v.op.name == 'gen/decoder/rnn/softmax_b'
- ][0]
-
- if FLAGS.data_set == 'ptb':
- model_str = 'Model'
- else:
- model_str = 'model'
-
- variable_mapping = {
- str(model_str) + '/embedding':
- decoder_embedding,
- str(model_str) + '/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/kernel':
- decoder_lstm_w_0,
- str(model_str) + '/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/bias':
- decoder_lstm_b_0,
- str(model_str) + '/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/kernel':
- decoder_lstm_w_1,
- str(model_str) + '/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/bias':
- decoder_lstm_b_1,
- str(model_str) + '/softmax_b':
- decoder_softmax_b
- }
- return variable_mapping
-
-
-def dis_fwd_bidirectional(hparams):
- """Returns the *forward* PTB Variable name to MaskGAN Variable dictionary
- mapping. This is a highly restrictive function just for testing. This is for
- the bidirectional_zaremba discriminator.
-
- Args:
- FLAGS: Flags for the model.
- hparams: Hyperparameters for the MaskGAN.
-
- Returns:
- variable_mapping: Dictionary with Key: ckpt_name, Value: model_varself.
- """
- assert (FLAGS.discriminator_model == 'bidirectional_zaremba' or
- FLAGS.discriminator_model == 'bidirectional_vd')
- assert hparams.dis_num_layers == 2
-
- # Forward Discriminator Elements.
- if not FLAGS.dis_share_embedding:
- embedding = [
- v for v in tf.trainable_variables() if v.op.name == 'dis/embedding'
- ][0]
- fw_lstm_w_0 = [
- v for v in tf.trainable_variables()
- if v.op.name == 'dis/rnn/fw/multi_rnn_cell/cell_0/basic_lstm_cell/kernel'
- ][0]
- fw_lstm_b_0 = [
- v for v in tf.trainable_variables()
- if v.op.name == 'dis/rnn/fw/multi_rnn_cell/cell_0/basic_lstm_cell/bias'
- ][0]
- fw_lstm_w_1 = [
- v for v in tf.trainable_variables()
- if v.op.name == 'dis/rnn/fw/multi_rnn_cell/cell_1/basic_lstm_cell/kernel'
- ][0]
- fw_lstm_b_1 = [
- v for v in tf.trainable_variables()
- if v.op.name == 'dis/rnn/fw/multi_rnn_cell/cell_1/basic_lstm_cell/bias'
- ][0]
- if FLAGS.dis_share_embedding:
- variable_mapping = {
- 'Model/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/kernel': fw_lstm_w_0,
- 'Model/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/bias': fw_lstm_b_0,
- 'Model/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/kernel': fw_lstm_w_1,
- 'Model/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/bias': fw_lstm_b_1
- }
- else:
- variable_mapping = {
- 'Model/embedding': embedding,
- 'Model/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/kernel': fw_lstm_w_0,
- 'Model/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/bias': fw_lstm_b_0,
- 'Model/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/kernel': fw_lstm_w_1,
- 'Model/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/bias': fw_lstm_b_1
- }
- return variable_mapping
-
-
-def dis_bwd_bidirectional(hparams):
- """Returns the *backward* PTB Variable name to MaskGAN Variable dictionary
- mapping. This is a highly restrictive function just for testing. This is for
- the bidirectional_zaremba discriminator.
-
- Args:
- hparams: Hyperparameters for the MaskGAN.
-
- Returns:
- variable_mapping: Dictionary with Key: ckpt_name, Value: model_varself.
- """
- assert (FLAGS.discriminator_model == 'bidirectional_zaremba' or
- FLAGS.discriminator_model == 'bidirectional_vd')
- assert hparams.dis_num_layers == 2
-
- # Backward Discriminator Elements.
- bw_lstm_w_0 = [
- v for v in tf.trainable_variables()
- if v.op.name == 'dis/rnn/bw/multi_rnn_cell/cell_0/basic_lstm_cell/kernel'
- ][0]
- bw_lstm_b_0 = [
- v for v in tf.trainable_variables()
- if v.op.name == 'dis/rnn/bw/multi_rnn_cell/cell_0/basic_lstm_cell/bias'
- ][0]
- bw_lstm_w_1 = [
- v for v in tf.trainable_variables()
- if v.op.name == 'dis/rnn/bw/multi_rnn_cell/cell_1/basic_lstm_cell/kernel'
- ][0]
- bw_lstm_b_1 = [
- v for v in tf.trainable_variables()
- if v.op.name == 'dis/rnn/bw/multi_rnn_cell/cell_1/basic_lstm_cell/bias'
- ][0]
-
- variable_mapping = {
- 'Model/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/kernel': bw_lstm_w_0,
- 'Model/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/bias': bw_lstm_b_0,
- 'Model/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/kernel': bw_lstm_w_1,
- 'Model/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/bias': bw_lstm_b_1
- }
- return variable_mapping
-
-
-def dis_encoder_seq2seq(hparams):
- """Returns the PTB Variable name to MaskGAN Variable
- dictionary mapping.
-
- Args:
- hparams: Hyperparameters for the MaskGAN.
-
- Returns:
- variable_mapping: Dictionary with Key: ckpt_name, Value: model_varself.
- """
- assert FLAGS.discriminator_model == 'seq2seq_vd'
- assert hparams.dis_num_layers == 2
-
- ## Encoder forward variables.
- encoder_lstm_w_0 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'dis/encoder/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/kernel'
- ][0]
- encoder_lstm_b_0 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'dis/encoder/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/bias'
- ][0]
- encoder_lstm_w_1 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'dis/encoder/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/kernel'
- ][0]
- encoder_lstm_b_1 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'dis/encoder/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/bias'
- ][0]
-
- if FLAGS.data_set == 'ptb':
- model_str = 'Model'
- else:
- model_str = 'model'
-
- variable_mapping = {
- str(model_str) + '/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/kernel':
- encoder_lstm_w_0,
- str(model_str) + '/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/bias':
- encoder_lstm_b_0,
- str(model_str) + '/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/kernel':
- encoder_lstm_w_1,
- str(model_str) + '/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/bias':
- encoder_lstm_b_1
- }
- return variable_mapping
-
-
-def dis_decoder_seq2seq(hparams):
- assert FLAGS.discriminator_model == 'seq2seq_vd'
- assert hparams.dis_num_layers == 2
-
- if not FLAGS.dis_share_embedding:
- decoder_embedding = [
- v for v in tf.trainable_variables()
- if v.op.name == 'dis/decoder/rnn/embedding'
- ][0]
- decoder_lstm_w_0 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'dis/decoder/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/kernel'
- ][0]
- decoder_lstm_b_0 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'dis/decoder/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/bias'
- ][0]
- decoder_lstm_w_1 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'dis/decoder/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/kernel'
- ][0]
- decoder_lstm_b_1 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'dis/decoder/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/bias'
- ][0]
-
- if FLAGS.data_set == 'ptb':
- model_str = 'Model'
- else:
- model_str = 'model'
-
- if not FLAGS.dis_share_embedding:
- variable_mapping = {
- str(model_str) + '/embedding':
- decoder_embedding,
- str(model_str) + '/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/kernel':
- decoder_lstm_w_0,
- str(model_str) + '/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/bias':
- decoder_lstm_b_0,
- str(model_str) + '/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/kernel':
- decoder_lstm_w_1,
- str(model_str) + '/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/bias':
- decoder_lstm_b_1
- }
- else:
- variable_mapping = {
- str(model_str) + '/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/kernel':
- decoder_lstm_w_0,
- str(model_str) + '/RNN/multi_rnn_cell/cell_0/basic_lstm_cell/bias':
- decoder_lstm_b_0,
- str(model_str) + '/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/kernel':
- decoder_lstm_w_1,
- str(model_str) + '/RNN/multi_rnn_cell/cell_1/basic_lstm_cell/bias':
- decoder_lstm_b_1,
- }
- return variable_mapping
-
-
-def dis_seq2seq_vd(hparams):
- assert FLAGS.discriminator_model == 'seq2seq_vd'
- assert hparams.dis_num_layers == 2
-
- if not FLAGS.dis_share_embedding:
- decoder_embedding = [
- v for v in tf.trainable_variables()
- if v.op.name == 'dis/decoder/rnn/embedding'
- ][0]
-
- ## Encoder variables.
- encoder_lstm_w_0 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'dis/encoder/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/kernel'
- ][0]
- encoder_lstm_b_0 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'dis/encoder/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/bias'
- ][0]
- encoder_lstm_w_1 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'dis/encoder/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/kernel'
- ][0]
- encoder_lstm_b_1 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'dis/encoder/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/bias'
- ][0]
-
- ## Attention.
- if FLAGS.attention_option is not None:
- decoder_attention_keys = [
- v for v in tf.trainable_variables()
- if v.op.name == 'dis/decoder/attention_keys/weights'
- ][0]
- decoder_attention_construct_weights = [
- v for v in tf.trainable_variables()
- if v.op.name == 'dis/decoder/rnn/attention_construct/weights'
- ][0]
-
- ## Decoder.
- decoder_lstm_w_0 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'dis/decoder/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/kernel'
- ][0]
- decoder_lstm_b_0 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'dis/decoder/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/bias'
- ][0]
- decoder_lstm_w_1 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'dis/decoder/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/kernel'
- ][0]
- decoder_lstm_b_1 = [
- v for v in tf.trainable_variables() if v.op.name ==
- 'dis/decoder/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/bias'
- ][0]
-
- # Standard variable mappings.
- variable_mapping = {
- 'gen/encoder/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/kernel':
- encoder_lstm_w_0,
- 'gen/encoder/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/bias':
- encoder_lstm_b_0,
- 'gen/encoder/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/kernel':
- encoder_lstm_w_1,
- 'gen/encoder/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/bias':
- encoder_lstm_b_1,
- 'gen/decoder/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/kernel':
- decoder_lstm_w_0,
- 'gen/decoder/rnn/multi_rnn_cell/cell_0/basic_lstm_cell/bias':
- decoder_lstm_b_0,
- 'gen/decoder/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/kernel':
- decoder_lstm_w_1,
- 'gen/decoder/rnn/multi_rnn_cell/cell_1/basic_lstm_cell/bias':
- decoder_lstm_b_1
- }
-
- # Optional variable mappings.
- if not FLAGS.dis_share_embedding:
- variable_mapping['gen/decoder/rnn/embedding'] = decoder_embedding
- if FLAGS.attention_option is not None:
- variable_mapping[
- 'gen/decoder/attention_keys/weights'] = decoder_attention_keys
- variable_mapping[
- 'gen/decoder/rnn/attention_construct/weights'] = decoder_attention_construct_weights
-
- return variable_mapping
diff --git a/research/maskgan/models/__init__.py b/research/maskgan/models/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/maskgan/models/attention_utils.py b/research/maskgan/models/attention_utils.py
deleted file mode 100644
index 4bd9e41dd3178d6210e8f81d628b7d92004a6601..0000000000000000000000000000000000000000
--- a/research/maskgan/models/attention_utils.py
+++ /dev/null
@@ -1,477 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Attention-based decoder functions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-from tensorflow.python.framework import function
-
-__all__ = [
- "prepare_attention", "attention_decoder_fn_train",
- "attention_decoder_fn_inference"
-]
-
-
-def attention_decoder_fn_train(encoder_state,
- attention_keys,
- attention_values,
- attention_score_fn,
- attention_construct_fn,
- name=None):
- """Attentional decoder function for `dynamic_rnn_decoder` during training.
-
- The `attention_decoder_fn_train` is a training function for an
- attention-based sequence-to-sequence model. It should be used when
- `dynamic_rnn_decoder` is in the training mode.
-
- The `attention_decoder_fn_train` is called with a set of the user arguments
- and returns the `decoder_fn`, which can be passed to the
- `dynamic_rnn_decoder`, such that
-
- ```
- dynamic_fn_train = attention_decoder_fn_train(encoder_state)
- outputs_train, state_train = dynamic_rnn_decoder(
- decoder_fn=dynamic_fn_train, ...)
- ```
-
- Further usage can be found in the `kernel_tests/seq2seq_test.py`.
-
- Args:
- encoder_state: The encoded state to initialize the `dynamic_rnn_decoder`.
- attention_keys: to be compared with target states.
- attention_values: to be used to construct context vectors.
- attention_score_fn: to compute similarity between key and target states.
- attention_construct_fn: to build attention states.
- name: (default: `None`) NameScope for the decoder function;
- defaults to "simple_decoder_fn_train"
-
- Returns:
- A decoder function with the required interface of `dynamic_rnn_decoder`
- intended for training.
- """
- with tf.name_scope(name, "attention_decoder_fn_train", [
- encoder_state, attention_keys, attention_values, attention_score_fn,
- attention_construct_fn
- ]):
- pass
-
- def decoder_fn(time, cell_state, cell_input, cell_output, context_state):
- """Decoder function used in the `dynamic_rnn_decoder` for training.
-
- Args:
- time: positive integer constant reflecting the current timestep.
- cell_state: state of RNNCell.
- cell_input: input provided by `dynamic_rnn_decoder`.
- cell_output: output of RNNCell.
- context_state: context state provided by `dynamic_rnn_decoder`.
-
- Returns:
- A tuple (done, next state, next input, emit output, next context state)
- where:
-
- done: `None`, which is used by the `dynamic_rnn_decoder` to indicate
- that `sequence_lengths` in `dynamic_rnn_decoder` should be used.
-
- next state: `cell_state`, this decoder function does not modify the
- given state.
-
- next input: `cell_input`, this decoder function does not modify the
- given input. The input could be modified when applying e.g. attention.
-
- emit output: `cell_output`, this decoder function does not modify the
- given output.
-
- next context state: `context_state`, this decoder function does not
- modify the given context state. The context state could be modified when
- applying e.g. beam search.
- """
- with tf.name_scope(
- name, "attention_decoder_fn_train",
- [time, cell_state, cell_input, cell_output, context_state]):
- if cell_state is None: # first call, return encoder_state
- cell_state = encoder_state
-
- # init attention
- attention = _init_attention(encoder_state)
- else:
- # construct attention
- attention = attention_construct_fn(cell_output, attention_keys,
- attention_values)
- cell_output = attention
-
- # combine cell_input and attention
- next_input = tf.concat([cell_input, attention], 1)
-
- return (None, cell_state, next_input, cell_output, context_state)
-
- return decoder_fn
-
-
-def attention_decoder_fn_inference(output_fn,
- encoder_state,
- attention_keys,
- attention_values,
- attention_score_fn,
- attention_construct_fn,
- embeddings,
- start_of_sequence_id,
- end_of_sequence_id,
- maximum_length,
- num_decoder_symbols,
- dtype=tf.int32,
- name=None):
- """Attentional decoder function for `dynamic_rnn_decoder` during inference.
-
- The `attention_decoder_fn_inference` is a simple inference function for a
- sequence-to-sequence model. It should be used when `dynamic_rnn_decoder` is
- in the inference mode.
-
- The `attention_decoder_fn_inference` is called with user arguments
- and returns the `decoder_fn`, which can be passed to the
- `dynamic_rnn_decoder`, such that
-
- ```
- dynamic_fn_inference = attention_decoder_fn_inference(...)
- outputs_inference, state_inference = dynamic_rnn_decoder(
- decoder_fn=dynamic_fn_inference, ...)
- ```
-
- Further usage can be found in the `kernel_tests/seq2seq_test.py`.
-
- Args:
- output_fn: An output function to project your `cell_output` onto class
- logits.
-
- An example of an output function;
-
- ```
- tf.variable_scope("decoder") as varscope
- output_fn = lambda x: tf.contrib.layers.linear(x, num_decoder_symbols,
- scope=varscope)
-
- outputs_train, state_train = seq2seq.dynamic_rnn_decoder(...)
- logits_train = output_fn(outputs_train)
-
- varscope.reuse_variables()
- logits_inference, state_inference = seq2seq.dynamic_rnn_decoder(
- output_fn=output_fn, ...)
- ```
-
- If `None` is supplied it will act as an identity function, which
- might be wanted when using the RNNCell `OutputProjectionWrapper`.
-
- encoder_state: The encoded state to initialize the `dynamic_rnn_decoder`.
- attention_keys: to be compared with target states.
- attention_values: to be used to construct context vectors.
- attention_score_fn: to compute similarity between key and target states.
- attention_construct_fn: to build attention states.
- embeddings: The embeddings matrix used for the decoder sized
- `[num_decoder_symbols, embedding_size]`.
- start_of_sequence_id: The start of sequence ID in the decoder embeddings.
- end_of_sequence_id: The end of sequence ID in the decoder embeddings.
- maximum_length: The maximum allowed of time steps to decode.
- num_decoder_symbols: The number of classes to decode at each time step.
- dtype: (default: `tf.int32`) The default data type to use when
- handling integer objects.
- name: (default: `None`) NameScope for the decoder function;
- defaults to "attention_decoder_fn_inference"
-
- Returns:
- A decoder function with the required interface of `dynamic_rnn_decoder`
- intended for inference.
- """
- with tf.name_scope(name, "attention_decoder_fn_inference", [
- output_fn, encoder_state, attention_keys, attention_values,
- attention_score_fn, attention_construct_fn, embeddings,
- start_of_sequence_id, end_of_sequence_id, maximum_length,
- num_decoder_symbols, dtype
- ]):
- start_of_sequence_id = tf.convert_to_tensor(start_of_sequence_id, dtype)
- end_of_sequence_id = tf.convert_to_tensor(end_of_sequence_id, dtype)
- maximum_length = tf.convert_to_tensor(maximum_length, dtype)
- num_decoder_symbols = tf.convert_to_tensor(num_decoder_symbols, dtype)
- encoder_info = tf.contrib.framework.nest.flatten(encoder_state)[0]
- batch_size = encoder_info.get_shape()[0].value
- if output_fn is None:
- output_fn = lambda x: x
- if batch_size is None:
- batch_size = tf.shape(encoder_info)[0]
-
- def decoder_fn(time, cell_state, cell_input, cell_output, context_state):
- """Decoder function used in the `dynamic_rnn_decoder` for inference.
-
- The main difference between this decoder function and the `decoder_fn` in
- `attention_decoder_fn_train` is how `next_cell_input` is calculated. In
- decoder function we calculate the next input by applying an argmax across
- the feature dimension of the output from the decoder. This is a
- greedy-search approach. (Bahdanau et al., 2014) & (Sutskever et al., 2014)
- use beam-search instead.
-
- Args:
- time: positive integer constant reflecting the current timestep.
- cell_state: state of RNNCell.
- cell_input: input provided by `dynamic_rnn_decoder`.
- cell_output: output of RNNCell.
- context_state: context state provided by `dynamic_rnn_decoder`.
-
- Returns:
- A tuple (done, next state, next input, emit output, next context state)
- where:
-
- done: A boolean vector to indicate which sentences has reached a
- `end_of_sequence_id`. This is used for early stopping by the
- `dynamic_rnn_decoder`. When `time>=maximum_length` a boolean vector with
- all elements as `true` is returned.
-
- next state: `cell_state`, this decoder function does not modify the
- given state.
-
- next input: The embedding from argmax of the `cell_output` is used as
- `next_input`.
-
- emit output: If `output_fn is None` the supplied `cell_output` is
- returned, else the `output_fn` is used to update the `cell_output`
- before calculating `next_input` and returning `cell_output`.
-
- next context state: `context_state`, this decoder function does not
- modify the given context state. The context state could be modified when
- applying e.g. beam search.
-
- Raises:
- ValueError: if cell_input is not None.
-
- """
- with tf.name_scope(
- name, "attention_decoder_fn_inference",
- [time, cell_state, cell_input, cell_output, context_state]):
- if cell_input is not None:
- raise ValueError(
- "Expected cell_input to be None, but saw: %s" % cell_input)
- if cell_output is None:
- # invariant that this is time == 0
- next_input_id = tf.ones(
- [
- batch_size,
- ], dtype=dtype) * (
- start_of_sequence_id)
- done = tf.zeros(
- [
- batch_size,
- ], dtype=tf.bool)
- cell_state = encoder_state
- cell_output = tf.zeros([num_decoder_symbols], dtype=tf.float32)
- cell_input = tf.gather(embeddings, next_input_id)
-
- # init attention
- attention = _init_attention(encoder_state)
- else:
- # construct attention
- attention = attention_construct_fn(cell_output, attention_keys,
- attention_values)
- cell_output = attention
-
- # argmax decoder
- cell_output = output_fn(cell_output) # logits
- next_input_id = tf.cast(tf.argmax(cell_output, 1), dtype=dtype)
- done = tf.equal(next_input_id, end_of_sequence_id)
- cell_input = tf.gather(embeddings, next_input_id)
-
- # combine cell_input and attention
- next_input = tf.concat([cell_input, attention], 1)
-
- # if time > maxlen, return all true vector
- done = tf.cond(
- tf.greater(time, maximum_length),
- lambda: tf.ones([
- batch_size,], dtype=tf.bool), lambda: done)
- return (done, cell_state, next_input, cell_output, context_state)
-
- return decoder_fn
-
-
-## Helper functions ##
-def prepare_attention(attention_states, attention_option, num_units,
- reuse=None):
- """Prepare keys/values/functions for attention.
-
- Args:
- attention_states: hidden states to attend over.
- attention_option: how to compute attention, either "luong" or "bahdanau".
- num_units: hidden state dimension.
- reuse: whether to reuse variable scope.
-
- Returns:
- attention_keys: to be compared with target states.
- attention_values: to be used to construct context vectors.
- attention_score_fn: to compute similarity between key and target states.
- attention_construct_fn: to build attention states.
- """
- # Prepare attention keys / values from attention_states
- with tf.variable_scope("attention_keys", reuse=reuse) as scope:
- attention_keys = tf.contrib.layers.linear(
- attention_states, num_units, biases_initializer=None, scope=scope)
- attention_values = attention_states
-
- # Attention score function
- attention_score_fn = _create_attention_score_fn("attention_score", num_units,
- attention_option, reuse)
- # Attention construction function
- attention_construct_fn = _create_attention_construct_fn(
- "attention_construct", num_units, attention_score_fn, reuse)
-
- return (attention_keys, attention_values, attention_score_fn,
- attention_construct_fn)
-
-
-def _init_attention(encoder_state):
- """Initialize attention. Handling both LSTM and GRU.
-
- Args:
- encoder_state: The encoded state to initialize the `dynamic_rnn_decoder`.
-
- Returns:
- attn: initial zero attention vector.
- """
-
- # Multi- vs single-layer
- # TODO(thangluong): is this the best way to check?
- if isinstance(encoder_state, tuple):
- top_state = encoder_state[-1]
- else:
- top_state = encoder_state
-
- # LSTM vs GRU
- if isinstance(top_state, tf.contrib.rnn.LSTMStateTuple):
- attn = tf.zeros_like(top_state.h)
- else:
- attn = tf.zeros_like(top_state)
-
- return attn
-
-
-def _create_attention_construct_fn(name, num_units, attention_score_fn, reuse):
- """Function to compute attention vectors.
-
- Args:
- name: to label variables.
- num_units: hidden state dimension.
- attention_score_fn: to compute similarity between key and target states.
- reuse: whether to reuse variable scope.
-
- Returns:
- attention_construct_fn: to build attention states.
- """
-
- def construct_fn(attention_query, attention_keys, attention_values):
- with tf.variable_scope(name, reuse=reuse) as scope:
- context = attention_score_fn(attention_query, attention_keys,
- attention_values)
- concat_input = tf.concat([attention_query, context], 1)
- attention = tf.contrib.layers.linear(
- concat_input, num_units, biases_initializer=None, scope=scope)
- return attention
-
- return construct_fn
-
-
-# keys: [batch_size, attention_length, attn_size]
-# query: [batch_size, 1, attn_size]
-# return weights [batch_size, attention_length]
-@function.Defun(func_name="attn_add_fun", noinline=True)
-def _attn_add_fun(v, keys, query):
- return tf.reduce_sum(v * tf.tanh(keys + query), [2])
-
-
-@function.Defun(func_name="attn_mul_fun", noinline=True)
-def _attn_mul_fun(keys, query):
- return tf.reduce_sum(keys * query, [2])
-
-
-def _create_attention_score_fn(name,
- num_units,
- attention_option,
- reuse,
- dtype=tf.float32):
- """Different ways to compute attention scores.
-
- Args:
- name: to label variables.
- num_units: hidden state dimension.
- attention_option: how to compute attention, either "luong" or "bahdanau".
- "bahdanau": additive (Bahdanau et al., ICLR'2015)
- "luong": multiplicative (Luong et al., EMNLP'2015)
- reuse: whether to reuse variable scope.
- dtype: (default: `tf.float32`) data type to use.
-
- Returns:
- attention_score_fn: to compute similarity between key and target states.
- """
- with tf.variable_scope(name, reuse=reuse):
- if attention_option == "bahdanau":
- query_w = tf.get_variable("attnW", [num_units, num_units], dtype=dtype)
- score_v = tf.get_variable("attnV", [num_units], dtype=dtype)
-
- def attention_score_fn(query, keys, values):
- """Put attention masks on attention_values using attention_keys and query.
-
- Args:
- query: A Tensor of shape [batch_size, num_units].
- keys: A Tensor of shape [batch_size, attention_length, num_units].
- values: A Tensor of shape [batch_size, attention_length, num_units].
-
- Returns:
- context_vector: A Tensor of shape [batch_size, num_units].
-
- Raises:
- ValueError: if attention_option is neither "luong" or "bahdanau".
-
-
- """
- if attention_option == "bahdanau":
- # transform query
- query = tf.matmul(query, query_w)
-
- # reshape query: [batch_size, 1, num_units]
- query = tf.reshape(query, [-1, 1, num_units])
-
- # attn_fun
- scores = _attn_add_fun(score_v, keys, query)
- elif attention_option == "luong":
- # reshape query: [batch_size, 1, num_units]
- query = tf.reshape(query, [-1, 1, num_units])
-
- # attn_fun
- scores = _attn_mul_fun(keys, query)
- else:
- raise ValueError("Unknown attention option %s!" % attention_option)
-
- # Compute alignment weights
- # scores: [batch_size, length]
- # alignments: [batch_size, length]
- # TODO(thangluong): not normalize over padding positions.
- alignments = tf.nn.softmax(scores)
-
- # Now calculate the attention-weighted vector.
- alignments = tf.expand_dims(alignments, 2)
- context_vector = tf.reduce_sum(alignments * values, [1])
- context_vector.set_shape([None, num_units])
-
- return context_vector
-
- return attention_score_fn
diff --git a/research/maskgan/models/bidirectional.py b/research/maskgan/models/bidirectional.py
deleted file mode 100644
index 1e6b3fe45f9ffe7dffdeb5c0d571de7e68227498..0000000000000000000000000000000000000000
--- a/research/maskgan/models/bidirectional.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Simple bidirectional model definitions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-# ZoneoutWrapper.
-from regularization import zoneout
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def discriminator(hparams, sequence, is_training, reuse=None):
- """Define the bidirectional Discriminator graph."""
- sequence = tf.cast(sequence, tf.int32)
-
- if FLAGS.dis_share_embedding:
- assert hparams.dis_rnn_size == hparams.gen_rnn_size, (
- 'If you wish to share Discriminator/Generator embeddings, they must be'
- ' same dimension.')
- with tf.variable_scope('gen/rnn', reuse=True):
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
-
- with tf.variable_scope('dis', reuse=reuse):
- cell_fwd = tf.contrib.rnn.LayerNormBasicLSTMCell(
- hparams.dis_rnn_size, forget_bias=1.0, reuse=reuse)
- cell_bwd = tf.contrib.rnn.LayerNormBasicLSTMCell(
- hparams.dis_rnn_size, forget_bias=1.0, reuse=reuse)
- if FLAGS.zoneout_drop_prob > 0.0:
- cell_fwd = zoneout.ZoneoutWrapper(
- cell_fwd,
- zoneout_drop_prob=FLAGS.zoneout_drop_prob,
- is_training=is_training)
- cell_bwd = zoneout.ZoneoutWrapper(
- cell_bwd,
- zoneout_drop_prob=FLAGS.zoneout_drop_prob,
- is_training=is_training)
-
- state_fwd = cell_fwd.zero_state(FLAGS.batch_size, tf.float32)
- state_bwd = cell_bwd.zero_state(FLAGS.batch_size, tf.float32)
-
- if not FLAGS.dis_share_embedding:
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.dis_rnn_size])
-
- rnn_inputs = tf.nn.embedding_lookup(embedding, sequence)
- rnn_inputs = tf.unstack(rnn_inputs, axis=1)
-
- with tf.variable_scope('rnn') as vs:
- outputs, _, _ = tf.contrib.rnn.static_bidirectional_rnn(
- cell_fwd, cell_bwd, rnn_inputs, state_fwd, state_bwd, scope=vs)
-
- # Prediction is linear output for Discriminator.
- predictions = tf.contrib.layers.linear(outputs, 1, scope=vs)
-
- predictions = tf.transpose(predictions, [1, 0, 2])
- return tf.squeeze(predictions, axis=2)
diff --git a/research/maskgan/models/bidirectional_vd.py b/research/maskgan/models/bidirectional_vd.py
deleted file mode 100644
index 469af9da57a8a0dbf280327308a17fa6e0277a86..0000000000000000000000000000000000000000
--- a/research/maskgan/models/bidirectional_vd.py
+++ /dev/null
@@ -1,116 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Simple bidirectional model definitions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-from regularization import variational_dropout
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def discriminator(hparams,
- sequence,
- is_training,
- reuse=None,
- initial_state=None):
- """Define the Discriminator graph."""
- sequence = tf.cast(sequence, tf.int32)
-
- if FLAGS.dis_share_embedding:
- assert hparams.dis_rnn_size == hparams.gen_rnn_size, (
- 'If you wish to share Discriminator/Generator embeddings, they must be'
- ' same dimension.')
- with tf.variable_scope('gen/decoder/rnn', reuse=True):
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
-
- with tf.variable_scope('dis', reuse=reuse):
-
- def lstm_cell():
- return tf.contrib.rnn.BasicLSTMCell(
- hparams.dis_rnn_size,
- forget_bias=0.0,
- state_is_tuple=True,
- reuse=reuse)
-
- attn_cell = lstm_cell
- if is_training and hparams.dis_vd_keep_prob < 1:
-
- def attn_cell():
- return variational_dropout.VariationalDropoutWrapper(
- lstm_cell(), FLAGS.batch_size, hparams.dis_rnn_size,
- hparams.dis_vd_keep_prob, hparams.dis_vd_keep_prob)
-
- cell_fwd = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.dis_num_layers)],
- state_is_tuple=True)
-
- cell_bwd = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.dis_num_layers)],
- state_is_tuple=True)
-
- # print initial_state
- # print cell_fwd.zero_state(FLAGS.batch_size, tf.float32)
- if initial_state:
- state_fwd = [[tf.identity(x) for x in inner_initial_state]
- for inner_initial_state in initial_state]
- state_bwd = cell_bwd.zero_state(FLAGS.batch_size, tf.float32)
- else:
- state_fwd = cell_fwd.zero_state(FLAGS.batch_size, tf.float32)
- state_bwd = cell_bwd.zero_state(FLAGS.batch_size, tf.float32)
-
- def make_mask(keep_prob, units):
- random_tensor = keep_prob
- # 0. if [keep_prob, 1.0) and 1. if [1.0, 1.0 + keep_prob)
- random_tensor += tf.random_uniform(tf.stack([FLAGS.batch_size, units]))
- return tf.floor(random_tensor) / keep_prob
-
- if is_training:
- output_mask = make_mask(hparams.dis_vd_keep_prob,
- 2 * hparams.dis_rnn_size)
-
- if not FLAGS.dis_share_embedding:
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.dis_rnn_size])
-
- rnn_inputs = tf.nn.embedding_lookup(embedding, sequence)
-
- rnn_inputs = tf.unstack(rnn_inputs, axis=1)
-
- with tf.variable_scope('rnn') as vs:
- outputs, _, _ = tf.contrib.rnn.static_bidirectional_rnn(
- cell_fwd, cell_bwd, rnn_inputs, state_fwd, state_bwd, scope=vs)
-
- if is_training:
- outputs *= output_mask
-
- # Prediction is linear output for Discriminator.
- predictions = tf.contrib.layers.linear(outputs, 1, scope=vs)
- predictions = tf.transpose(predictions, [1, 0, 2])
-
- if FLAGS.baseline_method == 'critic':
- with tf.variable_scope('critic', reuse=reuse) as critic_scope:
- values = tf.contrib.layers.linear(outputs, 1, scope=critic_scope)
- values = tf.transpose(values, [1, 0, 2])
-
- return tf.squeeze(predictions, axis=2), tf.squeeze(values, axis=2)
-
- else:
- return tf.squeeze(predictions, axis=2), None
diff --git a/research/maskgan/models/bidirectional_zaremba.py b/research/maskgan/models/bidirectional_zaremba.py
deleted file mode 100644
index b0683d7cc1493a8aa0298b7dc91020a152a9da36..0000000000000000000000000000000000000000
--- a/research/maskgan/models/bidirectional_zaremba.py
+++ /dev/null
@@ -1,83 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Simple bidirectional model definitions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def discriminator(hparams, sequence, is_training, reuse=None):
- """Define the bidirectional Discriminator graph."""
- sequence = tf.cast(sequence, tf.int32)
-
- if FLAGS.dis_share_embedding:
- assert hparams.dis_rnn_size == hparams.gen_rnn_size, (
- 'If you wish to share Discriminator/Generator embeddings, they must be'
- ' same dimension.')
- with tf.variable_scope('gen/rnn', reuse=True):
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
-
- with tf.variable_scope('dis', reuse=reuse):
-
- def lstm_cell():
- return tf.contrib.rnn.BasicLSTMCell(
- hparams.dis_rnn_size,
- forget_bias=0.0,
- state_is_tuple=True,
- reuse=reuse)
-
- attn_cell = lstm_cell
- if is_training and FLAGS.keep_prob < 1:
-
- def attn_cell():
- return tf.contrib.rnn.DropoutWrapper(
- lstm_cell(), output_keep_prob=FLAGS.keep_prob)
-
- cell_fwd = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.dis_num_layers)],
- state_is_tuple=True)
-
- cell_bwd = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.dis_num_layers)],
- state_is_tuple=True)
-
- state_fwd = cell_fwd.zero_state(FLAGS.batch_size, tf.float32)
- state_bwd = cell_bwd.zero_state(FLAGS.batch_size, tf.float32)
-
- if not FLAGS.dis_share_embedding:
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.dis_rnn_size])
-
- rnn_inputs = tf.nn.embedding_lookup(embedding, sequence)
- if is_training and FLAGS.keep_prob < 1:
- rnn_inputs = tf.nn.dropout(rnn_inputs, FLAGS.keep_prob)
- rnn_inputs = tf.unstack(rnn_inputs, axis=1)
-
- with tf.variable_scope('rnn') as vs:
- outputs, _, _ = tf.contrib.rnn.static_bidirectional_rnn(
- cell_fwd, cell_bwd, rnn_inputs, state_fwd, state_bwd, scope=vs)
-
- # Prediction is linear output for Discriminator.
- predictions = tf.contrib.layers.linear(outputs, 1, scope=vs)
-
- predictions = tf.transpose(predictions, [1, 0, 2])
- return tf.squeeze(predictions, axis=2)
diff --git a/research/maskgan/models/cnn.py b/research/maskgan/models/cnn.py
deleted file mode 100644
index ca682debf1630f5773cef48b874334d28d1fc6fc..0000000000000000000000000000000000000000
--- a/research/maskgan/models/cnn.py
+++ /dev/null
@@ -1,93 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Simple CNN model definitions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def discriminator(hparams, sequence, is_training, reuse=None):
- """Define the Discriminator graph."""
- del is_training
- sequence = tf.cast(sequence, tf.int32)
-
- if FLAGS.dis_share_embedding:
- assert hparams.dis_rnn_size == hparams.gen_rnn_size, (
- "If you wish to share Discriminator/Generator embeddings, they must be"
- " same dimension.")
- with tf.variable_scope("gen/rnn", reuse=True):
- embedding = tf.get_variable("embedding",
- [FLAGS.vocab_size, hparams.gen_rnn_size])
-
- dis_filter_sizes = [3, 4, 5, 6, 7, 8, 9, 10, 15, 20]
-
- with tf.variable_scope("dis", reuse=reuse):
- if not FLAGS.dis_share_embedding:
- embedding = tf.get_variable("embedding",
- [FLAGS.vocab_size, hparams.dis_rnn_size])
- cnn_inputs = tf.nn.embedding_lookup(embedding, sequence)
-
- # Create a convolution layer for each filter size
- conv_outputs = []
- for filter_size in dis_filter_sizes:
- with tf.variable_scope("conv-%s" % filter_size):
- # Convolution Layer
- filter_shape = [
- filter_size, hparams.dis_rnn_size, hparams.dis_num_filters
- ]
- W = tf.get_variable(
- name="W", initializer=tf.truncated_normal(filter_shape, stddev=0.1))
- b = tf.get_variable(
- name="b",
- initializer=tf.constant(0.1, shape=[hparams.dis_num_filters]))
- conv = tf.nn.conv1d(
- cnn_inputs, W, stride=1, padding="SAME", name="conv")
-
- # Apply nonlinearity
- h = tf.nn.relu(tf.nn.bias_add(conv, b), name="relu")
-
- conv_outputs.append(h)
-
- # Combine all the pooled features
- dis_num_filters_total = hparams.dis_num_filters * len(dis_filter_sizes)
-
- h_conv = tf.concat(conv_outputs, axis=2)
- h_conv_flat = tf.reshape(h_conv, [-1, dis_num_filters_total])
-
- # Add dropout
- with tf.variable_scope("dropout"):
- h_drop = tf.nn.dropout(h_conv_flat, FLAGS.keep_prob)
-
- with tf.variable_scope("fully_connected"):
- fc = tf.contrib.layers.fully_connected(
- h_drop, num_outputs=dis_num_filters_total / 2)
-
- # Final (unnormalized) scores and predictions
- with tf.variable_scope("output"):
- W = tf.get_variable(
- "W",
- shape=[dis_num_filters_total / 2, 1],
- initializer=tf.contrib.layers.xavier_initializer())
- b = tf.get_variable(name="b", initializer=tf.constant(0.1, shape=[1]))
- predictions = tf.nn.xw_plus_b(fc, W, b, name="predictions")
- predictions = tf.reshape(
- predictions, shape=[FLAGS.batch_size, FLAGS.sequence_length])
- return predictions
diff --git a/research/maskgan/models/critic_vd.py b/research/maskgan/models/critic_vd.py
deleted file mode 100644
index ede8b7bb77af28f562c2e3942728899fe9b16422..0000000000000000000000000000000000000000
--- a/research/maskgan/models/critic_vd.py
+++ /dev/null
@@ -1,108 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Critic model definitions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from six.moves import xrange
-import tensorflow as tf
-from regularization import variational_dropout
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def critic_seq2seq_vd_derivative(hparams, sequence, is_training, reuse=None):
- """Define the Critic graph which is derived from the seq2seq_vd
- Discriminator. This will be initialized with the same parameters as the
- language model and will share the forward RNN components with the
- Discriminator. This estimates the V(s_t), where the state
- s_t = x_0,...,x_t-1.
- """
- assert FLAGS.discriminator_model == 'seq2seq_vd'
- sequence = tf.cast(sequence, tf.int32)
-
- if FLAGS.dis_share_embedding:
- assert hparams.dis_rnn_size == hparams.gen_rnn_size, (
- 'If you wish to share Discriminator/Generator embeddings, they must be'
- ' same dimension.')
- with tf.variable_scope('gen/decoder/rnn', reuse=True):
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
- else:
- with tf.variable_scope('dis/decoder/rnn', reuse=True):
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.dis_rnn_size])
-
- with tf.variable_scope(
- 'dis/decoder/rnn/multi_rnn_cell', reuse=True) as dis_scope:
-
- def lstm_cell():
- return tf.contrib.rnn.BasicLSTMCell(
- hparams.dis_rnn_size,
- forget_bias=0.0,
- state_is_tuple=True,
- reuse=True)
-
- attn_cell = lstm_cell
- if is_training and hparams.dis_vd_keep_prob < 1:
-
- def attn_cell():
- return variational_dropout.VariationalDropoutWrapper(
- lstm_cell(), FLAGS.batch_size, hparams.dis_rnn_size,
- hparams.dis_vd_keep_prob, hparams.dis_vd_keep_prob)
-
- cell_critic = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.dis_num_layers)],
- state_is_tuple=True)
-
- with tf.variable_scope('critic', reuse=reuse):
- state_dis = cell_critic.zero_state(FLAGS.batch_size, tf.float32)
-
- def make_mask(keep_prob, units):
- random_tensor = keep_prob
- # 0. if [keep_prob, 1.0) and 1. if [1.0, 1.0 + keep_prob)
- random_tensor += tf.random_uniform(tf.stack([FLAGS.batch_size, units]))
- return tf.floor(random_tensor) / keep_prob
-
- if is_training:
- output_mask = make_mask(hparams.dis_vd_keep_prob, hparams.dis_rnn_size)
-
- with tf.variable_scope('rnn') as vs:
- values = []
-
- rnn_inputs = tf.nn.embedding_lookup(embedding, sequence)
-
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- if t == 0:
- rnn_in = tf.zeros_like(rnn_inputs[:, 0])
- else:
- rnn_in = rnn_inputs[:, t - 1]
- rnn_out, state_dis = cell_critic(rnn_in, state_dis, scope=dis_scope)
-
- if is_training:
- rnn_out *= output_mask
-
- # Prediction is linear output for Discriminator.
- value = tf.contrib.layers.linear(rnn_out, 1, scope=vs)
-
- values.append(value)
- values = tf.stack(values, axis=1)
- return tf.squeeze(values, axis=2)
diff --git a/research/maskgan/models/evaluation_utils.py b/research/maskgan/models/evaluation_utils.py
deleted file mode 100644
index fc2a3a16f0b2c03736bfaa881c5c14546240d283..0000000000000000000000000000000000000000
--- a/research/maskgan/models/evaluation_utils.py
+++ /dev/null
@@ -1,280 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Evaluation utilities."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from collections import Counter
-# Dependency imports
-import numpy as np
-from scipy.special import expit
-
-import tensorflow as tf
-
-from model_utils import helper
-from model_utils import n_gram
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def print_and_log_losses(log, step, is_present_rate, avg_dis_loss,
- avg_gen_loss):
- """Prints and logs losses to the log file.
-
- Args:
- log: GFile for logs.
- step: Global step.
- is_present_rate: Current masking rate.
- avg_dis_loss: List of Discriminator losses.
- avg_gen_loss: List of Generator losses.
- """
- print('global_step: %d' % step)
- print(' is_present_rate: %.3f' % is_present_rate)
- print(' D train loss: %.5f' % np.mean(avg_dis_loss))
- print(' G train loss: %.5f' % np.mean(avg_gen_loss))
- log.write('\nglobal_step: %d\n' % step)
- log.write((' is_present_rate: %.3f\n' % is_present_rate))
- log.write(' D train loss: %.5f\n' % np.mean(avg_dis_loss))
- log.write(' G train loss: %.5f\n' % np.mean(avg_gen_loss))
-
-
-def print_and_log(log, id_to_word, sequence_eval, max_num_to_print=5):
- """Helper function for printing and logging evaluated sequences."""
- indices_arr = np.asarray(sequence_eval)
- samples = helper.convert_to_human_readable(id_to_word, indices_arr,
- max_num_to_print)
-
- for i, sample in enumerate(samples):
- print('Sample', i, '. ', sample)
- log.write('\nSample ' + str(i) + '. ' + sample)
- log.write('\n')
- print('\n')
- log.flush()
- return samples
-
-
-def zip_seq_pred_crossent(id_to_word, sequences, predictions, cross_entropy):
- """Zip together the sequences, predictions, cross entropy."""
- indices = np.asarray(sequences)
-
- batch_of_metrics = []
-
- for ind_batch, pred_batch, crossent_batch in zip(indices, predictions,
- cross_entropy):
- metrics = []
-
- for index, pred, crossent in zip(ind_batch, pred_batch, crossent_batch):
- metrics.append([str(id_to_word[index]), pred, crossent])
-
- batch_of_metrics.append(metrics)
- return batch_of_metrics
-
-
-def zip_metrics(indices, *args):
- """Zip together the indices matrices with the provided metrics matrices."""
- batch_of_metrics = []
- for metrics_batch in zip(indices, *args):
-
- metrics = []
- for m in zip(*metrics_batch):
- metrics.append(m)
- batch_of_metrics.append(metrics)
- return batch_of_metrics
-
-
-def print_formatted(present, id_to_word, log, batch_of_tuples):
- """Print and log metrics."""
- num_cols = len(batch_of_tuples[0][0])
- repeat_float_format = '{:<12.3f} '
- repeat_str_format = '{:<13}'
-
- format_str = ''.join(
- ['[{:<1}] {:<20}',
- str(repeat_float_format * (num_cols - 1))])
-
- # TODO(liamfedus): Generalize the logging. This is sloppy.
- header_format_str = ''.join(
- ['[{:<1}] {:<20}',
- str(repeat_str_format * (num_cols - 1))])
- header_str = header_format_str.format('p', 'Word', 'p(real)', 'log-perp',
- 'log(p(a))', 'r', 'R=V*(s)', 'b=V(s)',
- 'A(a,s)')
-
- for i, batch in enumerate(batch_of_tuples):
- print(' Sample: %d' % i)
- log.write(' Sample %d.\n' % i)
- print(' ', header_str)
- log.write(' ' + str(header_str) + '\n')
-
- for j, t in enumerate(batch):
- t = list(t)
- t[0] = id_to_word[t[0]]
- buffer_str = format_str.format(int(present[i][j]), *t)
- print(' ', buffer_str)
- log.write(' ' + str(buffer_str) + '\n')
- log.flush()
-
-
-def generate_RL_logs(sess, model, log, id_to_word, feed):
- """Generate complete logs while running with REINFORCE."""
- # Impute Sequences.
- [
- p,
- fake_sequence_eval,
- fake_predictions_eval,
- _,
- fake_cross_entropy_losses_eval,
- _,
- fake_log_probs_eval,
- fake_rewards_eval,
- fake_baselines_eval,
- cumulative_rewards_eval,
- fake_advantages_eval,
- ] = sess.run(
- [
- model.present,
- model.fake_sequence,
- model.fake_predictions,
- model.real_predictions,
- model.fake_cross_entropy_losses,
- model.fake_logits,
- model.fake_log_probs,
- model.fake_rewards,
- model.fake_baselines,
- model.cumulative_rewards,
- model.fake_advantages,
- ],
- feed_dict=feed)
-
- indices = np.asarray(fake_sequence_eval)
-
- # Convert Discriminator linear layer to probability.
- fake_prob_eval = expit(fake_predictions_eval)
-
- # Add metrics.
- fake_tuples = zip_metrics(indices, fake_prob_eval,
- fake_cross_entropy_losses_eval, fake_log_probs_eval,
- fake_rewards_eval, cumulative_rewards_eval,
- fake_baselines_eval, fake_advantages_eval)
-
- # real_tuples = zip_metrics(indices, )
-
- # Print forward sequences.
- tuples_to_print = fake_tuples[:FLAGS.max_num_to_print]
- print_formatted(p, id_to_word, log, tuples_to_print)
-
- print('Samples')
- log.write('Samples\n')
- samples = print_and_log(log, id_to_word, fake_sequence_eval,
- FLAGS.max_num_to_print)
- return samples
-
-
-def generate_logs(sess, model, log, id_to_word, feed):
- """Impute Sequences using the model for a particular feed and send it to
- logs."""
- # Impute Sequences.
- [
- p, sequence_eval, fake_predictions_eval, fake_cross_entropy_losses_eval,
- fake_logits_eval
- ] = sess.run(
- [
- model.present, model.fake_sequence, model.fake_predictions,
- model.fake_cross_entropy_losses, model.fake_logits
- ],
- feed_dict=feed)
-
- # Convert Discriminator linear layer to probability.
- fake_prob_eval = expit(fake_predictions_eval)
-
- # Forward Masked Tuples.
- fake_tuples = zip_seq_pred_crossent(id_to_word, sequence_eval, fake_prob_eval,
- fake_cross_entropy_losses_eval)
-
- tuples_to_print = fake_tuples[:FLAGS.max_num_to_print]
-
- if FLAGS.print_verbose:
- print('fake_logits_eval')
- print(fake_logits_eval)
-
- for i, batch in enumerate(tuples_to_print):
- print(' Sample %d.' % i)
- log.write(' Sample %d.\n' % i)
- for j, pred in enumerate(batch):
- buffer_str = ('[{:<1}] {:<20} {:<7.3f} {:<7.3f}').format(
- int(p[i][j]), pred[0], pred[1], pred[2])
- print(' ', buffer_str)
- log.write(' ' + str(buffer_str) + '\n')
- log.flush()
-
- print('Samples')
- log.write('Samples\n')
- samples = print_and_log(log, id_to_word, sequence_eval,
- FLAGS.max_num_to_print)
- return samples
-
-
-def create_merged_ngram_dictionaries(indices, n):
- """Generate a single dictionary for the full batch.
-
- Args:
- indices: List of lists of indices.
- n: Degree of n-grams.
-
- Returns:
- Dictionary of hashed(n-gram tuples) to counts in the batch of indices.
- """
- ngram_dicts = []
-
- for ind in indices:
- ngrams = n_gram.find_all_ngrams(ind, n=n)
- ngram_counts = n_gram.construct_ngrams_dict(ngrams)
- ngram_dicts.append(ngram_counts)
-
- merged_gen_dict = Counter()
- for ngram_dict in ngram_dicts:
- merged_gen_dict += Counter(ngram_dict)
- return merged_gen_dict
-
-
-def sequence_ngram_evaluation(sess, sequence, log, feed, data_ngram_count, n):
- """Calculates the percent of ngrams produced in the sequence is present in
- data_ngram_count.
-
- Args:
- sess: tf.Session.
- sequence: Sequence Tensor from the MaskGAN model.
- log: gFile log.
- feed: Feed to evaluate.
- data_ngram_count: Dictionary of hashed(n-gram tuples) to counts in the
- data_set.
-
- Returns:
- avg_percent_captured: Percent of produced ngrams that appear in the
- data_ngram_count.
- """
- del log
- # Impute sequence.
- [sequence_eval] = sess.run([sequence], feed_dict=feed)
- indices = sequence_eval
-
- # Retrieve the counts across the batch of indices.
- gen_ngram_counts = create_merged_ngram_dictionaries(
- indices, n=n)
- return n_gram.percent_unique_ngrams_in_train(data_ngram_count,
- gen_ngram_counts)
diff --git a/research/maskgan/models/feedforward.py b/research/maskgan/models/feedforward.py
deleted file mode 100644
index d48a517d6bea65477b8a940ed770f92203da6dfd..0000000000000000000000000000000000000000
--- a/research/maskgan/models/feedforward.py
+++ /dev/null
@@ -1,98 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Simple FNN model definitions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from six.moves import xrange
-import tensorflow as tf
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def discriminator(hparams, sequence, is_training, reuse=None):
- """Define the Discriminator graph."""
- del is_training
- sequence = tf.cast(sequence, tf.int32)
-
- if FLAGS.dis_share_embedding:
- assert hparams.dis_rnn_size == hparams.gen_rnn_size, (
- "If you wish to share Discriminator/Generator embeddings, they must be"
- " same dimension.")
- with tf.variable_scope("gen/rnn", reuse=True):
- embedding = tf.get_variable("embedding",
- [FLAGS.vocab_size, hparams.gen_rnn_size])
-
- with tf.variable_scope("dis", reuse=reuse):
- if not FLAGS.dis_share_embedding:
- embedding = tf.get_variable("embedding",
- [FLAGS.vocab_size, hparams.dis_rnn_size])
-
- embeddings = tf.nn.embedding_lookup(embedding, sequence)
-
- # Input matrices.
- W = tf.get_variable(
- "W",
- initializer=tf.truncated_normal(
- shape=[3 * hparams.dis_embedding_dim, hparams.dis_hidden_dim],
- stddev=0.1))
- b = tf.get_variable(
- "b", initializer=tf.constant(0.1, shape=[hparams.dis_hidden_dim]))
-
- # Output matrices.
- W_out = tf.get_variable(
- "W_out",
- initializer=tf.truncated_normal(
- shape=[hparams.dis_hidden_dim, 1], stddev=0.1))
- b_out = tf.get_variable("b_out", initializer=tf.constant(0.1, shape=[1]))
-
- predictions = []
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- inp = embeddings[:, t]
-
- if t > 0:
- past_inp = tf.unstack(embeddings[:, 0:t], axis=1)
- avg_past_inp = tf.add_n(past_inp) / len(past_inp)
- else:
- avg_past_inp = tf.zeros_like(inp)
-
- if t < FLAGS.sequence_length:
- future_inp = tf.unstack(embeddings[:, t:], axis=1)
- avg_future_inp = tf.add_n(future_inp) / len(future_inp)
- else:
- avg_future_inp = tf.zeros_like(inp)
-
- # Cumulative input.
- concat_inp = tf.concat([avg_past_inp, inp, avg_future_inp], axis=1)
-
- # Hidden activations.
- hidden = tf.nn.relu(tf.nn.xw_plus_b(concat_inp, W, b, name="scores"))
-
- # Add dropout
- with tf.variable_scope("dropout"):
- hidden = tf.nn.dropout(hidden, FLAGS.keep_prob)
-
- # Output.
- output = tf.nn.xw_plus_b(hidden, W_out, b_out, name="output")
-
- predictions.append(output)
- predictions = tf.stack(predictions, axis=1)
- return tf.squeeze(predictions, axis=2)
diff --git a/research/maskgan/models/rnn.py b/research/maskgan/models/rnn.py
deleted file mode 100644
index 40b3a7aa3b85ddfd3002d845416b5004088620fc..0000000000000000000000000000000000000000
--- a/research/maskgan/models/rnn.py
+++ /dev/null
@@ -1,211 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Simple RNN model definitions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from six.moves import xrange
-import tensorflow as tf
-
-# ZoneoutWrapper.
-from regularization import zoneout
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def generator(hparams,
- inputs,
- targets,
- targets_present,
- is_training,
- is_validating,
- reuse=None):
- """Define the Generator graph.
-
- G will now impute tokens that have been masked from the input seqeunce.
- """
- tf.logging.warning(
- 'Undirectional generative model is not a useful model for this MaskGAN '
- 'because future context is needed. Use only for debugging purposes.')
- init_scale = 0.05
- initializer = tf.random_uniform_initializer(-init_scale, init_scale)
-
- with tf.variable_scope('gen', reuse=reuse, initializer=initializer):
-
- def lstm_cell():
- return tf.contrib.rnn.LayerNormBasicLSTMCell(
- hparams.gen_rnn_size, reuse=reuse)
-
- attn_cell = lstm_cell
- if FLAGS.zoneout_drop_prob > 0.0:
-
- def attn_cell():
- return zoneout.ZoneoutWrapper(
- lstm_cell(),
- zoneout_drop_prob=FLAGS.zoneout_drop_prob,
- is_training=is_training)
-
- cell_gen = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.gen_num_layers)],
- state_is_tuple=True)
-
- initial_state = cell_gen.zero_state(FLAGS.batch_size, tf.float32)
-
- with tf.variable_scope('rnn'):
- sequence, logits, log_probs = [], [], []
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
- softmax_w = tf.get_variable('softmax_w',
- [hparams.gen_rnn_size, FLAGS.vocab_size])
- softmax_b = tf.get_variable('softmax_b', [FLAGS.vocab_size])
-
- rnn_inputs = tf.nn.embedding_lookup(embedding, inputs)
-
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- # Input to the model is the first token to provide context. The
- # model will then predict token t > 0.
- if t == 0:
- # Always provide the real input at t = 0.
- state_gen = initial_state
- rnn_inp = rnn_inputs[:, t]
-
- # If the target at the last time-step was present, read in the real.
- # If the target at the last time-step was not present, read in the fake.
- else:
- real_rnn_inp = rnn_inputs[:, t]
- fake_rnn_inp = tf.nn.embedding_lookup(embedding, fake)
-
- # Use teacher forcing.
- if (is_training and
- FLAGS.gen_training_strategy == 'cross_entropy') or is_validating:
- rnn_inp = real_rnn_inp
- else:
- # Note that targets_t-1 == inputs_(t)
- rnn_inp = tf.where(targets_present[:, t - 1], real_rnn_inp,
- fake_rnn_inp)
-
- # RNN.
- rnn_out, state_gen = cell_gen(rnn_inp, state_gen)
- logit = tf.matmul(rnn_out, softmax_w) + softmax_b
-
- # Real sample.
- real = targets[:, t]
-
- # Fake sample.
- categorical = tf.contrib.distributions.Categorical(logits=logit)
- fake = categorical.sample()
- log_prob = categorical.log_prob(fake)
-
- # Output for Generator will either be generated or the target.
- # If present: Return real.
- # If not present: Return fake.
- output = tf.where(targets_present[:, t], real, fake)
-
- # Append to lists.
- sequence.append(output)
- logits.append(logit)
- log_probs.append(log_prob)
-
- # Produce the RNN state had the model operated only
- # over real data.
- real_state_gen = initial_state
- for t in xrange(FLAGS.sequence_length):
- tf.get_variable_scope().reuse_variables()
-
- rnn_inp = rnn_inputs[:, t]
-
- # RNN.
- rnn_out, real_state_gen = cell_gen(rnn_inp, real_state_gen)
-
- final_state = real_state_gen
-
- return (tf.stack(sequence, axis=1), tf.stack(logits, axis=1), tf.stack(
- log_probs, axis=1), initial_state, final_state)
-
-
-def discriminator(hparams, sequence, is_training, reuse=None):
- """Define the Discriminator graph.
-
- Args:
- hparams: Hyperparameters for the MaskGAN.
- FLAGS: Current flags.
- sequence: [FLAGS.batch_size, FLAGS.sequence_length]
- is_training:
- reuse
-
- Returns:
- predictions:
- """
- tf.logging.warning(
- 'Undirectional Discriminative model is not a useful model for this '
- 'MaskGAN because future context is needed. Use only for debugging '
- 'purposes.')
- sequence = tf.cast(sequence, tf.int32)
-
- if FLAGS.dis_share_embedding:
- assert hparams.dis_rnn_size == hparams.gen_rnn_size, (
- 'If you wish to share Discriminator/Generator embeddings, they must be'
- ' same dimension.')
- with tf.variable_scope('gen/rnn', reuse=True):
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
-
- with tf.variable_scope('dis', reuse=reuse):
-
- def lstm_cell():
- return tf.contrib.rnn.LayerNormBasicLSTMCell(
- hparams.dis_rnn_size, reuse=reuse)
-
- attn_cell = lstm_cell
- if FLAGS.zoneout_drop_prob > 0.0:
-
- def attn_cell():
- return zoneout.ZoneoutWrapper(
- lstm_cell(),
- zoneout_drop_prob=FLAGS.zoneout_drop_prob,
- is_training=is_training)
-
- cell_dis = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.dis_num_layers)],
- state_is_tuple=True)
- state_dis = cell_dis.zero_state(FLAGS.batch_size, tf.float32)
-
- with tf.variable_scope('rnn') as vs:
- predictions = []
- if not FLAGS.dis_share_embedding:
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.dis_rnn_size])
-
- rnn_inputs = tf.nn.embedding_lookup(embedding, sequence)
-
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- rnn_in = rnn_inputs[:, t]
- rnn_out, state_dis = cell_dis(rnn_in, state_dis)
-
- # Prediction is linear output for Discriminator.
- pred = tf.contrib.layers.linear(rnn_out, 1, scope=vs)
-
- predictions.append(pred)
- predictions = tf.stack(predictions, axis=1)
- return tf.squeeze(predictions, axis=2)
diff --git a/research/maskgan/models/rnn_nas.py b/research/maskgan/models/rnn_nas.py
deleted file mode 100644
index 618ace2f8196fb4718ae01bc406f114523fd44cc..0000000000000000000000000000000000000000
--- a/research/maskgan/models/rnn_nas.py
+++ /dev/null
@@ -1,234 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Simple RNN model definitions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-from six.moves import xrange
-import tensorflow as tf
-
-# NAS Code..
-from nas_utils import configs
-from nas_utils import custom_cell
-from nas_utils import variational_dropout
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def get_config():
- return configs.AlienConfig2()
-
-
-LSTMTuple = collections.namedtuple('LSTMTuple', ['c', 'h'])
-
-
-def generator(hparams,
- inputs,
- targets,
- targets_present,
- is_training,
- is_validating,
- reuse=None):
- """Define the Generator graph.
-
- G will now impute tokens that have been masked from the input seqeunce.
- """
- tf.logging.info(
- 'Undirectional generative model is not a useful model for this MaskGAN '
- 'because future context is needed. Use only for debugging purposes.')
- config = get_config()
- config.keep_prob = [hparams.gen_nas_keep_prob_0, hparams.gen_nas_keep_prob_1]
- configs.print_config(config)
-
- init_scale = config.init_scale
- initializer = tf.random_uniform_initializer(-init_scale, init_scale)
-
- with tf.variable_scope('gen', reuse=reuse, initializer=initializer):
- # Neural architecture search cell.
- cell = custom_cell.Alien(config.hidden_size)
-
- if is_training:
- [h2h_masks, _, _,
- output_mask] = variational_dropout.generate_variational_dropout_masks(
- hparams, config.keep_prob)
- else:
- output_mask = None
-
- cell_gen = custom_cell.GenericMultiRNNCell([cell] * config.num_layers)
- initial_state = cell_gen.zero_state(FLAGS.batch_size, tf.float32)
-
- with tf.variable_scope('rnn'):
- sequence, logits, log_probs = [], [], []
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
- softmax_w = tf.matrix_transpose(embedding)
- softmax_b = tf.get_variable('softmax_b', [FLAGS.vocab_size])
-
- rnn_inputs = tf.nn.embedding_lookup(embedding, inputs)
-
- if is_training and FLAGS.keep_prob < 1:
- rnn_inputs = tf.nn.dropout(rnn_inputs, FLAGS.keep_prob)
-
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- # Input to the model is the first token to provide context. The
- # model will then predict token t > 0.
- if t == 0:
- # Always provide the real input at t = 0.
- state_gen = initial_state
- rnn_inp = rnn_inputs[:, t]
-
- # If the input is present, read in the input at t.
- # If the input is not present, read in the previously generated.
- else:
- real_rnn_inp = rnn_inputs[:, t]
- fake_rnn_inp = tf.nn.embedding_lookup(embedding, fake)
-
- # While validating, the decoder should be operating in teacher
- # forcing regime. Also, if we're just training with cross_entropy
- # use teacher forcing.
- if is_validating or (is_training and
- FLAGS.gen_training_strategy == 'cross_entropy'):
- rnn_inp = real_rnn_inp
- else:
- rnn_inp = tf.where(targets_present[:, t - 1], real_rnn_inp,
- fake_rnn_inp)
-
- if is_training:
- state_gen = list(state_gen)
- for layer_num, per_layer_state in enumerate(state_gen):
- per_layer_state = LSTMTuple(
- per_layer_state[0], per_layer_state[1] * h2h_masks[layer_num])
- state_gen[layer_num] = per_layer_state
-
- # RNN.
- rnn_out, state_gen = cell_gen(rnn_inp, state_gen)
-
- if is_training:
- rnn_out = output_mask * rnn_out
-
- logit = tf.matmul(rnn_out, softmax_w) + softmax_b
-
- # Real sample.
- real = targets[:, t]
-
- categorical = tf.contrib.distributions.Categorical(logits=logit)
- fake = categorical.sample()
- log_prob = categorical.log_prob(fake)
-
- # Output for Generator will either be generated or the input.
- #
- # If present: Return real.
- # If not present: Return fake.
- output = tf.where(targets_present[:, t], real, fake)
-
- # Add to lists.
- sequence.append(output)
- log_probs.append(log_prob)
- logits.append(logit)
-
- # Produce the RNN state had the model operated only
- # over real data.
- real_state_gen = initial_state
- for t in xrange(FLAGS.sequence_length):
- tf.get_variable_scope().reuse_variables()
-
- rnn_inp = rnn_inputs[:, t]
-
- # RNN.
- rnn_out, real_state_gen = cell_gen(rnn_inp, real_state_gen)
-
- final_state = real_state_gen
-
- return (tf.stack(sequence, axis=1), tf.stack(logits, axis=1), tf.stack(
- log_probs, axis=1), initial_state, final_state)
-
-
-def discriminator(hparams, sequence, is_training, reuse=None):
- """Define the Discriminator graph."""
- tf.logging.info(
- 'Undirectional Discriminative model is not a useful model for this '
- 'MaskGAN because future context is needed. Use only for debugging '
- 'purposes.')
- sequence = tf.cast(sequence, tf.int32)
-
- if FLAGS.dis_share_embedding:
- assert hparams.dis_rnn_size == hparams.gen_rnn_size, (
- 'If you wish to share Discriminator/Generator embeddings, they must be'
- ' same dimension.')
- with tf.variable_scope('gen/rnn', reuse=True):
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
-
- config = get_config()
- config.keep_prob = [hparams.dis_nas_keep_prob_0, hparams.dis_nas_keep_prob_1]
- configs.print_config(config)
-
- with tf.variable_scope('dis', reuse=reuse):
- # Neural architecture search cell.
- cell = custom_cell.Alien(config.hidden_size)
-
- if is_training:
- [h2h_masks, _, _,
- output_mask] = variational_dropout.generate_variational_dropout_masks(
- hparams, config.keep_prob)
- else:
- output_mask = None
-
- cell_dis = custom_cell.GenericMultiRNNCell([cell] * config.num_layers)
- state_dis = cell_dis.zero_state(FLAGS.batch_size, tf.float32)
-
- with tf.variable_scope('rnn') as vs:
- predictions = []
- if not FLAGS.dis_share_embedding:
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.dis_rnn_size])
-
- rnn_inputs = tf.nn.embedding_lookup(embedding, sequence)
-
- if is_training and FLAGS.keep_prob < 1:
- rnn_inputs = tf.nn.dropout(rnn_inputs, FLAGS.keep_prob)
-
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- rnn_in = rnn_inputs[:, t]
-
- if is_training:
- state_dis = list(state_dis)
- for layer_num, per_layer_state in enumerate(state_dis):
- per_layer_state = LSTMTuple(
- per_layer_state[0], per_layer_state[1] * h2h_masks[layer_num])
- state_dis[layer_num] = per_layer_state
-
- # RNN.
- rnn_out, state_dis = cell_dis(rnn_in, state_dis)
-
- if is_training:
- rnn_out = output_mask * rnn_out
-
- # Prediction is linear output for Discriminator.
- pred = tf.contrib.layers.linear(rnn_out, 1, scope=vs)
-
- predictions.append(pred)
- predictions = tf.stack(predictions, axis=1)
- return tf.squeeze(predictions, axis=2)
diff --git a/research/maskgan/models/rnn_vd.py b/research/maskgan/models/rnn_vd.py
deleted file mode 100644
index 428f1a54bda7d6e5f9dd55061149664b1b3e751d..0000000000000000000000000000000000000000
--- a/research/maskgan/models/rnn_vd.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Simple RNN model definitions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from six.moves import xrange
-import tensorflow as tf
-from regularization import variational_dropout
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def discriminator(hparams,
- sequence,
- is_training,
- reuse=None,
- initial_state=None):
- """Define the Discriminator graph."""
- tf.logging.info(
- 'Undirectional Discriminative model is not a useful model for this '
- 'MaskGAN because future context is needed. Use only for debugging '
- 'purposes.')
- sequence = tf.cast(sequence, tf.int32)
-
- if FLAGS.dis_share_embedding:
- assert hparams.dis_rnn_size == hparams.gen_rnn_size, (
- 'If you wish to share Discriminator/Generator embeddings, they must be'
- ' same dimension.')
- with tf.variable_scope('gen/decoder/rnn', reuse=True):
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
-
- with tf.variable_scope('dis', reuse=reuse):
-
- def lstm_cell():
- return tf.contrib.rnn.BasicLSTMCell(
- hparams.dis_rnn_size,
- forget_bias=0.0,
- state_is_tuple=True,
- reuse=reuse)
-
- attn_cell = lstm_cell
- if is_training and hparams.dis_vd_keep_prob < 1:
-
- def attn_cell():
- return variational_dropout.VariationalDropoutWrapper(
- lstm_cell(), FLAGS.batch_size, hparams.dis_rnn_size,
- hparams.dis_vd_keep_prob, hparams.dis_vd_keep_prob)
-
- cell_dis = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.dis_num_layers)],
- state_is_tuple=True)
-
- if initial_state:
- state_dis = [[tf.identity(x) for x in inner_initial_state]
- for inner_initial_state in initial_state]
- else:
- state_dis = cell_dis.zero_state(FLAGS.batch_size, tf.float32)
-
- def make_mask(keep_prob, units):
- random_tensor = keep_prob
- # 0. if [keep_prob, 1.0) and 1. if [1.0, 1.0 + keep_prob)
- random_tensor += tf.random_uniform(tf.stack([FLAGS.batch_size, units]))
- return tf.floor(random_tensor) / keep_prob
-
- if is_training:
- output_mask = make_mask(hparams.dis_vd_keep_prob, hparams.dis_rnn_size)
-
- with tf.variable_scope('rnn') as vs:
- predictions, rnn_outs = [], []
-
- if not FLAGS.dis_share_embedding:
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.dis_rnn_size])
-
- rnn_inputs = tf.nn.embedding_lookup(embedding, sequence)
-
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- rnn_in = rnn_inputs[:, t]
- rnn_out, state_dis = cell_dis(rnn_in, state_dis)
-
- if is_training:
- rnn_out *= output_mask
-
- # Prediction is linear output for Discriminator.
- pred = tf.contrib.layers.linear(rnn_out, 1, scope=vs)
- predictions.append(pred)
- rnn_outs.append(rnn_out)
-
- predictions = tf.stack(predictions, axis=1)
-
- if FLAGS.baseline_method == 'critic':
- with tf.variable_scope('critic', reuse=reuse) as critic_scope:
- rnn_outs = tf.stack(rnn_outs, axis=1)
- values = tf.contrib.layers.linear(rnn_outs, 1, scope=critic_scope)
- return tf.squeeze(predictions, axis=2), tf.squeeze(values, axis=2)
-
- else:
- return tf.squeeze(predictions, axis=2), None
diff --git a/research/maskgan/models/rnn_zaremba.py b/research/maskgan/models/rnn_zaremba.py
deleted file mode 100644
index 9369c77fbb849551721b46321e6868a7aeaceea6..0000000000000000000000000000000000000000
--- a/research/maskgan/models/rnn_zaremba.py
+++ /dev/null
@@ -1,196 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Simple RNN model definitions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from six.moves import xrange
-import tensorflow as tf
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def generator(hparams,
- inputs,
- targets,
- targets_present,
- is_training,
- is_validating,
- reuse=None):
- """Define the Generator graph.
-
- G will now impute tokens that have been masked from the input seqeunce.
- """
- tf.logging.warning(
- 'Undirectional generative model is not a useful model for this MaskGAN '
- 'because future context is needed. Use only for debugging purposes.')
- init_scale = 0.05
- initializer = tf.random_uniform_initializer(-init_scale, init_scale)
- with tf.variable_scope('gen', reuse=reuse, initializer=initializer):
-
- def lstm_cell():
- return tf.contrib.rnn.BasicLSTMCell(hparams.gen_rnn_size,
- forget_bias=0.0,
- state_is_tuple=True,
- reuse=reuse)
-
- attn_cell = lstm_cell
- if is_training and FLAGS.keep_prob < 1:
-
- def attn_cell():
- return tf.contrib.rnn.DropoutWrapper(
- lstm_cell(), output_keep_prob=FLAGS.keep_prob)
-
- cell_gen = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.gen_num_layers)],
- state_is_tuple=True)
-
- initial_state = cell_gen.zero_state(FLAGS.batch_size, tf.float32)
-
- with tf.variable_scope('rnn'):
- sequence, logits, log_probs = [], [], []
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
- softmax_w = tf.get_variable('softmax_w',
- [hparams.gen_rnn_size, FLAGS.vocab_size])
- softmax_b = tf.get_variable('softmax_b', [FLAGS.vocab_size])
-
- rnn_inputs = tf.nn.embedding_lookup(embedding, inputs)
-
- if is_training and FLAGS.keep_prob < 1:
- rnn_inputs = tf.nn.dropout(rnn_inputs, FLAGS.keep_prob)
-
- fake = None
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- # Input to the model is the first token to provide context. The
- # model will then predict token t > 0.
- if t == 0:
- # Always provide the real input at t = 0.
- state_gen = initial_state
- rnn_inp = rnn_inputs[:, t]
-
- # If the input is present, read in the input at t.
- # If the input is not present, read in the previously generated.
- else:
- real_rnn_inp = rnn_inputs[:, t]
- fake_rnn_inp = tf.nn.embedding_lookup(embedding, fake)
-
- # While validating, the decoder should be operating in teacher
- # forcing regime. Also, if we're just training with cross_entropy
- # use teacher forcing.
- if is_validating or (is_training and
- FLAGS.gen_training_strategy == 'cross_entropy'):
- rnn_inp = real_rnn_inp
- else:
- rnn_inp = tf.where(targets_present[:, t - 1], real_rnn_inp,
- fake_rnn_inp)
-
- # RNN.
- rnn_out, state_gen = cell_gen(rnn_inp, state_gen)
- logit = tf.matmul(rnn_out, softmax_w) + softmax_b
-
- # Real sample.
- real = targets[:, t]
-
- categorical = tf.contrib.distributions.Categorical(logits=logit)
- fake = categorical.sample()
- log_prob = categorical.log_prob(fake)
-
- # Output for Generator will either be generated or the input.
- #
- # If present: Return real.
- # If not present: Return fake.
- output = tf.where(targets_present[:, t], real, fake)
-
- # Add to lists.
- sequence.append(output)
- log_probs.append(log_prob)
- logits.append(logit)
-
- # Produce the RNN state had the model operated only
- # over real data.
- real_state_gen = initial_state
- for t in xrange(FLAGS.sequence_length):
- tf.get_variable_scope().reuse_variables()
-
- rnn_inp = rnn_inputs[:, t]
-
- # RNN.
- rnn_out, real_state_gen = cell_gen(rnn_inp, real_state_gen)
-
- final_state = real_state_gen
-
- return (tf.stack(sequence, axis=1), tf.stack(logits, axis=1), tf.stack(
- log_probs, axis=1), initial_state, final_state)
-
-
-def discriminator(hparams, sequence, is_training, reuse=None):
- """Define the Discriminator graph."""
- tf.logging.warning(
- 'Undirectional Discriminative model is not a useful model for this '
- 'MaskGAN because future context is needed. Use only for debugging '
- 'purposes.')
- sequence = tf.cast(sequence, tf.int32)
-
- with tf.variable_scope('dis', reuse=reuse):
-
- def lstm_cell():
- return tf.contrib.rnn.BasicLSTMCell(hparams.dis_rnn_size,
- forget_bias=0.0,
- state_is_tuple=True,
- reuse=reuse)
-
- attn_cell = lstm_cell
- if is_training and FLAGS.keep_prob < 1:
-
- def attn_cell():
- return tf.contrib.rnn.DropoutWrapper(
- lstm_cell(), output_keep_prob=FLAGS.keep_prob)
-
- cell_dis = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.dis_num_layers)],
- state_is_tuple=True)
-
- state_dis = cell_dis.zero_state(FLAGS.batch_size, tf.float32)
-
- with tf.variable_scope('rnn') as vs:
- predictions = []
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.dis_rnn_size])
-
- rnn_inputs = tf.nn.embedding_lookup(embedding, sequence)
-
- if is_training and FLAGS.keep_prob < 1:
- rnn_inputs = tf.nn.dropout(rnn_inputs, FLAGS.keep_prob)
-
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- rnn_in = rnn_inputs[:, t]
- rnn_out, state_dis = cell_dis(rnn_in, state_dis)
-
- # Prediction is linear output for Discriminator.
- pred = tf.contrib.layers.linear(rnn_out, 1, scope=vs)
-
- predictions.append(pred)
- predictions = tf.stack(predictions, axis=1)
- return tf.squeeze(predictions, axis=2)
diff --git a/research/maskgan/models/rollout.py b/research/maskgan/models/rollout.py
deleted file mode 100644
index 6919af2e31fa362f702e96e135d4a2bc06e063a2..0000000000000000000000000000000000000000
--- a/research/maskgan/models/rollout.py
+++ /dev/null
@@ -1,384 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Rollout RNN model definitions which call rnn_zaremba code."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-
-from six.moves import xrange
-import tensorflow as tf
-
-from losses import losses
-from model_utils import helper
-from model_utils import model_construction
-from model_utils import model_losses
-from model_utils import model_optimization
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def create_rollout_MaskGAN(hparams, is_training):
- """Create the MaskGAN model.
-
- Args:
- hparams: Hyperparameters for the MaskGAN.
- is_training: Boolean indicating operational mode (train/inference).
- evaluated with a teacher forcing regime.
-
- Return:
- model: Namedtuple for specifying the MaskGAN."""
- global_step = tf.Variable(0, name='global_step', trainable=False)
-
- new_learning_rate = tf.placeholder(tf.float32, [], name='new_learning_rate')
- learning_rate = tf.Variable(0.0, name='learning_rate', trainable=False)
- learning_rate_update = tf.assign(learning_rate, new_learning_rate)
-
- new_rate = tf.placeholder(tf.float32, [], name='new_rate')
- percent_real_var = tf.Variable(0.0, trainable=False)
- percent_real_update = tf.assign(percent_real_var, new_rate)
-
- ## Placeholders.
- inputs = tf.placeholder(
- tf.int32, shape=[FLAGS.batch_size, FLAGS.sequence_length])
- present = tf.placeholder(
- tf.bool, shape=[FLAGS.batch_size, FLAGS.sequence_length])
- inv_present = tf.placeholder(
- tf.bool, shape=[FLAGS.batch_size, FLAGS.sequence_length])
-
- ## Rollout Generator.
- fwd_gen_rollouts = rollout_generator(
- hparams, inputs, present, is_training=is_training, is_validating=False)
- inv_gen_rollouts = rollout_generator(
- hparams,
- inputs,
- inv_present,
- is_training=is_training,
- is_validating=False,
- reuse=True)
-
- ## Rollout Discriminator.
- fwd_dis_rollouts = rollout_discriminator(
- hparams, fwd_gen_rollouts, is_training=is_training)
- inv_dis_rollouts = rollout_discriminator(
- hparams, inv_gen_rollouts, is_training=is_training, reuse=True)
-
- ## Discriminator Loss.
- [dis_loss, dis_loss_pred, dis_loss_inv_pred] = rollout_discriminator_loss(
- fwd_dis_rollouts, present, inv_dis_rollouts, inv_present)
-
- ## Average log-perplexity for only missing words. However, to do this,
- # the logits are still computed using teacher forcing, that is, the ground
- # truth tokens are fed in at each time point to be valid.
- # TODO(liamfedus): Fix the naming convention.
- with tf.variable_scope('gen_rollout'):
- _, fwd_eval_logits, _ = model_construction.create_generator(
- hparams,
- inputs,
- present,
- is_training=False,
- is_validating=True,
- reuse=True)
-
- avg_log_perplexity = model_losses.calculate_log_perplexity(
- fwd_eval_logits, inputs, present)
-
- ## Generator Loss.
- # 1. Cross Entropy losses on missing tokens.
- [fwd_cross_entropy_losses,
- inv_cross_entropy_losses] = rollout_masked_cross_entropy_loss(
- inputs, present, inv_present, fwd_gen_rollouts, inv_gen_rollouts)
-
- # 2. GAN losses on missing tokens.
- [fwd_RL_loss,
- fwd_RL_statistics, fwd_averages_op] = rollout_reinforce_objective(
- hparams, fwd_gen_rollouts, fwd_dis_rollouts, present)
- [inv_RL_loss,
- inv_RL_statistics, inv_averages_op] = rollout_reinforce_objective(
- hparams, inv_gen_rollouts, inv_dis_rollouts, inv_present)
-
- # TODO(liamfedus): Generalize this to use all logs.
- [fwd_sequence, fwd_logits, fwd_log_probs] = fwd_gen_rollouts[-1]
- [inv_sequence, inv_logits, inv_log_probs] = inv_gen_rollouts[-1]
-
- # TODO(liamfedus): Generalize this to use all logs.
- fwd_predictions = fwd_dis_rollouts[-1]
- inv_predictions = inv_dis_rollouts[-1]
-
- # TODO(liamfedus): Generalize this to use all logs.
- [fwd_log_probs, fwd_rewards, fwd_advantages,
- fwd_baselines] = fwd_RL_statistics[-1]
- [inv_log_probs, inv_rewards, inv_advantages,
- inv_baselines] = inv_RL_statistics[-1]
-
- ## Pre-training.
- if FLAGS.gen_pretrain_steps:
- # TODO(liamfedus): Rewrite this.
- fwd_cross_entropy_loss = tf.reduce_mean(fwd_cross_entropy_losses)
- gen_pretrain_op = model_optimization.create_gen_pretrain_op(
- hparams, fwd_cross_entropy_loss, global_step)
- else:
- gen_pretrain_op = tf.no_op('gen_pretrain_no_op')
- if FLAGS.dis_pretrain_steps:
- dis_pretrain_op = model_optimization.create_dis_pretrain_op(
- hparams, dis_loss, global_step)
- else:
- dis_pretrain_op = tf.no_op('dis_pretrain_no_op')
-
- ## Generator Train Op.
- # 1. Cross-Entropy.
- if FLAGS.gen_training_strategy == 'cross_entropy':
- gen_loss = tf.reduce_mean(
- fwd_cross_entropy_losses + inv_cross_entropy_losses) / 2.
- [gen_train_op, gen_grads,
- gen_vars] = model_optimization.create_gen_train_op(
- hparams, learning_rate, gen_loss, global_step, mode='MINIMIZE')
-
- # 2. GAN (REINFORCE)
- elif FLAGS.gen_training_strategy == 'reinforce':
- gen_loss = (fwd_RL_loss + inv_RL_loss) / 2.
- [gen_train_op, gen_grads,
- gen_vars] = model_optimization.create_reinforce_gen_train_op(
- hparams, learning_rate, gen_loss, fwd_averages_op, inv_averages_op,
- global_step)
-
- else:
- raise NotImplementedError
-
- ## Discriminator Train Op.
- dis_train_op, dis_grads, dis_vars = model_optimization.create_dis_train_op(
- hparams, dis_loss, global_step)
-
- ## Summaries.
- with tf.name_scope('general'):
- tf.summary.scalar('percent_real', percent_real_var)
- tf.summary.scalar('learning_rate', learning_rate)
-
- with tf.name_scope('generator_losses'):
- tf.summary.scalar('gen_loss', tf.reduce_mean(gen_loss))
- tf.summary.scalar('gen_loss_fwd_cross_entropy',
- tf.reduce_mean(fwd_cross_entropy_losses))
- tf.summary.scalar('gen_loss_inv_cross_entropy',
- tf.reduce_mean(inv_cross_entropy_losses))
-
- with tf.name_scope('REINFORCE'):
- with tf.name_scope('objective'):
- tf.summary.scalar('fwd_RL_loss', tf.reduce_mean(fwd_RL_loss))
- tf.summary.scalar('inv_RL_loss', tf.reduce_mean(inv_RL_loss))
-
- with tf.name_scope('rewards'):
- helper.variable_summaries(fwd_rewards, 'fwd_rewards')
- helper.variable_summaries(inv_rewards, 'inv_rewards')
-
- with tf.name_scope('advantages'):
- helper.variable_summaries(fwd_advantages, 'fwd_advantages')
- helper.variable_summaries(inv_advantages, 'inv_advantages')
-
- with tf.name_scope('baselines'):
- helper.variable_summaries(fwd_baselines, 'fwd_baselines')
- helper.variable_summaries(inv_baselines, 'inv_baselines')
-
- with tf.name_scope('log_probs'):
- helper.variable_summaries(fwd_log_probs, 'fwd_log_probs')
- helper.variable_summaries(inv_log_probs, 'inv_log_probs')
-
- with tf.name_scope('discriminator_losses'):
- tf.summary.scalar('dis_loss', dis_loss)
- tf.summary.scalar('dis_loss_fwd_sequence', dis_loss_pred)
- tf.summary.scalar('dis_loss_inv_sequence', dis_loss_inv_pred)
-
- with tf.name_scope('logits'):
- helper.variable_summaries(fwd_logits, 'fwd_logits')
- helper.variable_summaries(inv_logits, 'inv_logits')
-
- for v, g in zip(gen_vars, gen_grads):
- helper.variable_summaries(v, v.op.name)
- helper.variable_summaries(g, 'grad/' + v.op.name)
-
- for v, g in zip(dis_vars, dis_grads):
- helper.variable_summaries(v, v.op.name)
- helper.variable_summaries(g, 'grad/' + v.op.name)
-
- merge_summaries_op = tf.summary.merge_all()
-
- # Model saver.
- saver = tf.train.Saver(keep_checkpoint_every_n_hours=1, max_to_keep=5)
-
- # Named tuple that captures elements of the MaskGAN model.
- Model = collections.namedtuple('Model', [
- 'inputs', 'present', 'inv_present', 'percent_real_update', 'new_rate',
- 'fwd_sequence', 'fwd_logits', 'fwd_rewards', 'fwd_advantages',
- 'fwd_log_probs', 'fwd_predictions', 'fwd_cross_entropy_losses',
- 'inv_sequence', 'inv_logits', 'inv_rewards', 'inv_advantages',
- 'inv_log_probs', 'inv_predictions', 'inv_cross_entropy_losses',
- 'avg_log_perplexity', 'dis_loss', 'gen_loss', 'dis_train_op',
- 'gen_train_op', 'gen_pretrain_op', 'dis_pretrain_op',
- 'merge_summaries_op', 'global_step', 'new_learning_rate',
- 'learning_rate_update', 'saver'
- ])
-
- model = Model(
- inputs, present, inv_present, percent_real_update, new_rate, fwd_sequence,
- fwd_logits, fwd_rewards, fwd_advantages, fwd_log_probs, fwd_predictions,
- fwd_cross_entropy_losses, inv_sequence, inv_logits, inv_rewards,
- inv_advantages, inv_log_probs, inv_predictions, inv_cross_entropy_losses,
- avg_log_perplexity, dis_loss, gen_loss, dis_train_op, gen_train_op,
- gen_pretrain_op, dis_pretrain_op, merge_summaries_op, global_step,
- new_learning_rate, learning_rate_update, saver)
- return model
-
-
-def rollout_generator(hparams,
- inputs,
- input_present,
- is_training,
- is_validating,
- reuse=None):
- """Define the Generator graph which does rollouts.
-
- G will now impute tokens that have been masked from the input seqeunce.
- """
- rollouts = []
-
- with tf.variable_scope('gen_rollout'):
- for n in xrange(FLAGS.num_rollouts):
- if n > 0:
- # TODO(liamfedus): Why is it necessary here to manually set reuse?
- reuse = True
- tf.get_variable_scope().reuse_variables()
-
- [sequence, logits, log_probs] = model_construction.create_generator(
- hparams,
- inputs,
- input_present,
- is_training,
- is_validating,
- reuse=reuse)
-
- rollouts.append([sequence, logits, log_probs])
-
- # Length assertion.
- assert len(rollouts) == FLAGS.num_rollouts
-
- return rollouts
-
-
-def rollout_discriminator(hparams, gen_rollouts, is_training, reuse=None):
- """Define the Discriminator graph which does rollouts.
-
- G will now impute tokens that have been masked from the input seqeunce.
- """
- rollout_predictions = []
-
- with tf.variable_scope('dis_rollout'):
- for n, rollout in enumerate(gen_rollouts):
- if n > 0:
- # TODO(liamfedus): Why is it necessary here to manually set reuse?
- reuse = True
- tf.get_variable_scope().reuse_variables()
-
- [sequence, _, _] = rollout
-
- predictions = model_construction.create_discriminator(
- hparams, sequence, is_training=is_training, reuse=reuse)
-
- # Predictions for each rollout.
- rollout_predictions.append(predictions)
-
- # Length assertion.
- assert len(rollout_predictions) == FLAGS.num_rollouts
-
- return rollout_predictions
-
-
-def rollout_reinforce_objective(hparams, gen_rollouts, dis_rollouts, present):
- cumulative_gen_objective = 0.
- cumulative_averages_op = []
- cumulative_statistics = []
-
- assert len(gen_rollouts) == len(dis_rollouts)
-
- for gen_rollout, dis_rollout in zip(gen_rollouts, dis_rollouts):
- [_, _, log_probs] = gen_rollout
- dis_predictions = dis_rollout
-
- [
- final_gen_objective, log_probs, rewards, advantages, baselines,
- maintain_averages_op
- ] = model_losses.calculate_reinforce_objective(hparams, log_probs,
- dis_predictions, present)
-
- # Accumulate results.
- cumulative_gen_objective += final_gen_objective
- cumulative_averages_op.append(maintain_averages_op)
- cumulative_statistics.append([log_probs, rewards, advantages, baselines])
-
- # Group all the averaging operations.
- cumulative_averages_op = tf.group(*cumulative_averages_op)
- cumulative_gen_objective /= FLAGS.num_rollouts
- [log_probs, rewards, advantages, baselines] = cumulative_statistics[-1]
-
- # Length assertion.
- assert len(cumulative_statistics) == FLAGS.num_rollouts
-
- return [
- cumulative_gen_objective, cumulative_statistics, cumulative_averages_op
- ]
-
-
-def rollout_masked_cross_entropy_loss(inputs, present, inv_present,
- fwd_rollouts, inv_rollouts):
- cumulative_fwd_cross_entropy_losses = tf.zeros(
- shape=[FLAGS.batch_size, FLAGS.sequence_length])
- cumulative_inv_cross_entropy_losses = tf.zeros(
- shape=[FLAGS.batch_size, FLAGS.sequence_length])
-
- for fwd_rollout, inv_rollout in zip(fwd_rollouts, inv_rollouts):
- [_, fwd_logits, _] = fwd_rollout
- [_, inv_logits, _] = inv_rollout
-
- [fwd_cross_entropy_losses,
- inv_cross_entropy_losses] = model_losses.create_masked_cross_entropy_loss(
- inputs, present, inv_present, fwd_logits, inv_logits)
-
- cumulative_fwd_cross_entropy_losses = tf.add(
- cumulative_fwd_cross_entropy_losses, fwd_cross_entropy_losses)
- cumulative_inv_cross_entropy_losses = tf.add(
- cumulative_inv_cross_entropy_losses, inv_cross_entropy_losses)
-
- return [
- cumulative_fwd_cross_entropy_losses, cumulative_inv_cross_entropy_losses
- ]
-
-
-def rollout_discriminator_loss(fwd_rollouts, present, inv_rollouts,
- inv_present):
-
- dis_loss = 0
- dis_loss_pred = 0
- dis_loss_inv_pred = 0
-
- for fwd_predictions, inv_predictions in zip(fwd_rollouts, inv_rollouts):
- dis_loss_pred += losses.discriminator_loss(fwd_predictions, present)
- dis_loss_inv_pred += losses.discriminator_loss(inv_predictions, inv_present)
-
- dis_loss_pred /= FLAGS.num_rollouts
- dis_loss_inv_pred /= FLAGS.num_rollouts
-
- dis_loss = (dis_loss_pred + dis_loss_inv_pred) / 2.
- return [dis_loss, dis_loss_pred, dis_loss_inv_pred]
diff --git a/research/maskgan/models/seq2seq.py b/research/maskgan/models/seq2seq.py
deleted file mode 100644
index fac397c98381309f6c7c6d428fcec3c665bcff98..0000000000000000000000000000000000000000
--- a/research/maskgan/models/seq2seq.py
+++ /dev/null
@@ -1,277 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Simple seq2seq model definitions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-from six.moves import xrange
-from models import attention_utils
-
-# ZoneoutWrapper.
-from regularization import zoneout
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def transform_input_with_is_missing_token(inputs, targets_present):
- """Transforms the inputs to have missing tokens when it's masked out. The
- mask is for the targets, so therefore, to determine if an input at time t is
- masked, we have to check if the target at time t - 1 is masked out.
-
- e.g.
- inputs = [a, b, c, d]
- targets = [b, c, d, e]
- targets_present = [1, 0, 1, 0]
-
- then,
- transformed_input = [a, b, , d]
-
- Args:
- inputs: tf.int32 Tensor of shape [batch_size, sequence_length] with tokens
- up to, but not including, vocab_size.
- targets_present: tf.bool Tensor of shape [batch_size, sequence_length] with
- True representing the presence of the word.
-
- Returns:
- transformed_input: tf.int32 Tensor of shape [batch_size, sequence_length]
- which takes on value of inputs when the input is present and takes on
- value=vocab_size to indicate a missing token.
- """
- # To fill in if the input is missing.
- input_missing = tf.constant(
- FLAGS.vocab_size,
- dtype=tf.int32,
- shape=[FLAGS.batch_size, FLAGS.sequence_length])
-
- # The 0th input will always be present to MaskGAN.
- zeroth_input_present = tf.constant(True, tf.bool, shape=[FLAGS.batch_size, 1])
-
- # Input present mask.
- inputs_present = tf.concat(
- [zeroth_input_present, targets_present[:, :-1]], axis=1)
-
- transformed_input = tf.where(inputs_present, inputs, input_missing)
- return transformed_input
-
-
-def gen_encoder(hparams, inputs, targets_present, is_training, reuse=None):
- """Define the Encoder graph."""
- # We will use the same variable from the decoder.
- if FLAGS.seq2seq_share_embedding:
- with tf.variable_scope('decoder/rnn'):
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
-
- with tf.variable_scope('encoder', reuse=reuse):
-
- def lstm_cell():
- return tf.contrib.rnn.LayerNormBasicLSTMCell(
- hparams.gen_rnn_size, reuse=reuse)
-
- attn_cell = lstm_cell
- if FLAGS.zoneout_drop_prob > 0.0:
-
- def attn_cell():
- return zoneout.ZoneoutWrapper(
- lstm_cell(),
- zoneout_drop_prob=FLAGS.zoneout_drop_prob,
- is_training=is_training)
-
- cell = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.gen_num_layers)],
- state_is_tuple=True)
-
- initial_state = cell.zero_state(FLAGS.batch_size, tf.float32)
-
- # Add a missing token for inputs not present.
- real_inputs = inputs
- masked_inputs = transform_input_with_is_missing_token(
- inputs, targets_present)
-
- with tf.variable_scope('rnn'):
- hidden_states = []
-
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size + 1, hparams.gen_rnn_size])
-
- real_rnn_inputs = tf.nn.embedding_lookup(embedding, real_inputs)
- masked_rnn_inputs = tf.nn.embedding_lookup(embedding, masked_inputs)
-
- state = initial_state
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- rnn_inp = masked_rnn_inputs[:, t]
- rnn_out, state = cell(rnn_inp, state)
- hidden_states.append(rnn_out)
- final_masked_state = state
- hidden_states = tf.stack(hidden_states, axis=1)
-
- # Produce the RNN state had the model operated only
- # over real data.
- real_state = initial_state
- for t in xrange(FLAGS.sequence_length):
- tf.get_variable_scope().reuse_variables()
-
- # RNN.
- rnn_inp = real_rnn_inputs[:, t]
- rnn_out, real_state = cell(rnn_inp, real_state)
- final_state = real_state
-
- return (hidden_states, final_masked_state), initial_state, final_state
-
-
-def gen_decoder(hparams,
- inputs,
- targets,
- targets_present,
- encoding_state,
- is_training,
- is_validating,
- reuse=None):
- """Define the Decoder graph. The Decoder will now impute tokens that
- have been masked from the input seqeunce.
- """
- gen_decoder_rnn_size = hparams.gen_rnn_size
-
- with tf.variable_scope('decoder', reuse=reuse):
-
- def lstm_cell():
- return tf.contrib.rnn.LayerNormBasicLSTMCell(
- gen_decoder_rnn_size, reuse=reuse)
-
- attn_cell = lstm_cell
- if FLAGS.zoneout_drop_prob > 0.0:
-
- def attn_cell():
- return zoneout.ZoneoutWrapper(
- lstm_cell(),
- zoneout_drop_prob=FLAGS.zoneout_drop_prob,
- is_training=is_training)
-
- cell_gen = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.gen_num_layers)],
- state_is_tuple=True)
-
- # Hidden encoder states.
- hidden_vector_encodings = encoding_state[0]
-
- # Carry forward the final state tuple from the encoder.
- # State tuples.
- state_gen = encoding_state[1]
-
- if FLAGS.attention_option is not None:
- (attention_keys, attention_values, _,
- attention_construct_fn) = attention_utils.prepare_attention(
- hidden_vector_encodings,
- FLAGS.attention_option,
- num_units=gen_decoder_rnn_size,
- reuse=reuse)
-
- with tf.variable_scope('rnn'):
- sequence, logits, log_probs = [], [], []
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, gen_decoder_rnn_size])
- softmax_w = tf.get_variable('softmax_w',
- [gen_decoder_rnn_size, FLAGS.vocab_size])
- softmax_b = tf.get_variable('softmax_b', [FLAGS.vocab_size])
-
- rnn_inputs = tf.nn.embedding_lookup(embedding, inputs)
-
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- # Input to the Decoder.
- if t == 0:
- # Always provide the real input at t = 0.
- rnn_inp = rnn_inputs[:, t]
-
- # If the input is present, read in the input at t.
- # If the input is not present, read in the previously generated.
- else:
- real_rnn_inp = rnn_inputs[:, t]
- fake_rnn_inp = tf.nn.embedding_lookup(embedding, fake)
-
- # While validating, the decoder should be operating in teacher
- # forcing regime. Also, if we're just training with cross_entropy
- # use teacher forcing.
- if is_validating or (is_training and
- FLAGS.gen_training_strategy == 'cross_entropy'):
- rnn_inp = real_rnn_inp
- else:
- rnn_inp = tf.where(targets_present[:, t - 1], real_rnn_inp,
- fake_rnn_inp)
-
- # RNN.
- rnn_out, state_gen = cell_gen(rnn_inp, state_gen)
-
- if FLAGS.attention_option is not None:
- rnn_out = attention_construct_fn(rnn_out, attention_keys,
- attention_values)
- # # TODO(liamfedus): Assert not "monotonic" attention_type.
- # # TODO(liamfedus): FLAGS.attention_type.
- # context_state = revised_attention_utils._empty_state()
- # rnn_out, context_state = attention_construct_fn(
- # rnn_out, attention_keys, attention_values, context_state, t)
- logit = tf.matmul(rnn_out, softmax_w) + softmax_b
-
- # Output for Decoder.
- # If input is present: Return real at t+1.
- # If input is not present: Return fake for t+1.
- real = targets[:, t]
-
- categorical = tf.contrib.distributions.Categorical(logits=logit)
- fake = categorical.sample()
- log_prob = categorical.log_prob(fake)
-
- output = tf.where(targets_present[:, t], real, fake)
-
- # Add to lists.
- sequence.append(output)
- log_probs.append(log_prob)
- logits.append(logit)
-
- return (tf.stack(sequence, axis=1), tf.stack(logits, axis=1), tf.stack(
- log_probs, axis=1))
-
-
-def generator(hparams,
- inputs,
- targets,
- targets_present,
- is_training,
- is_validating,
- reuse=None):
- """Define the Generator graph."""
- with tf.variable_scope('gen', reuse=reuse):
- encoder_states, initial_state, final_state = gen_encoder(
- hparams, inputs, targets_present, is_training=is_training, reuse=reuse)
- stacked_sequence, stacked_logits, stacked_log_probs = gen_decoder(
- hparams,
- inputs,
- targets,
- targets_present,
- encoder_states,
- is_training=is_training,
- is_validating=is_validating,
- reuse=reuse)
- return (stacked_sequence, stacked_logits, stacked_log_probs, initial_state,
- final_state)
diff --git a/research/maskgan/models/seq2seq_nas.py b/research/maskgan/models/seq2seq_nas.py
deleted file mode 100644
index cede90f5625c6e46740ad7601681712e73f07450..0000000000000000000000000000000000000000
--- a/research/maskgan/models/seq2seq_nas.py
+++ /dev/null
@@ -1,333 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Simple seq2seq model definitions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-from six.moves import xrange
-import tensorflow as tf
-
-from models import attention_utils
-
-# NAS Code..
-from nas_utils import configs
-from nas_utils import custom_cell
-from nas_utils import variational_dropout
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def get_config():
- return configs.AlienConfig2()
-
-
-LSTMTuple = collections.namedtuple('LSTMTuple', ['c', 'h'])
-
-
-def transform_input_with_is_missing_token(inputs, targets_present):
- """Transforms the inputs to have missing tokens when it's masked out. The
- mask is for the targets, so therefore, to determine if an input at time t is
- masked, we have to check if the target at time t - 1 is masked out.
-
- e.g.
- inputs = [a, b, c, d]
- targets = [b, c, d, e]
- targets_present = [1, 0, 1, 0]
-
- then,
- transformed_input = [a, b, , d]
-
- Args:
- inputs: tf.int32 Tensor of shape [batch_size, sequence_length] with tokens
- up to, but not including, vocab_size.
- targets_present: tf.bool Tensor of shape [batch_size, sequence_length] with
- True representing the presence of the word.
-
- Returns:
- transformed_input: tf.int32 Tensor of shape [batch_size, sequence_length]
- which takes on value of inputs when the input is present and takes on
- value=vocab_size to indicate a missing token.
- """
- # To fill in if the input is missing.
- input_missing = tf.constant(
- FLAGS.vocab_size,
- dtype=tf.int32,
- shape=[FLAGS.batch_size, FLAGS.sequence_length])
-
- # The 0th input will always be present to MaskGAN.
- zeroth_input_present = tf.constant(True, tf.bool, shape=[FLAGS.batch_size, 1])
-
- # Input present mask.
- inputs_present = tf.concat(
- [zeroth_input_present, targets_present[:, :-1]], axis=1)
-
- transformed_input = tf.where(inputs_present, inputs, input_missing)
- return transformed_input
-
-
-def gen_encoder(hparams, inputs, targets_present, is_training, reuse=None):
- """Define the Encoder graph.
-
-
- Args:
- hparams: Hyperparameters for the MaskGAN.
- inputs: tf.int32 Tensor of shape [batch_size, sequence_length] with tokens
- up to, but not including, vocab_size.
- targets_present: tf.bool Tensor of shape [batch_size, sequence_length] with
- True representing the presence of the target.
- is_training: Boolean indicating operational mode (train/inference).
- reuse (Optional): Whether to reuse the variables.
-
- Returns:
- Tuple of (hidden_states, final_state).
- """
- config = get_config()
- configs.print_config(config)
- # We will use the same variable from the decoder.
- if FLAGS.seq2seq_share_embedding:
- with tf.variable_scope('decoder/rnn'):
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
-
- with tf.variable_scope('encoder', reuse=reuse):
- # Neural architecture search cell.
- cell = custom_cell.Alien(config.hidden_size)
-
- if is_training:
- [h2h_masks, h2i_masks, _,
- output_mask] = variational_dropout.generate_variational_dropout_masks(
- hparams, config.keep_prob)
- else:
- h2i_masks, output_mask = None, None
-
- cell = custom_cell.GenericMultiRNNCell([cell] * config.num_layers)
-
- initial_state = cell.zero_state(FLAGS.batch_size, tf.float32)
-
- # Add a missing token for inputs not present.
- real_inputs = inputs
- masked_inputs = transform_input_with_is_missing_token(
- inputs, targets_present)
-
- with tf.variable_scope('rnn'):
- hidden_states = []
-
- # Split the embedding into two parts so that we can load the PTB
- # weights into one part of the Variable.
- if not FLAGS.seq2seq_share_embedding:
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
- missing_embedding = tf.get_variable('missing_embedding',
- [1, hparams.gen_rnn_size])
- embedding = tf.concat([embedding, missing_embedding], axis=0)
-
- real_rnn_inputs = tf.nn.embedding_lookup(embedding, real_inputs)
- masked_rnn_inputs = tf.nn.embedding_lookup(embedding, masked_inputs)
-
- if is_training and FLAGS.keep_prob < 1:
- masked_rnn_inputs = tf.nn.dropout(masked_rnn_inputs, FLAGS.keep_prob)
-
- state = initial_state
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- rnn_inp = masked_rnn_inputs[:, t]
-
- if is_training:
- state = list(state)
- for layer_num, per_layer_state in enumerate(state):
- per_layer_state = LSTMTuple(
- per_layer_state[0], per_layer_state[1] * h2h_masks[layer_num])
- state[layer_num] = per_layer_state
-
- rnn_out, state = cell(rnn_inp, state, h2i_masks)
-
- if is_training:
- rnn_out = output_mask * rnn_out
-
- hidden_states.append(rnn_out)
- final_masked_state = state
- hidden_states = tf.stack(hidden_states, axis=1)
-
- # Produce the RNN state had the model operated only
- # over real data.
- real_state = initial_state
- for t in xrange(FLAGS.sequence_length):
- tf.get_variable_scope().reuse_variables()
-
- # RNN.
- rnn_inp = real_rnn_inputs[:, t]
- rnn_out, real_state = cell(rnn_inp, real_state)
- final_state = real_state
-
- return (hidden_states, final_masked_state), initial_state, final_state
-
-
-def gen_decoder(hparams,
- inputs,
- targets,
- targets_present,
- encoding_state,
- is_training,
- is_validating,
- reuse=None):
- """Define the Decoder graph. The Decoder will now impute tokens that
- have been masked from the input seqeunce.
- """
- config = get_config()
- gen_decoder_rnn_size = hparams.gen_rnn_size
-
- if FLAGS.seq2seq_share_embedding:
- with tf.variable_scope('decoder/rnn', reuse=True):
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, gen_decoder_rnn_size])
-
- with tf.variable_scope('decoder', reuse=reuse):
- # Neural architecture search cell.
- cell = custom_cell.Alien(config.hidden_size)
-
- if is_training:
- [h2h_masks, _, _,
- output_mask] = variational_dropout.generate_variational_dropout_masks(
- hparams, config.keep_prob)
- else:
- output_mask = None
-
- cell_gen = custom_cell.GenericMultiRNNCell([cell] * config.num_layers)
-
- # Hidden encoder states.
- hidden_vector_encodings = encoding_state[0]
-
- # Carry forward the final state tuple from the encoder.
- # State tuples.
- state_gen = encoding_state[1]
-
- if FLAGS.attention_option is not None:
- (attention_keys, attention_values, _,
- attention_construct_fn) = attention_utils.prepare_attention(
- hidden_vector_encodings,
- FLAGS.attention_option,
- num_units=gen_decoder_rnn_size,
- reuse=reuse)
-
- with tf.variable_scope('rnn'):
- sequence, logits, log_probs = [], [], []
-
- if not FLAGS.seq2seq_share_embedding:
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, gen_decoder_rnn_size])
- softmax_w = tf.matrix_transpose(embedding)
- softmax_b = tf.get_variable('softmax_b', [FLAGS.vocab_size])
-
- rnn_inputs = tf.nn.embedding_lookup(embedding, inputs)
-
- if is_training and FLAGS.keep_prob < 1:
- rnn_inputs = tf.nn.dropout(rnn_inputs, FLAGS.keep_prob)
-
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- # Input to the Decoder.
- if t == 0:
- # Always provide the real input at t = 0.
- rnn_inp = rnn_inputs[:, t]
-
- # If the input is present, read in the input at t.
- # If the input is not present, read in the previously generated.
- else:
- real_rnn_inp = rnn_inputs[:, t]
- fake_rnn_inp = tf.nn.embedding_lookup(embedding, fake)
-
- # While validating, the decoder should be operating in teacher
- # forcing regime. Also, if we're just training with cross_entropy
- # use teacher forcing.
- if is_validating or (is_training and
- FLAGS.gen_training_strategy == 'cross_entropy'):
- rnn_inp = real_rnn_inp
- else:
- rnn_inp = tf.where(targets_present[:, t - 1], real_rnn_inp,
- fake_rnn_inp)
-
- if is_training:
- state_gen = list(state_gen)
- for layer_num, per_layer_state in enumerate(state_gen):
- per_layer_state = LSTMTuple(
- per_layer_state[0], per_layer_state[1] * h2h_masks[layer_num])
- state_gen[layer_num] = per_layer_state
-
- # RNN.
- rnn_out, state_gen = cell_gen(rnn_inp, state_gen)
-
- if is_training:
- rnn_out = output_mask * rnn_out
-
- if FLAGS.attention_option is not None:
- rnn_out = attention_construct_fn(rnn_out, attention_keys,
- attention_values)
- # # TODO(liamfedus): Assert not "monotonic" attention_type.
- # # TODO(liamfedus): FLAGS.attention_type.
- # context_state = revised_attention_utils._empty_state()
- # rnn_out, context_state = attention_construct_fn(
- # rnn_out, attention_keys, attention_values, context_state, t)
- logit = tf.matmul(rnn_out, softmax_w) + softmax_b
-
- # Output for Decoder.
- # If input is present: Return real at t+1.
- # If input is not present: Return fake for t+1.
- real = targets[:, t]
-
- categorical = tf.contrib.distributions.Categorical(logits=logit)
- fake = categorical.sample()
- log_prob = categorical.log_prob(fake)
-
- output = tf.where(targets_present[:, t], real, fake)
-
- # Add to lists.
- sequence.append(output)
- log_probs.append(log_prob)
- logits.append(logit)
-
- return (tf.stack(sequence, axis=1), tf.stack(logits, axis=1), tf.stack(
- log_probs, axis=1))
-
-
-def generator(hparams,
- inputs,
- targets,
- targets_present,
- is_training,
- is_validating,
- reuse=None):
- """Define the Generator graph."""
- with tf.variable_scope('gen', reuse=reuse):
- encoder_states, initial_state, final_state = gen_encoder(
- hparams, inputs, targets_present, is_training=is_training, reuse=reuse)
- stacked_sequence, stacked_logits, stacked_log_probs = gen_decoder(
- hparams,
- inputs,
- targets,
- targets_present,
- encoder_states,
- is_training=is_training,
- is_validating=is_validating,
- reuse=reuse)
- return (stacked_sequence, stacked_logits, stacked_log_probs, initial_state,
- final_state)
diff --git a/research/maskgan/models/seq2seq_vd.py b/research/maskgan/models/seq2seq_vd.py
deleted file mode 100644
index 850eda435c48c73d574a06b1b65a12f71a18f276..0000000000000000000000000000000000000000
--- a/research/maskgan/models/seq2seq_vd.py
+++ /dev/null
@@ -1,609 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Simple seq2seq model definitions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from six.moves import xrange
-import tensorflow as tf
-
-from models import attention_utils
-from regularization import variational_dropout
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def transform_input_with_is_missing_token(inputs, targets_present):
- """Transforms the inputs to have missing tokens when it's masked out. The
- mask is for the targets, so therefore, to determine if an input at time t is
- masked, we have to check if the target at time t - 1 is masked out.
-
- e.g.
- inputs = [a, b, c, d]
- targets = [b, c, d, e]
- targets_present = [1, 0, 1, 0]
-
- which computes,
- inputs_present = [1, 1, 0, 1]
-
- and outputs,
- transformed_input = [a, b, , d]
-
- Args:
- inputs: tf.int32 Tensor of shape [batch_size, sequence_length] with tokens
- up to, but not including, vocab_size.
- targets_present: tf.bool Tensor of shape [batch_size, sequence_length] with
- True representing the presence of the word.
-
- Returns:
- transformed_input: tf.int32 Tensor of shape [batch_size, sequence_length]
- which takes on value of inputs when the input is present and takes on
- value=vocab_size to indicate a missing token.
- """
- # To fill in if the input is missing.
- input_missing = tf.constant(
- FLAGS.vocab_size,
- dtype=tf.int32,
- shape=[FLAGS.batch_size, FLAGS.sequence_length])
-
- # The 0th input will always be present to MaskGAN.
- zeroth_input_present = tf.constant(True, tf.bool, shape=[FLAGS.batch_size, 1])
-
- # Input present mask.
- inputs_present = tf.concat(
- [zeroth_input_present, targets_present[:, :-1]], axis=1)
-
- transformed_input = tf.where(inputs_present, inputs, input_missing)
- return transformed_input
-
-
-# TODO(adai): IMDB labels placeholder to encoder.
-def gen_encoder(hparams, inputs, targets_present, is_training, reuse=None):
- """Define the Encoder graph.
-
- Args:
- hparams: Hyperparameters for the MaskGAN.
- inputs: tf.int32 Tensor of shape [batch_size, sequence_length] with tokens
- up to, but not including, vocab_size.
- targets_present: tf.bool Tensor of shape [batch_size, sequence_length] with
- True representing the presence of the target.
- is_training: Boolean indicating operational mode (train/inference).
- reuse (Optional): Whether to reuse the variables.
-
- Returns:
- Tuple of (hidden_states, final_state).
- """
- # We will use the same variable from the decoder.
- if FLAGS.seq2seq_share_embedding:
- with tf.variable_scope('decoder/rnn'):
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
-
- with tf.variable_scope('encoder', reuse=reuse):
-
- def lstm_cell():
- return tf.contrib.rnn.BasicLSTMCell(
- hparams.gen_rnn_size,
- forget_bias=0.0,
- state_is_tuple=True,
- reuse=reuse)
-
- attn_cell = lstm_cell
- if is_training and hparams.gen_vd_keep_prob < 1:
-
- def attn_cell():
- return variational_dropout.VariationalDropoutWrapper(
- lstm_cell(), FLAGS.batch_size, hparams.gen_rnn_size,
- hparams.gen_vd_keep_prob, hparams.gen_vd_keep_prob)
-
- cell = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.gen_num_layers)],
- state_is_tuple=True)
-
- initial_state = cell.zero_state(FLAGS.batch_size, tf.float32)
-
- # Add a missing token for inputs not present.
- real_inputs = inputs
- masked_inputs = transform_input_with_is_missing_token(
- inputs, targets_present)
-
- with tf.variable_scope('rnn') as scope:
- hidden_states = []
-
- # Split the embedding into two parts so that we can load the PTB
- # weights into one part of the Variable.
- if not FLAGS.seq2seq_share_embedding:
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
- missing_embedding = tf.get_variable('missing_embedding',
- [1, hparams.gen_rnn_size])
- embedding = tf.concat([embedding, missing_embedding], axis=0)
-
- # TODO(adai): Perhaps append IMDB labels placeholder to input at
- # each time point.
- real_rnn_inputs = tf.nn.embedding_lookup(embedding, real_inputs)
- masked_rnn_inputs = tf.nn.embedding_lookup(embedding, masked_inputs)
-
- state = initial_state
-
- def make_mask(keep_prob, units):
- random_tensor = keep_prob
- # 0. if [keep_prob, 1.0) and 1. if [1.0, 1.0 + keep_prob)
- random_tensor += tf.random_uniform(
- tf.stack([FLAGS.batch_size, 1, units]))
- return tf.floor(random_tensor) / keep_prob
-
- if is_training:
- output_mask = make_mask(hparams.gen_vd_keep_prob, hparams.gen_rnn_size)
-
- hidden_states, state = tf.nn.dynamic_rnn(
- cell, masked_rnn_inputs, initial_state=state, scope=scope)
- if is_training:
- hidden_states *= output_mask
-
- final_masked_state = state
-
- # Produce the RNN state had the model operated only
- # over real data.
- real_state = initial_state
- _, real_state = tf.nn.dynamic_rnn(
- cell, real_rnn_inputs, initial_state=real_state, scope=scope)
- final_state = real_state
-
- return (hidden_states, final_masked_state), initial_state, final_state
-
-
-# TODO(adai): IMDB labels placeholder to encoder.
-def gen_encoder_cnn(hparams, inputs, targets_present, is_training, reuse=None):
- """Define the CNN Encoder graph."""
- del reuse
- sequence = transform_input_with_is_missing_token(inputs, targets_present)
-
- # TODO(liamfedus): Make this a hyperparameter.
- dis_filter_sizes = [3, 4, 5, 6, 7, 8, 9, 10, 15, 20]
-
- # Keeping track of l2 regularization loss (optional)
- # l2_loss = tf.constant(0.0)
-
- with tf.variable_scope('encoder', reuse=True):
- with tf.variable_scope('rnn'):
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
-
- cnn_inputs = tf.nn.embedding_lookup(embedding, sequence)
-
- # Create a convolution layer for each filter size
- conv_outputs = []
- for filter_size in dis_filter_sizes:
- with tf.variable_scope('conv-%s' % filter_size):
- # Convolution Layer
- filter_shape = [
- filter_size, hparams.gen_rnn_size, hparams.dis_num_filters
- ]
- W = tf.get_variable(
- name='W', initializer=tf.truncated_normal(filter_shape, stddev=0.1))
- b = tf.get_variable(
- name='b',
- initializer=tf.constant(0.1, shape=[hparams.dis_num_filters]))
- conv = tf.nn.conv1d(cnn_inputs, W, stride=1, padding='SAME', name='conv')
-
- # Apply nonlinearity
- h = tf.nn.relu(tf.nn.bias_add(conv, b), name='relu')
-
- conv_outputs.append(h)
-
- # Combine all the pooled features
- dis_num_filters_total = hparams.dis_num_filters * len(dis_filter_sizes)
-
- h_conv = tf.concat(conv_outputs, axis=2)
- h_conv_flat = tf.reshape(h_conv, [-1, dis_num_filters_total])
-
- # Add dropout
- if is_training:
- with tf.variable_scope('dropout'):
- h_conv_flat = tf.nn.dropout(h_conv_flat, hparams.gen_vd_keep_prob)
-
- # Final (unnormalized) scores and predictions
- with tf.variable_scope('output'):
- W = tf.get_variable(
- 'W',
- shape=[dis_num_filters_total, hparams.gen_rnn_size],
- initializer=tf.contrib.layers.xavier_initializer())
- b = tf.get_variable(
- name='b', initializer=tf.constant(0.1, shape=[hparams.gen_rnn_size]))
- # l2_loss += tf.nn.l2_loss(W)
- # l2_loss += tf.nn.l2_loss(b)
- predictions = tf.nn.xw_plus_b(h_conv_flat, W, b, name='predictions')
- predictions = tf.reshape(
- predictions,
- shape=[FLAGS.batch_size, FLAGS.sequence_length, hparams.gen_rnn_size])
- final_state = tf.reduce_mean(predictions, 1)
- return predictions, (final_state, final_state)
-
-
-# TODO(adai): IMDB labels placeholder to decoder.
-def gen_decoder(hparams,
- inputs,
- targets,
- targets_present,
- encoding_state,
- is_training,
- is_validating,
- reuse=None):
- """Define the Decoder graph. The Decoder will now impute tokens that
- have been masked from the input seqeunce.
- """
- gen_decoder_rnn_size = hparams.gen_rnn_size
-
- targets = tf.Print(targets, [targets], message='targets', summarize=50)
- if FLAGS.seq2seq_share_embedding:
- with tf.variable_scope('decoder/rnn', reuse=True):
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
-
- with tf.variable_scope('decoder', reuse=reuse):
-
- def lstm_cell():
- return tf.contrib.rnn.BasicLSTMCell(
- gen_decoder_rnn_size,
- forget_bias=0.0,
- state_is_tuple=True,
- reuse=reuse)
-
- attn_cell = lstm_cell
- if is_training and hparams.gen_vd_keep_prob < 1:
-
- def attn_cell():
- return variational_dropout.VariationalDropoutWrapper(
- lstm_cell(), FLAGS.batch_size, hparams.gen_rnn_size,
- hparams.gen_vd_keep_prob, hparams.gen_vd_keep_prob)
-
- cell_gen = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.gen_num_layers)],
- state_is_tuple=True)
-
- # Hidden encoder states.
- hidden_vector_encodings = encoding_state[0]
-
- # Carry forward the final state tuple from the encoder.
- # State tuples.
- state_gen = encoding_state[1]
-
- if FLAGS.attention_option is not None:
- (attention_keys, attention_values, _,
- attention_construct_fn) = attention_utils.prepare_attention(
- hidden_vector_encodings,
- FLAGS.attention_option,
- num_units=gen_decoder_rnn_size,
- reuse=reuse)
-
- def make_mask(keep_prob, units):
- random_tensor = keep_prob
- # 0. if [keep_prob, 1.0) and 1. if [1.0, 1.0 + keep_prob)
- random_tensor += tf.random_uniform(tf.stack([FLAGS.batch_size, units]))
- return tf.floor(random_tensor) / keep_prob
-
- if is_training:
- output_mask = make_mask(hparams.gen_vd_keep_prob, hparams.gen_rnn_size)
-
- with tf.variable_scope('rnn'):
- sequence, logits, log_probs = [], [], []
-
- if not FLAGS.seq2seq_share_embedding:
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
- softmax_w = tf.matrix_transpose(embedding)
- softmax_b = tf.get_variable('softmax_b', [FLAGS.vocab_size])
-
- rnn_inputs = tf.nn.embedding_lookup(embedding, inputs)
- # TODO(adai): Perhaps append IMDB labels placeholder to input at
- # each time point.
-
- rnn_outs = []
-
- fake = None
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- # Input to the Decoder.
- if t == 0:
- # Always provide the real input at t = 0.
- rnn_inp = rnn_inputs[:, t]
-
- # If the input is present, read in the input at t.
- # If the input is not present, read in the previously generated.
- else:
- real_rnn_inp = rnn_inputs[:, t]
-
- # While validating, the decoder should be operating in teacher
- # forcing regime. Also, if we're just training with cross_entropy
- # use teacher forcing.
- if is_validating or FLAGS.gen_training_strategy == 'cross_entropy':
- rnn_inp = real_rnn_inp
- else:
- fake_rnn_inp = tf.nn.embedding_lookup(embedding, fake)
- rnn_inp = tf.where(targets_present[:, t - 1], real_rnn_inp,
- fake_rnn_inp)
-
- # RNN.
- rnn_out, state_gen = cell_gen(rnn_inp, state_gen)
-
- if FLAGS.attention_option is not None:
- rnn_out = attention_construct_fn(rnn_out, attention_keys,
- attention_values)
- if is_training:
- rnn_out *= output_mask
-
- rnn_outs.append(rnn_out)
- if FLAGS.gen_training_strategy != 'cross_entropy':
- logit = tf.nn.bias_add(tf.matmul(rnn_out, softmax_w), softmax_b)
-
- # Output for Decoder.
- # If input is present: Return real at t+1.
- # If input is not present: Return fake for t+1.
- real = targets[:, t]
-
- categorical = tf.contrib.distributions.Categorical(logits=logit)
- if FLAGS.use_gen_mode:
- fake = categorical.mode()
- else:
- fake = categorical.sample()
- log_prob = categorical.log_prob(fake)
- output = tf.where(targets_present[:, t], real, fake)
-
- else:
- real = targets[:, t]
- logit = tf.zeros(tf.stack([FLAGS.batch_size, FLAGS.vocab_size]))
- log_prob = tf.zeros(tf.stack([FLAGS.batch_size]))
- output = real
-
- # Add to lists.
- sequence.append(output)
- log_probs.append(log_prob)
- logits.append(logit)
-
- if FLAGS.gen_training_strategy == 'cross_entropy':
- logits = tf.nn.bias_add(
- tf.matmul(
- tf.reshape(tf.stack(rnn_outs, 1), [-1, gen_decoder_rnn_size]),
- softmax_w), softmax_b)
- logits = tf.reshape(logits,
- [-1, FLAGS.sequence_length, FLAGS.vocab_size])
- else:
- logits = tf.stack(logits, axis=1)
-
- return (tf.stack(sequence, axis=1), logits, tf.stack(log_probs, axis=1))
-
-
-def dis_encoder(hparams, masked_inputs, is_training, reuse=None,
- embedding=None):
- """Define the Discriminator encoder. Reads in the masked inputs for context
- and produces the hidden states of the encoder."""
- with tf.variable_scope('encoder', reuse=reuse):
-
- def lstm_cell():
- return tf.contrib.rnn.BasicLSTMCell(
- hparams.dis_rnn_size,
- forget_bias=0.0,
- state_is_tuple=True,
- reuse=reuse)
-
- attn_cell = lstm_cell
- if is_training and hparams.dis_vd_keep_prob < 1:
-
- def attn_cell():
- return variational_dropout.VariationalDropoutWrapper(
- lstm_cell(), FLAGS.batch_size, hparams.dis_rnn_size,
- hparams.dis_vd_keep_prob, hparams.dis_vd_keep_prob)
-
- cell_dis = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.dis_num_layers)],
- state_is_tuple=True)
-
- state_dis = cell_dis.zero_state(FLAGS.batch_size, tf.float32)
-
- with tf.variable_scope('rnn'):
- hidden_states = []
-
- missing_embedding = tf.get_variable('missing_embedding',
- [1, hparams.dis_rnn_size])
- embedding = tf.concat([embedding, missing_embedding], axis=0)
- masked_rnn_inputs = tf.nn.embedding_lookup(embedding, masked_inputs)
-
- def make_mask(keep_prob, units):
- random_tensor = keep_prob
- # 0. if [keep_prob, 1.0) and 1. if [1.0, 1.0 + keep_prob)
- random_tensor += tf.random_uniform(tf.stack([FLAGS.batch_size, units]))
- return tf.floor(random_tensor) / keep_prob
-
- if is_training:
- output_mask = make_mask(hparams.dis_vd_keep_prob, hparams.dis_rnn_size)
-
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- rnn_in = masked_rnn_inputs[:, t]
- rnn_out, state_dis = cell_dis(rnn_in, state_dis)
- if is_training:
- rnn_out *= output_mask
- hidden_states.append(rnn_out)
- final_state = state_dis
-
- return (tf.stack(hidden_states, axis=1), final_state)
-
-
-def dis_decoder(hparams,
- sequence,
- encoding_state,
- is_training,
- reuse=None,
- embedding=None):
- """Define the Discriminator decoder. Read in the sequence and predict
- at each time point."""
- sequence = tf.cast(sequence, tf.int32)
-
- with tf.variable_scope('decoder', reuse=reuse):
-
- def lstm_cell():
- return tf.contrib.rnn.BasicLSTMCell(
- hparams.dis_rnn_size,
- forget_bias=0.0,
- state_is_tuple=True,
- reuse=reuse)
-
- attn_cell = lstm_cell
- if is_training and hparams.dis_vd_keep_prob < 1:
-
- def attn_cell():
- return variational_dropout.VariationalDropoutWrapper(
- lstm_cell(), FLAGS.batch_size, hparams.dis_rnn_size,
- hparams.dis_vd_keep_prob, hparams.dis_vd_keep_prob)
-
- cell_dis = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.dis_num_layers)],
- state_is_tuple=True)
-
- # Hidden encoder states.
- hidden_vector_encodings = encoding_state[0]
-
- # Carry forward the final state tuple from the encoder.
- # State tuples.
- state = encoding_state[1]
-
- if FLAGS.attention_option is not None:
- (attention_keys, attention_values, _,
- attention_construct_fn) = attention_utils.prepare_attention(
- hidden_vector_encodings,
- FLAGS.attention_option,
- num_units=hparams.dis_rnn_size,
- reuse=reuse)
-
- def make_mask(keep_prob, units):
- random_tensor = keep_prob
- # 0. if [keep_prob, 1.0) and 1. if [1.0, 1.0 + keep_prob)
- random_tensor += tf.random_uniform(tf.stack([FLAGS.batch_size, units]))
- return tf.floor(random_tensor) / keep_prob
-
- if is_training:
- output_mask = make_mask(hparams.dis_vd_keep_prob, hparams.dis_rnn_size)
-
- with tf.variable_scope('rnn') as vs:
- predictions = []
-
- rnn_inputs = tf.nn.embedding_lookup(embedding, sequence)
-
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- rnn_in = rnn_inputs[:, t]
- rnn_out, state = cell_dis(rnn_in, state)
-
- if FLAGS.attention_option is not None:
- rnn_out = attention_construct_fn(rnn_out, attention_keys,
- attention_values)
- if is_training:
- rnn_out *= output_mask
-
- # Prediction is linear output for Discriminator.
- pred = tf.contrib.layers.linear(rnn_out, 1, scope=vs)
- predictions.append(pred)
-
- predictions = tf.stack(predictions, axis=1)
- return tf.squeeze(predictions, axis=2)
-
-
-def discriminator(hparams,
- inputs,
- targets_present,
- sequence,
- is_training,
- reuse=None):
- """Define the Discriminator graph."""
- if FLAGS.dis_share_embedding:
- assert hparams.dis_rnn_size == hparams.gen_rnn_size, (
- 'If you wish to share Discriminator/Generator embeddings, they must be'
- ' same dimension.')
- with tf.variable_scope('gen/decoder/rnn', reuse=True):
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
- else:
- # Explicitly share the embedding.
- with tf.variable_scope('dis/decoder/rnn', reuse=reuse):
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.dis_rnn_size])
-
- # Mask the input sequence.
- masked_inputs = transform_input_with_is_missing_token(inputs, targets_present)
-
- # Confirm masking.
- masked_inputs = tf.Print(
- masked_inputs, [inputs, targets_present, masked_inputs, sequence],
- message='inputs, targets_present, masked_inputs, sequence',
- summarize=10)
-
- with tf.variable_scope('dis', reuse=reuse):
- encoder_states = dis_encoder(
- hparams,
- masked_inputs,
- is_training=is_training,
- reuse=reuse,
- embedding=embedding)
- predictions = dis_decoder(
- hparams,
- sequence,
- encoder_states,
- is_training=is_training,
- reuse=reuse,
- embedding=embedding)
-
- # if FLAGS.baseline_method == 'critic':
- # with tf.variable_scope('critic', reuse=reuse) as critic_scope:
- # values = tf.contrib.layers.linear(rnn_outs, 1, scope=critic_scope)
- # values = tf.squeeze(values, axis=2)
- # else:
- # values = None
-
- return predictions
-
-
-# TODO(adai): IMDB labels placeholder to encoder/decoder.
-def generator(hparams,
- inputs,
- targets,
- targets_present,
- is_training,
- is_validating,
- reuse=None):
- """Define the Generator graph."""
- with tf.variable_scope('gen', reuse=reuse):
- encoder_states, initial_state, final_state = gen_encoder(
- hparams, inputs, targets_present, is_training=is_training, reuse=reuse)
- stacked_sequence, stacked_logits, stacked_log_probs = gen_decoder(
- hparams,
- inputs,
- targets,
- targets_present,
- encoder_states,
- is_training=is_training,
- is_validating=is_validating,
- reuse=reuse)
- return (stacked_sequence, stacked_logits, stacked_log_probs, initial_state,
- final_state, encoder_states)
diff --git a/research/maskgan/models/seq2seq_zaremba.py b/research/maskgan/models/seq2seq_zaremba.py
deleted file mode 100644
index 25f6ce44f0cb2fe650e23b332ace014ab7cdf469..0000000000000000000000000000000000000000
--- a/research/maskgan/models/seq2seq_zaremba.py
+++ /dev/null
@@ -1,305 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Simple seq2seq model definitions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-from six.moves import xrange
-from models import attention_utils
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def transform_input_with_is_missing_token(inputs, targets_present):
- """Transforms the inputs to have missing tokens when it's masked out. The
- mask is for the targets, so therefore, to determine if an input at time t is
- masked, we have to check if the target at time t - 1 is masked out.
-
- e.g.
- inputs = [a, b, c, d]
- targets = [b, c, d, e]
- targets_present = [1, 0, 1, 0]
-
- then,
- transformed_input = [a, b, , d]
-
- Args:
- inputs: tf.int32 Tensor of shape [batch_size, sequence_length] with tokens
- up to, but not including, vocab_size.
- targets_present: tf.bool Tensor of shape [batch_size, sequence_length] with
- True representing the presence of the word.
-
- Returns:
- transformed_input: tf.int32 Tensor of shape [batch_size, sequence_length]
- which takes on value of inputs when the input is present and takes on
- value=vocab_size to indicate a missing token.
- """
- # To fill in if the input is missing.
- input_missing = tf.constant(FLAGS.vocab_size,
- dtype=tf.int32,
- shape=[FLAGS.batch_size, FLAGS.sequence_length])
-
- # The 0th input will always be present to MaskGAN.
- zeroth_input_present = tf.constant(True, tf.bool, shape=[FLAGS.batch_size, 1])
-
- # Input present mask.
- inputs_present = tf.concat(
- [zeroth_input_present, targets_present[:, :-1]], axis=1)
-
- transformed_input = tf.where(inputs_present, inputs, input_missing)
- return transformed_input
-
-
-def gen_encoder(hparams, inputs, targets_present, is_training, reuse=None):
- """Define the Encoder graph.
-
-
- Args:
- hparams: Hyperparameters for the MaskGAN.
- inputs: tf.int32 Tensor of shape [batch_size, sequence_length] with tokens
- up to, but not including, vocab_size.
- targets_present: tf.bool Tensor of shape [batch_size, sequence_length] with
- True representing the presence of the target.
- is_training: Boolean indicating operational mode (train/inference).
- reuse (Optional): Whether to reuse the variables.
-
- Returns:
- Tuple of (hidden_states, final_state).
- """
- with tf.variable_scope('encoder', reuse=reuse):
-
- def lstm_cell():
- return tf.contrib.rnn.BasicLSTMCell(hparams.gen_rnn_size,
- forget_bias=0.0,
- state_is_tuple=True,
- reuse=reuse)
-
- attn_cell = lstm_cell
- if is_training and FLAGS.keep_prob < 1:
-
- def attn_cell():
- return tf.contrib.rnn.DropoutWrapper(
- lstm_cell(), output_keep_prob=FLAGS.keep_prob)
-
- cell = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.gen_num_layers)],
- state_is_tuple=True)
-
- initial_state = cell.zero_state(FLAGS.batch_size, tf.float32)
-
- # Add a missing token for inputs not present.
- real_inputs = inputs
- masked_inputs = transform_input_with_is_missing_token(inputs,
- targets_present)
-
- with tf.variable_scope('rnn'):
- hidden_states = []
-
- # Split the embedding into two parts so that we can load the PTB
- # weights into one part of the Variable.
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
- missing_embedding = tf.get_variable('missing_embedding',
- [1, hparams.gen_rnn_size])
- embedding = tf.concat([embedding, missing_embedding], axis=0)
-
- real_rnn_inputs = tf.nn.embedding_lookup(embedding, real_inputs)
- masked_rnn_inputs = tf.nn.embedding_lookup(embedding, masked_inputs)
-
- if is_training and FLAGS.keep_prob < 1:
- masked_rnn_inputs = tf.nn.dropout(masked_rnn_inputs, FLAGS.keep_prob)
-
- state = initial_state
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- rnn_inp = masked_rnn_inputs[:, t]
- rnn_out, state = cell(rnn_inp, state)
- hidden_states.append(rnn_out)
- final_masked_state = state
- hidden_states = tf.stack(hidden_states, axis=1)
-
- # Produce the RNN state had the model operated only
- # over real data.
- real_state = initial_state
- for t in xrange(FLAGS.sequence_length):
- tf.get_variable_scope().reuse_variables()
-
- # RNN.
- rnn_inp = real_rnn_inputs[:, t]
- rnn_out, real_state = cell(rnn_inp, real_state)
- final_state = real_state
-
- return (hidden_states, final_masked_state), initial_state, final_state
-
-
-def gen_decoder(hparams,
- inputs,
- targets,
- targets_present,
- encoding_state,
- is_training,
- is_validating,
- reuse=None):
- """Define the Decoder graph. The Decoder will now impute tokens that
- have been masked from the input seqeunce.
- """
- gen_decoder_rnn_size = hparams.gen_rnn_size
-
- with tf.variable_scope('decoder', reuse=reuse):
-
- def lstm_cell():
- return tf.contrib.rnn.BasicLSTMCell(gen_decoder_rnn_size,
- forget_bias=0.0,
- state_is_tuple=True,
- reuse=reuse)
-
- attn_cell = lstm_cell
- if is_training and FLAGS.keep_prob < 1:
-
- def attn_cell():
- return tf.contrib.rnn.DropoutWrapper(
- lstm_cell(), output_keep_prob=FLAGS.keep_prob)
-
- cell_gen = tf.contrib.rnn.MultiRNNCell(
- [attn_cell() for _ in range(hparams.gen_num_layers)],
- state_is_tuple=True)
-
- # Hidden encoder states.
- hidden_vector_encodings = encoding_state[0]
-
- # Carry forward the final state tuple from the encoder.
- # State tuples.
- state_gen = encoding_state[1]
-
- if FLAGS.attention_option is not None:
- (attention_keys, attention_values, _,
- attention_construct_fn) = attention_utils.prepare_attention(
- hidden_vector_encodings,
- FLAGS.attention_option,
- num_units=gen_decoder_rnn_size,
- reuse=reuse)
-
- with tf.variable_scope('rnn'):
- sequence, logits, log_probs = [], [], []
-
- embedding = tf.get_variable('embedding',
- [FLAGS.vocab_size, hparams.gen_rnn_size])
- softmax_w = tf.matrix_transpose(embedding)
- softmax_b = tf.get_variable('softmax_b', [FLAGS.vocab_size])
-
- rnn_inputs = tf.nn.embedding_lookup(embedding, inputs)
-
- if is_training and FLAGS.keep_prob < 1:
- rnn_inputs = tf.nn.dropout(rnn_inputs, FLAGS.keep_prob)
-
- rnn_outs = []
-
- fake = None
- for t in xrange(FLAGS.sequence_length):
- if t > 0:
- tf.get_variable_scope().reuse_variables()
-
- # Input to the Decoder.
- if t == 0:
- # Always provide the real input at t = 0.
- rnn_inp = rnn_inputs[:, t]
-
- # If the input is present, read in the input at t.
- # If the input is not present, read in the previously generated.
- else:
- real_rnn_inp = rnn_inputs[:, t]
-
- # While validating, the decoder should be operating in teacher
- # forcing regime. Also, if we're just training with cross_entropy
- # use teacher forcing.
- if is_validating or FLAGS.gen_training_strategy == 'cross_entropy':
- rnn_inp = real_rnn_inp
- else:
- fake_rnn_inp = tf.nn.embedding_lookup(embedding, fake)
- rnn_inp = tf.where(targets_present[:, t - 1], real_rnn_inp,
- fake_rnn_inp)
-
- # RNN.
- rnn_out, state_gen = cell_gen(rnn_inp, state_gen)
-
- if FLAGS.attention_option is not None:
- rnn_out = attention_construct_fn(rnn_out, attention_keys,
- attention_values)
- rnn_outs.append(rnn_out)
- if FLAGS.gen_training_strategy != 'cross_entropy':
- logit = tf.nn.bias_add(tf.matmul(rnn_out, softmax_w), softmax_b)
-
- # Output for Decoder.
- # If input is present: Return real at t+1.
- # If input is not present: Return fake for t+1.
- real = targets[:, t]
-
- categorical = tf.contrib.distributions.Categorical(logits=logit)
- fake = categorical.sample()
- log_prob = categorical.log_prob(fake)
-
- output = tf.where(targets_present[:, t], real, fake)
-
- else:
- batch_size = tf.shape(rnn_out)[0]
- logit = tf.zeros(tf.stack([batch_size, FLAGS.vocab_size]))
- log_prob = tf.zeros(tf.stack([batch_size]))
- output = targets[:, t]
-
- # Add to lists.
- sequence.append(output)
- log_probs.append(log_prob)
- logits.append(logit)
- if FLAGS.gen_training_strategy == 'cross_entropy':
- logits = tf.nn.bias_add(
- tf.matmul(
- tf.reshape(tf.stack(rnn_outs, 1), [-1, gen_decoder_rnn_size]),
- softmax_w), softmax_b)
- logits = tf.reshape(logits,
- [-1, FLAGS.sequence_length, FLAGS.vocab_size])
- else:
- logits = tf.stack(logits, axis=1)
-
- return (tf.stack(sequence, axis=1), logits, tf.stack(log_probs, axis=1))
-
-
-def generator(hparams,
- inputs,
- targets,
- targets_present,
- is_training,
- is_validating,
- reuse=None):
- """Define the Generator graph."""
- with tf.variable_scope('gen', reuse=reuse):
- encoder_states, initial_state, final_state = gen_encoder(
- hparams, inputs, targets_present, is_training=is_training, reuse=reuse)
- stacked_sequence, stacked_logits, stacked_log_probs = gen_decoder(
- hparams,
- inputs,
- targets,
- targets_present,
- encoder_states,
- is_training=is_training,
- is_validating=is_validating,
- reuse=reuse)
- return (stacked_sequence, stacked_logits, stacked_log_probs, initial_state,
- final_state)
diff --git a/research/maskgan/nas_utils/__init__.py b/research/maskgan/nas_utils/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/maskgan/nas_utils/configs.py b/research/maskgan/nas_utils/configs.py
deleted file mode 100644
index 80d867c36d1de07663d59d6c161aaf9cbe241d95..0000000000000000000000000000000000000000
--- a/research/maskgan/nas_utils/configs.py
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-def print_config(config):
- print("-" * 10, "Configuration Specs", "-" * 10)
- for item in dir(config):
- if list(item)[0] != "_":
- print(item, getattr(config, item))
- print("-" * 29)
-
-
-class AlienConfig2(object):
- """Base 8 740 shared embeddings, gets 64.0 (mean: std: min: max: )."""
- init_scale = 0.05
- learning_rate = 1.0
- max_grad_norm = 10
- num_layers = 2
- num_steps = 25
- hidden_size = 740
- max_epoch = 70
- max_max_epoch = 250
- keep_prob = [1 - 0.15, 1 - 0.45]
- lr_decay = 0.95
- batch_size = 20
- vocab_size = 10000
- weight_decay = 1e-4
- share_embeddings = True
- cell = "alien"
- dropout_type = "variational"
diff --git a/research/maskgan/nas_utils/custom_cell.py b/research/maskgan/nas_utils/custom_cell.py
deleted file mode 100644
index 6add7ffa4e0d69da56d2bba7d9da3875b5c4dd3b..0000000000000000000000000000000000000000
--- a/research/maskgan/nas_utils/custom_cell.py
+++ /dev/null
@@ -1,166 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-import numpy as np
-import tensorflow as tf
-
-flags = tf.flags
-FLAGS = tf.app.flags.FLAGS
-LSTMTuple = collections.namedtuple('LSTMTuple', ['c', 'h'])
-
-
-def cell_depth(num):
- num /= 2
- val = np.log2(1 + num)
- assert abs(val - int(val)) == 0
- return int(val)
-
-
-class GenericMultiRNNCell(tf.contrib.rnn.RNNCell):
- """More generic version of MultiRNNCell that allows you to pass in a dropout mask"""
-
- def __init__(self, cells):
- """Create a RNN cell composed sequentially of a number of RNNCells.
-
- Args:
- cells: list of RNNCells that will be composed in this order.
- state_is_tuple: If True, accepted and returned states are n-tuples, where
- `n = len(cells)`. If False, the states are all
- concatenated along the column axis. This latter behavior will soon be
- deprecated.
-
- Raises:
- ValueError: if cells is empty (not allowed), or at least one of the cells
- returns a state tuple but the flag `state_is_tuple` is `False`.
- """
- self._cells = cells
-
- @property
- def state_size(self):
- return tuple(cell.state_size for cell in self._cells)
-
- @property
- def output_size(self):
- return self._cells[-1].output_size
-
- def __call__(self, inputs, state, input_masks=None, scope=None):
- """Run this multi-layer cell on inputs, starting from state."""
- with tf.variable_scope(scope or type(self).__name__):
- cur_inp = inputs
- new_states = []
- for i, cell in enumerate(self._cells):
- with tf.variable_scope('Cell%d' % i):
- cur_state = state[i]
- if input_masks is not None:
- cur_inp *= input_masks[i]
- cur_inp, new_state = cell(cur_inp, cur_state)
- new_states.append(new_state)
- new_states = tuple(new_states)
- return cur_inp, new_states
-
-
-class AlienRNNBuilder(tf.contrib.rnn.RNNCell):
-
- def __init__(self, num_units, params, additional_params, base_size):
- self.num_units = num_units
- self.cell_create_index = additional_params[0]
- self.cell_inject_index = additional_params[1]
- self.base_size = base_size
- self.cell_params = params[
- -2:] # Cell injection parameters are always the last two
- params = params[:-2]
- self.depth = cell_depth(len(params))
- self.params = params
- self.units_per_layer = [2**i for i in range(self.depth)
- ][::-1] # start with the biggest layer
-
- def __call__(self, inputs, state, scope=None):
- with tf.variable_scope(scope or type(self).__name__):
- definition1 = ['add', 'elem_mult', 'max']
- definition2 = [tf.identity, tf.tanh, tf.sigmoid, tf.nn.relu, tf.sin]
- layer_outputs = [[] for _ in range(self.depth)]
- with tf.variable_scope('rnn_builder'):
- curr_index = 0
- c, h = state
-
- # Run all dense matrix multiplications at once
- big_h_mat = tf.get_variable(
- 'big_h_mat', [self.num_units,
- self.base_size * self.num_units], tf.float32)
- big_inputs_mat = tf.get_variable(
- 'big_inputs_mat', [self.num_units,
- self.base_size * self.num_units], tf.float32)
- big_h_output = tf.matmul(h, big_h_mat)
- big_inputs_output = tf.matmul(inputs, big_inputs_mat)
- h_splits = tf.split(big_h_output, self.base_size, axis=1)
- inputs_splits = tf.split(big_inputs_output, self.base_size, axis=1)
-
- for layer_num, units in enumerate(self.units_per_layer):
- for unit_num in range(units):
- with tf.variable_scope(
- 'layer_{}_unit_{}'.format(layer_num, unit_num)):
- if layer_num == 0:
- prev1_mat = h_splits[unit_num]
- prev2_mat = inputs_splits[unit_num]
- else:
- prev1_mat = layer_outputs[layer_num - 1][2 * unit_num]
- prev2_mat = layer_outputs[layer_num - 1][2 * unit_num + 1]
- if definition1[self.params[curr_index]] == 'add':
- output = prev1_mat + prev2_mat
- elif definition1[self.params[curr_index]] == 'elem_mult':
- output = prev1_mat * prev2_mat
- elif definition1[self.params[curr_index]] == 'max':
- output = tf.maximum(prev1_mat, prev2_mat)
- if curr_index / 2 == self.cell_create_index: # Take the new cell before the activation
- new_c = tf.identity(output)
- output = definition2[self.params[curr_index + 1]](output)
- if curr_index / 2 == self.cell_inject_index:
- if definition1[self.cell_params[0]] == 'add':
- output += c
- elif definition1[self.cell_params[0]] == 'elem_mult':
- output *= c
- elif definition1[self.cell_params[0]] == 'max':
- output = tf.maximum(output, c)
- output = definition2[self.cell_params[1]](output)
- layer_outputs[layer_num].append(output)
- curr_index += 2
- new_h = layer_outputs[-1][-1]
- return new_h, LSTMTuple(new_c, new_h)
-
- @property
- def state_size(self):
- return LSTMTuple(self.num_units, self.num_units)
-
- @property
- def output_size(self):
- return self.num_units
-
-
-class Alien(AlienRNNBuilder):
- """Base 8 Cell."""
-
- def __init__(self, num_units):
- params = [
- 0, 2, 0, 3, 0, 2, 1, 3, 0, 1, 0, 2, 0, 1, 0, 2, 1, 1, 0, 1, 1, 1, 0, 2,
- 1, 0, 0, 1, 1, 1, 0, 1
- ]
- additional_params = [12, 8]
- base_size = 8
- super(Alien, self).__init__(num_units, params, additional_params, base_size)
diff --git a/research/maskgan/nas_utils/variational_dropout.py b/research/maskgan/nas_utils/variational_dropout.py
deleted file mode 100644
index 49cc29f0cd77f7bef9e3c47e7d7dae73fa877ecd..0000000000000000000000000000000000000000
--- a/research/maskgan/nas_utils/variational_dropout.py
+++ /dev/null
@@ -1,61 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Variational Dropout."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def generate_dropout_masks(keep_prob, shape, amount):
- masks = []
- for _ in range(amount):
- dropout_mask = tf.random_uniform(shape) + (keep_prob)
- dropout_mask = tf.floor(dropout_mask) / (keep_prob)
- masks.append(dropout_mask)
- return masks
-
-
-def generate_variational_dropout_masks(hparams, keep_prob):
- [batch_size, num_steps, size, num_layers] = [
- FLAGS.batch_size, FLAGS.sequence_length, hparams.gen_rnn_size,
- hparams.gen_num_layers
- ]
- if len(keep_prob) == 2:
- emb_keep_prob = keep_prob[0] # keep prob for embedding matrix
- h2h_keep_prob = emb_keep_prob # keep prob for hidden to hidden connections
- h2i_keep_prob = keep_prob[1] # keep prob for hidden to input connections
- out_keep_prob = h2i_keep_prob # keep probability for output state
- else:
- emb_keep_prob = keep_prob[0] # keep prob for embedding matrix
- h2h_keep_prob = keep_prob[1] # keep prob for hidden to hidden connections
- h2i_keep_prob = keep_prob[2] # keep prob for hidden to input connections
- out_keep_prob = keep_prob[3] # keep probability for output state
- h2i_masks = [] # Masks for input to recurrent connections
- h2h_masks = [] # Masks for recurrent to recurrent connections
-
- # Input word dropout mask
- emb_masks = generate_dropout_masks(emb_keep_prob, [num_steps, 1], batch_size)
- output_mask = generate_dropout_masks(out_keep_prob, [batch_size, size], 1)[0]
- h2i_masks = generate_dropout_masks(h2i_keep_prob, [batch_size, size],
- num_layers)
- h2h_masks = generate_dropout_masks(h2h_keep_prob, [batch_size, size],
- num_layers)
- return h2h_masks, h2i_masks, emb_masks, output_mask
diff --git a/research/maskgan/pretrain_mask_gan.py b/research/maskgan/pretrain_mask_gan.py
deleted file mode 100644
index 1a9d8ee947deaa3e31cc4c332969ed529e60305e..0000000000000000000000000000000000000000
--- a/research/maskgan/pretrain_mask_gan.py
+++ /dev/null
@@ -1,231 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Pretraining functions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-# Dependency imports
-
-import numpy as np
-
-import tensorflow as tf
-
-from data import imdb_loader
-from data import ptb_loader
-
-# Data.
-from model_utils import model_utils
-from models import evaluation_utils
-
-tf.app.flags.DEFINE_integer(
- 'gen_pretrain_steps', None,
- 'The number of steps to pretrain the generator with cross entropy loss.')
-tf.app.flags.DEFINE_integer(
- 'dis_pretrain_steps', None,
- 'The number of steps to pretrain the discriminator.')
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def pretrain_generator(sv, sess, model, data, log, id_to_word,
- data_ngram_counts, is_chief):
- """Pretrain the generator with classic language modeling training."""
- print('\nPretraining generator for %d steps.' % FLAGS.gen_pretrain_steps)
- log.write(
- '\nPretraining generator for %d steps.\n' % FLAGS.gen_pretrain_steps)
-
- is_pretraining = True
-
- while is_pretraining:
-
- costs = 0.
- iters = 0
- if FLAGS.data_set == 'ptb':
- iterator = ptb_loader.ptb_iterator(data, FLAGS.batch_size,
- FLAGS.sequence_length,
- FLAGS.epoch_size_override)
- elif FLAGS.data_set == 'imdb':
- iterator = imdb_loader.imdb_iterator(data, FLAGS.batch_size,
- FLAGS.sequence_length)
-
- for x, y, _ in iterator:
-
- # For pretraining with cross entropy loss, we have all tokens in the
- # forward sequence present (all True).
- model_utils.assign_percent_real(sess, model.percent_real_update,
- model.new_rate, 1.0)
- p = np.ones(shape=[FLAGS.batch_size, FLAGS.sequence_length], dtype=bool)
-
- pretrain_feed = {model.inputs: x, model.targets: y, model.present: p}
-
- [losses, cost_eval, _, step] = sess.run(
- [
- model.fake_cross_entropy_losses, model.avg_log_perplexity,
- model.gen_pretrain_op, model.global_step
- ],
- feed_dict=pretrain_feed)
-
- costs += cost_eval
- iters += FLAGS.sequence_length
-
- # Calulate rolling perplexity.
- perplexity = np.exp(costs / iters)
-
- # Summaries.
- if is_chief and step % FLAGS.summaries_every == 0:
- # Graph summaries.
- summary_str = sess.run(
- model.merge_summaries_op, feed_dict=pretrain_feed)
- sv.SummaryComputed(sess, summary_str)
-
- # Additional summary.
- for n, data_ngram_count in data_ngram_counts.iteritems():
- avg_percent_captured = evaluation_utils.sequence_ngram_evaluation(
- sess, model.fake_sequence, log, pretrain_feed, data_ngram_count,
- int(n))
- summary_percent_str = tf.Summary(value=[
- tf.Summary.Value(
- tag='general/%s-grams_percent_correct' % n,
- simple_value=avg_percent_captured)
- ])
- sv.SummaryComputed(sess, summary_percent_str, global_step=step)
-
- summary_perplexity_str = tf.Summary(value=[
- tf.Summary.Value(tag='general/perplexity', simple_value=perplexity)
- ])
- sv.SummaryComputed(sess, summary_perplexity_str, global_step=step)
-
- # Printing and logging
- if is_chief and step % FLAGS.print_every == 0:
- print('global_step: %d' % step)
- print(' generator loss: %.3f' % np.mean(losses))
- print(' perplexity: %.3f' % perplexity)
- log.write('global_step: %d\n' % step)
- log.write(' generator loss: %.3f\n' % np.mean(losses))
- log.write(' perplexity: %.3f\n' % perplexity)
-
- for n, data_ngram_count in data_ngram_counts.iteritems():
- avg_percent_captured = evaluation_utils.sequence_ngram_evaluation(
- sess, model.fake_sequence, log, pretrain_feed, data_ngram_count,
- int(n))
- print(' percent of %s-grams captured: %.3f.\n' %
- (n, avg_percent_captured))
- log.write(' percent of %s-grams captured: %.3f.\n\n' %
- (n, avg_percent_captured))
-
- evaluation_utils.generate_logs(sess, model, log, id_to_word,
- pretrain_feed)
-
- if step >= FLAGS.gen_pretrain_steps:
- is_pretraining = False
- break
- return
-
-
-def pretrain_discriminator(sv, sess, model, data, log, id_to_word,
- data_ngram_counts, is_chief):
- print('\nPretraining discriminator for %d steps.' % FLAGS.dis_pretrain_steps)
- log.write(
- '\nPretraining discriminator for %d steps.\n' % FLAGS.dis_pretrain_steps)
-
- is_pretraining = True
-
- while is_pretraining:
-
- cumulative_costs = 0.
- iters = 0
- if FLAGS.data_set == 'ptb':
- iterator = ptb_loader.ptb_iterator(data, FLAGS.batch_size,
- FLAGS.sequence_length,
- FLAGS.epoch_size_override)
- elif FLAGS.data_set == 'imdb':
- iterator = imdb_loader.imdb_iterator(data, FLAGS.batch_size,
- FLAGS.sequence_length)
-
- for x, y, _ in iterator:
- is_present_rate = FLAGS.is_present_rate
- # is_present_rate = np.random.uniform(low=0.0, high=1.0)
- model_utils.assign_percent_real(sess, model.percent_real_update,
- model.new_rate, is_present_rate)
- # Randomly mask out tokens.
- p = model_utils.generate_mask()
-
- pretrain_feed = {model.inputs: x, model.targets: y, model.present: p}
-
- [_, dis_loss_eval, gen_log_perplexity_eval, step] = sess.run(
- [
- model.dis_pretrain_op, model.dis_loss, model.avg_log_perplexity,
- model.global_step
- ],
- feed_dict=pretrain_feed)
-
- cumulative_costs += gen_log_perplexity_eval
- iters += 1
-
- # Calulate rolling perplexity.
- perplexity = np.exp(cumulative_costs / iters)
-
- # Summaries.
- if is_chief and step % FLAGS.summaries_every == 0:
- # Graph summaries.
- summary_str = sess.run(
- model.merge_summaries_op, feed_dict=pretrain_feed)
- sv.SummaryComputed(sess, summary_str)
-
- # Additional summary.
- for n, data_ngram_count in data_ngram_counts.iteritems():
- avg_percent_captured = evaluation_utils.sequence_ngram_evaluation(
- sess, model.fake_sequence, log, pretrain_feed, data_ngram_count,
- int(n))
- summary_percent_str = tf.Summary(value=[
- tf.Summary.Value(
- tag='general/%s-grams_percent_correct' % n,
- simple_value=avg_percent_captured)
- ])
- sv.SummaryComputed(sess, summary_percent_str, global_step=step)
-
- summary_perplexity_str = tf.Summary(value=[
- tf.Summary.Value(tag='general/perplexity', simple_value=perplexity)
- ])
- sv.SummaryComputed(sess, summary_perplexity_str, global_step=step)
-
- # Printing and logging
- if is_chief and step % FLAGS.print_every == 0:
- print('global_step: %d' % step)
- print(' discriminator loss: %.3f' % dis_loss_eval)
- print(' perplexity: %.3f' % perplexity)
- log.write('global_step: %d\n' % step)
- log.write(' discriminator loss: %.3f\n' % dis_loss_eval)
- log.write(' perplexity: %.3f\n' % perplexity)
-
- for n, data_ngram_count in data_ngram_counts.iteritems():
- avg_percent_captured = evaluation_utils.sequence_ngram_evaluation(
- sess, model.fake_sequence, log, pretrain_feed, data_ngram_count,
- int(n))
- print(' percent of %s-grams captured: %.3f.\n' %
- (n, avg_percent_captured))
- log.write(' percent of %s-grams captured: %.3f.\n\n' %
- (n, avg_percent_captured))
-
- evaluation_utils.generate_logs(sess, model, log, id_to_word,
- pretrain_feed)
-
- if step >= FLAGS.dis_pretrain_steps + int(FLAGS.gen_pretrain_steps or 0):
- is_pretraining = False
- break
- return
diff --git a/research/maskgan/regularization/__init__.py b/research/maskgan/regularization/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/maskgan/regularization/variational_dropout.py b/research/maskgan/regularization/variational_dropout.py
deleted file mode 100644
index d67fe52eee45c31012fe50e5de662d27565befae..0000000000000000000000000000000000000000
--- a/research/maskgan/regularization/variational_dropout.py
+++ /dev/null
@@ -1,56 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Variational Dropout Wrapper."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-
-class VariationalDropoutWrapper(tf.contrib.rnn.RNNCell):
- """Add variational dropout to a RNN cell."""
-
- def __init__(self, cell, batch_size, input_size, recurrent_keep_prob,
- input_keep_prob):
- self._cell = cell
- self._recurrent_keep_prob = recurrent_keep_prob
- self._input_keep_prob = input_keep_prob
-
- def make_mask(keep_prob, units):
- random_tensor = keep_prob
- # 0. if [keep_prob, 1.0) and 1. if [1.0, 1.0 + keep_prob)
- random_tensor += tf.random_uniform(tf.stack([batch_size, units]))
- return tf.floor(random_tensor) / keep_prob
-
- self._recurrent_mask = make_mask(recurrent_keep_prob,
- self._cell.state_size[0])
- self._input_mask = self._recurrent_mask
-
- @property
- def state_size(self):
- return self._cell.state_size
-
- @property
- def output_size(self):
- return self._cell.output_size
-
- def __call__(self, inputs, state, scope=None):
- dropped_inputs = inputs * self._input_mask
- dropped_state = (state[0], state[1] * self._recurrent_mask)
- new_h, new_state = self._cell(dropped_inputs, dropped_state, scope)
- return new_h, new_state
diff --git a/research/maskgan/regularization/zoneout.py b/research/maskgan/regularization/zoneout.py
deleted file mode 100644
index 5f9ef3e3014ae6f2e7eea1a2937c5f1e2c356411..0000000000000000000000000000000000000000
--- a/research/maskgan/regularization/zoneout.py
+++ /dev/null
@@ -1,64 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Zoneout Wrapper"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-
-class ZoneoutWrapper(tf.contrib.rnn.RNNCell):
- """Add Zoneout to a RNN cell."""
-
- def __init__(self, cell, zoneout_drop_prob, is_training=True):
- self._cell = cell
- self._zoneout_prob = zoneout_drop_prob
- self._is_training = is_training
-
- @property
- def state_size(self):
- return self._cell.state_size
-
- @property
- def output_size(self):
- return self._cell.output_size
-
- def __call__(self, inputs, state, scope=None):
- output, new_state = self._cell(inputs, state, scope)
- if not isinstance(self._cell.state_size, tuple):
- new_state = tf.split(value=new_state, num_or_size_splits=2, axis=1)
- state = tf.split(value=state, num_or_size_splits=2, axis=1)
- final_new_state = [new_state[0], new_state[1]]
- if self._is_training:
- for i, state_element in enumerate(state):
- random_tensor = 1 - self._zoneout_prob # keep probability
- random_tensor += tf.random_uniform(tf.shape(state_element))
- # 0. if [zoneout_prob, 1.0) and 1. if [1.0, 1.0 + zoneout_prob)
- binary_tensor = tf.floor(random_tensor)
- final_new_state[
- i] = (new_state[i] - state_element) * binary_tensor + state_element
- else:
- for i, state_element in enumerate(state):
- final_new_state[
- i] = state_element * self._zoneout_prob + new_state[i] * (
- 1 - self._zoneout_prob)
- if isinstance(self._cell.state_size, tuple):
- return output, tf.contrib.rnn.LSTMStateTuple(
- final_new_state[0], final_new_state[1])
-
- return output, tf.concat([final_new_state[0], final_new_state[1]], 1)
diff --git a/research/maskgan/sample_shuffler.py b/research/maskgan/sample_shuffler.py
deleted file mode 100644
index 58c31fb573a864b33f3d6e2f17b42e42f1d0ea4d..0000000000000000000000000000000000000000
--- a/research/maskgan/sample_shuffler.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Shuffle samples for human evaluation.
-
-Local launch command:
- python sample_shuffler.py
- --input_ml_path=/tmp/ptb/seq2seq_vd_shareemb_forreal_55_3
- --input_gan_path=/tmp/ptb/MaskGAN_PTB_ari_avg_56.29_v2.0.0
- --output_file_name=/tmp/ptb/shuffled_output.txt
-
- python sample_shuffler.py
- --input_ml_path=/tmp/generate_samples/MaskGAN_IMDB_Benchmark_87.1_v0.3.0
- --input_gan_path=/tmp/generate_samples/MaskGAN_IMDB_v1.0.1
- --output_file_name=/tmp/imdb/shuffled_output.txt
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-# Dependency imports
-import numpy as np
-
-import tensorflow as tf
-
-tf.app.flags.DEFINE_string('input_ml_path', '/tmp', 'Model output directory.')
-tf.app.flags.DEFINE_string('input_gan_path', '/tmp', 'Model output directory.')
-tf.app.flags.DEFINE_string('output_file_name', '/tmp/ptb/shuffled_output.txt',
- 'Model output file.')
-tf.app.flags.DEFINE_boolean(
- 'output_masked_logs', False,
- 'Whether to display for human evaluation (show masking).')
-tf.app.flags.DEFINE_integer('number_epochs', 1,
- 'The number of epochs to produce.')
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def shuffle_samples(input_file_1, input_file_2):
- """Shuffle the examples."""
- shuffled = []
-
- # Set a random seed to keep fixed mask.
- np.random.seed(0)
-
- for line_1, line_2 in zip(input_file_1, input_file_2):
- rand = np.random.randint(1, 3)
- if rand == 1:
- shuffled.append((rand, line_1, line_2))
- else:
- shuffled.append((rand, line_2, line_1))
- input_file_1.close()
- input_file_2.close()
- return shuffled
-
-
-def generate_output(shuffled_tuples, output_file_name):
- output_file = tf.gfile.GFile(output_file_name, mode='w')
-
- for tup in shuffled_tuples:
- formatted_tuple = ('\n{:<1}, {:<1}, {:<1}').format(tup[0], tup[1].rstrip(),
- tup[2].rstrip())
- output_file.write(formatted_tuple)
- output_file.close()
-
-
-def main(_):
- ml_samples_file = tf.gfile.GFile(
- os.path.join(FLAGS.input_ml_path, 'reviews.txt'), mode='r')
- gan_samples_file = tf.gfile.GFile(
- os.path.join(FLAGS.input_gan_path, 'reviews.txt'), mode='r')
-
- # Generate shuffled tuples.
- shuffled_tuples = shuffle_samples(ml_samples_file, gan_samples_file)
-
- # Output to file.
- generate_output(shuffled_tuples, FLAGS.output_file_name)
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/maskgan/train_mask_gan.py b/research/maskgan/train_mask_gan.py
deleted file mode 100644
index 1e70c2284a8704b1c92dcdec850ac29fc9625667..0000000000000000000000000000000000000000
--- a/research/maskgan/train_mask_gan.py
+++ /dev/null
@@ -1,1167 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Launch example:
-
-[IMDB]
-python train_mask_gan.py --data_dir
-/tmp/imdb --data_set imdb --batch_size 128
---sequence_length 20 --base_directory /tmp/maskGAN_v0.01
---hparams="gen_rnn_size=650,gen_num_layers=2,dis_rnn_size=650,dis_num_layers=2
-,critic_learning_rate=0.0009756,dis_learning_rate=0.0000585,
-dis_train_iterations=8,gen_learning_rate=0.0016624,
-gen_full_learning_rate_steps=1e9,gen_learning_rate_decay=0.999999,
-rl_discount_rate=0.8835659" --mode TRAIN --max_steps 1000000
---generator_model seq2seq_vd --discriminator_model seq2seq_vd
---is_present_rate 0.5 --summaries_every 25 --print_every 25
- --max_num_to_print=3 --generator_optimizer=adam
- --seq2seq_share_embedding=True --baseline_method=critic
- --attention_option=luong --n_gram_eval=4 --mask_strategy=contiguous
- --gen_training_strategy=reinforce --dis_pretrain_steps=100
- --perplexity_threshold=1000000
- --dis_share_embedding=True --maskgan_ckpt
- /tmp/model.ckpt-171091
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-
-from functools import partial
-import os
-import time
-# Dependency imports
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-import pretrain_mask_gan
-from data import imdb_loader
-from data import ptb_loader
-from model_utils import helper
-from model_utils import model_construction
-from model_utils import model_losses
-from model_utils import model_optimization
-
-# Data.
-from model_utils import model_utils
-
-from model_utils import n_gram
-from models import evaluation_utils
-
-from models import rollout
-
-np.set_printoptions(precision=3)
-np.set_printoptions(suppress=True)
-
-MODE_TRAIN = 'TRAIN'
-MODE_TRAIN_EVAL = 'TRAIN_EVAL'
-MODE_VALIDATION = 'VALIDATION'
-MODE_TEST = 'TEST'
-
-## Binary and setup FLAGS.
-tf.app.flags.DEFINE_enum(
- 'mode', 'TRAIN', [MODE_TRAIN, MODE_VALIDATION, MODE_TEST, MODE_TRAIN_EVAL],
- 'What this binary will do.')
-tf.app.flags.DEFINE_string('master', '',
- """Name of the TensorFlow master to use.""")
-tf.app.flags.DEFINE_string('eval_master', '',
- """Name prefix of the Tensorflow eval master.""")
-tf.app.flags.DEFINE_integer('task', 0,
- """Task id of the replica running the training.""")
-tf.app.flags.DEFINE_integer('ps_tasks', 0, """Number of tasks in the ps job.
- If 0 no ps job is used.""")
-
-## General FLAGS.
-tf.app.flags.DEFINE_string(
- 'hparams', '', 'Comma separated list of name=value hyperparameter pairs.')
-tf.app.flags.DEFINE_integer('batch_size', 20, 'The batch size.')
-tf.app.flags.DEFINE_integer('vocab_size', 10000, 'The vocabulary size.')
-tf.app.flags.DEFINE_integer('sequence_length', 20, 'The sequence length.')
-tf.app.flags.DEFINE_integer('max_steps', 1000000,
- 'Maximum number of steps to run.')
-tf.app.flags.DEFINE_string(
- 'mask_strategy', 'random', 'Strategy for masking the words. Determine the '
- 'characterisitics of how the words are dropped out. One of '
- "['contiguous', 'random'].")
-tf.app.flags.DEFINE_float('is_present_rate', 0.5,
- 'Percent of tokens present in the forward sequence.')
-tf.app.flags.DEFINE_float('is_present_rate_decay', None, 'Decay rate for the '
- 'percent of words that are real (are present).')
-tf.app.flags.DEFINE_string(
- 'generator_model', 'seq2seq',
- "Type of Generator model. One of ['rnn', 'seq2seq', 'seq2seq_zaremba',"
- "'rnn_zaremba', 'rnn_nas', 'seq2seq_nas']")
-tf.app.flags.DEFINE_string(
- 'attention_option', None,
- "Attention mechanism. One of [None, 'luong', 'bahdanau']")
-tf.app.flags.DEFINE_string(
- 'discriminator_model', 'bidirectional',
- "Type of Discriminator model. One of ['cnn', 'rnn', 'bidirectional', "
- "'rnn_zaremba', 'bidirectional_zaremba', 'rnn_nas', 'rnn_vd', 'seq2seq_vd']"
-)
-tf.app.flags.DEFINE_boolean('seq2seq_share_embedding', False,
- 'Whether to share the '
- 'embeddings between the encoder and decoder.')
-tf.app.flags.DEFINE_boolean(
- 'dis_share_embedding', False, 'Whether to share the '
- 'embeddings between the generator and discriminator.')
-tf.app.flags.DEFINE_boolean('dis_update_share_embedding', False, 'Whether the '
- 'discriminator should update the shared embedding.')
-tf.app.flags.DEFINE_boolean('use_gen_mode', False,
- 'Use the mode of the generator '
- 'to produce samples.')
-tf.app.flags.DEFINE_boolean('critic_update_dis_vars', False,
- 'Whether the critic '
- 'updates the discriminator variables.')
-
-## Training FLAGS.
-tf.app.flags.DEFINE_string(
- 'gen_training_strategy', 'reinforce',
- "Method for training the Generator. One of ['cross_entropy', 'reinforce']")
-tf.app.flags.DEFINE_string(
- 'generator_optimizer', 'adam',
- "Type of Generator optimizer. One of ['sgd', 'adam']")
-tf.app.flags.DEFINE_float('grad_clipping', 10., 'Norm for gradient clipping.')
-tf.app.flags.DEFINE_float('advantage_clipping', 5., 'Clipping for advantages.')
-tf.app.flags.DEFINE_string(
- 'baseline_method', None,
- "Approach for baseline. One of ['critic', 'dis_batch', 'ema', None]")
-tf.app.flags.DEFINE_float('perplexity_threshold', 15000,
- 'Limit for perplexity before terminating job.')
-tf.app.flags.DEFINE_float('zoneout_drop_prob', 0.1,
- 'Probability for dropping parameter for zoneout.')
-tf.app.flags.DEFINE_float('keep_prob', 0.5,
- 'Probability for keeping parameter for dropout.')
-
-## Logging and evaluation FLAGS.
-tf.app.flags.DEFINE_integer('print_every', 250,
- 'Frequency to print and log the '
- 'outputs of the model.')
-tf.app.flags.DEFINE_integer('max_num_to_print', 5,
- 'Number of samples to log/print.')
-tf.app.flags.DEFINE_boolean('print_verbose', False, 'Whether to print in full.')
-tf.app.flags.DEFINE_integer('summaries_every', 100,
- 'Frequency to compute summaries.')
-tf.app.flags.DEFINE_boolean('eval_language_model', False,
- 'Whether to evaluate on '
- 'all words as in language modeling.')
-tf.app.flags.DEFINE_float('eval_interval_secs', 60,
- 'Delay for evaluating model.')
-tf.app.flags.DEFINE_integer(
- 'n_gram_eval', 4, """The degree of the n-grams to use for evaluation.""")
-tf.app.flags.DEFINE_integer(
- 'epoch_size_override', None,
- 'If an integer, this dictates the size of the epochs and will potentially '
- 'not iterate over all the data.')
-tf.app.flags.DEFINE_integer('eval_epoch_size_override', None,
- 'Number of evaluation steps.')
-
-## Directories and checkpoints.
-tf.app.flags.DEFINE_string('base_directory', '/tmp/maskGAN_v0.00',
- 'Base directory for the logging, events and graph.')
-tf.app.flags.DEFINE_string('data_set', 'ptb', 'Data set to operate on. One of'
- "['ptb', 'imdb']")
-tf.app.flags.DEFINE_string('data_dir', '/tmp/data/ptb',
- 'Directory for the training data.')
-tf.app.flags.DEFINE_string(
- 'language_model_ckpt_dir', None,
- 'Directory storing checkpoints to initialize the model. Pretrained models'
- 'are stored at /tmp/maskGAN/pretrained/')
-tf.app.flags.DEFINE_string(
- 'language_model_ckpt_dir_reversed', None,
- 'Directory storing checkpoints of reversed models to initialize the model.'
- 'Pretrained models stored at'
- 'are stored at /tmp/PTB/pretrained_reversed')
-tf.app.flags.DEFINE_string(
- 'maskgan_ckpt', None,
- 'Override which checkpoint file to use to restore the '
- 'model. A pretrained seq2seq_zaremba model is stored at '
- '/tmp/maskGAN/pretrain/seq2seq_zaremba/train/model.ckpt-64912')
-
-tf.app.flags.DEFINE_boolean('wasserstein_objective', False,
- '(DEPRECATED) Whether to use the WGAN training.')
-tf.app.flags.DEFINE_integer('num_rollouts', 1,
- 'The number of rolled out predictions to make.')
-tf.app.flags.DEFINE_float('c_lower', -0.01, 'Lower bound for weights.')
-tf.app.flags.DEFINE_float('c_upper', 0.01, 'Upper bound for weights.')
-
-FLAGS = tf.app.flags.FLAGS
-
-
-def create_hparams():
- """Create the hparams object for generic training hyperparameters."""
- hparams = tf.contrib.training.HParams(
- gen_num_layers=2,
- dis_num_layers=2,
- gen_rnn_size=740,
- dis_rnn_size=740,
- gen_learning_rate=5e-4,
- dis_learning_rate=5e-3,
- critic_learning_rate=5e-3,
- dis_train_iterations=1,
- gen_learning_rate_decay=1.0,
- gen_full_learning_rate_steps=1e7,
- baseline_decay=0.999999,
- rl_discount_rate=0.9,
- gen_vd_keep_prob=0.5,
- dis_vd_keep_prob=0.5,
- dis_pretrain_learning_rate=5e-3,
- dis_num_filters=128,
- dis_hidden_dim=128,
- gen_nas_keep_prob_0=0.85,
- gen_nas_keep_prob_1=0.55,
- dis_nas_keep_prob_0=0.85,
- dis_nas_keep_prob_1=0.55)
- # Command line flags override any of the preceding hyperparameter values.
- if FLAGS.hparams:
- hparams = hparams.parse(FLAGS.hparams)
- return hparams
-
-
-def create_MaskGAN(hparams, is_training):
- """Create the MaskGAN model.
-
- Args:
- hparams: Hyperparameters for the MaskGAN.
- is_training: Boolean indicating operational mode (train/inference).
- evaluated with a teacher forcing regime.
-
- Return:
- model: Namedtuple for specifying the MaskGAN.
- """
- global_step = tf.Variable(0, name='global_step', trainable=False)
-
- new_learning_rate = tf.placeholder(tf.float32, [], name='new_learning_rate')
- learning_rate = tf.Variable(0.0, name='learning_rate', trainable=False)
- learning_rate_update = tf.assign(learning_rate, new_learning_rate)
-
- new_rate = tf.placeholder(tf.float32, [], name='new_rate')
- percent_real_var = tf.Variable(0.0, trainable=False)
- percent_real_update = tf.assign(percent_real_var, new_rate)
-
- ## Placeholders.
- inputs = tf.placeholder(
- tf.int32, shape=[FLAGS.batch_size, FLAGS.sequence_length])
- targets = tf.placeholder(
- tf.int32, shape=[FLAGS.batch_size, FLAGS.sequence_length])
- present = tf.placeholder(
- tf.bool, shape=[FLAGS.batch_size, FLAGS.sequence_length])
- # TODO(adai): Placeholder for IMDB label.
-
- ## Real Sequence is the targets.
- real_sequence = targets
-
- ## Fakse Sequence from the Generator.
- # TODO(adai): Generator must have IMDB labels placeholder.
- (fake_sequence, fake_logits, fake_log_probs, fake_gen_initial_state,
- fake_gen_final_state, _) = model_construction.create_generator(
- hparams,
- inputs,
- targets,
- present,
- is_training=is_training,
- is_validating=False)
- (_, eval_logits, _, eval_initial_state, eval_final_state,
- _) = model_construction.create_generator(
- hparams,
- inputs,
- targets,
- present,
- is_training=False,
- is_validating=True,
- reuse=True)
-
- ## Discriminator.
- fake_predictions = model_construction.create_discriminator(
- hparams,
- fake_sequence,
- is_training=is_training,
- inputs=inputs,
- present=present)
- real_predictions = model_construction.create_discriminator(
- hparams,
- real_sequence,
- is_training=is_training,
- reuse=True,
- inputs=inputs,
- present=present)
-
- ## Critic.
- # The critic will be used to estimate the forward rewards to the Generator.
- if FLAGS.baseline_method == 'critic':
- est_state_values = model_construction.create_critic(
- hparams, fake_sequence, is_training=is_training)
- else:
- est_state_values = None
-
- ## Discriminator Loss.
- [dis_loss, dis_loss_fake, dis_loss_real] = model_losses.create_dis_loss(
- fake_predictions, real_predictions, present)
-
- ## Average log-perplexity for only missing words. However, to do this,
- # the logits are still computed using teacher forcing, that is, the ground
- # truth tokens are fed in at each time point to be valid.
- avg_log_perplexity = model_losses.calculate_log_perplexity(
- eval_logits, targets, present)
-
- ## Generator Objective.
- # 1. Cross Entropy losses on missing tokens.
- fake_cross_entropy_losses = model_losses.create_masked_cross_entropy_loss(
- targets, present, fake_logits)
-
- # 2. GAN REINFORCE losses.
- [
- fake_RL_loss, fake_log_probs, fake_rewards, fake_advantages,
- fake_baselines, fake_averages_op, critic_loss, cumulative_rewards
- ] = model_losses.calculate_reinforce_objective(
- hparams, fake_log_probs, fake_predictions, present, est_state_values)
-
- ## Pre-training.
- if FLAGS.gen_pretrain_steps:
- raise NotImplementedError
- # # TODO(liamfedus): Rewrite this.
- # fwd_cross_entropy_loss = tf.reduce_mean(fwd_cross_entropy_losses)
- # gen_pretrain_op = model_optimization.create_gen_pretrain_op(
- # hparams, fwd_cross_entropy_loss, global_step)
- else:
- gen_pretrain_op = None
- if FLAGS.dis_pretrain_steps:
- dis_pretrain_op = model_optimization.create_dis_pretrain_op(
- hparams, dis_loss, global_step)
- else:
- dis_pretrain_op = None
-
- ## Generator Train Op.
- # 1. Cross-Entropy.
- if FLAGS.gen_training_strategy == 'cross_entropy':
- gen_loss = tf.reduce_mean(fake_cross_entropy_losses)
- [gen_train_op, gen_grads,
- gen_vars] = model_optimization.create_gen_train_op(
- hparams, learning_rate, gen_loss, global_step, mode='MINIMIZE')
-
- # 2. GAN (REINFORCE)
- elif FLAGS.gen_training_strategy == 'reinforce':
- gen_loss = fake_RL_loss
- [gen_train_op, gen_grads,
- gen_vars] = model_optimization.create_reinforce_gen_train_op(
- hparams, learning_rate, gen_loss, fake_averages_op, global_step)
-
- else:
- raise NotImplementedError
-
- ## Discriminator Train Op.
- dis_train_op, dis_grads, dis_vars = model_optimization.create_dis_train_op(
- hparams, dis_loss, global_step)
-
- ## Critic Train Op.
- if critic_loss is not None:
- [critic_train_op, _, _] = model_optimization.create_critic_train_op(
- hparams, critic_loss, global_step)
- dis_train_op = tf.group(dis_train_op, critic_train_op)
-
- ## Summaries.
- with tf.name_scope('general'):
- tf.summary.scalar('percent_real', percent_real_var)
- tf.summary.scalar('learning_rate', learning_rate)
-
- with tf.name_scope('generator_objectives'):
- tf.summary.scalar('gen_objective', tf.reduce_mean(gen_loss))
- tf.summary.scalar('gen_loss_cross_entropy',
- tf.reduce_mean(fake_cross_entropy_losses))
-
- with tf.name_scope('REINFORCE'):
- with tf.name_scope('objective'):
- tf.summary.scalar('fake_RL_loss', tf.reduce_mean(fake_RL_loss))
-
- with tf.name_scope('rewards'):
- helper.variable_summaries(cumulative_rewards, 'rewards')
-
- with tf.name_scope('advantages'):
- helper.variable_summaries(fake_advantages, 'advantages')
-
- with tf.name_scope('baselines'):
- helper.variable_summaries(fake_baselines, 'baselines')
-
- with tf.name_scope('log_probs'):
- helper.variable_summaries(fake_log_probs, 'log_probs')
-
- with tf.name_scope('discriminator_losses'):
- tf.summary.scalar('dis_loss', dis_loss)
- tf.summary.scalar('dis_loss_fake_sequence', dis_loss_fake)
- tf.summary.scalar('dis_loss_prob_fake_sequence', tf.exp(-dis_loss_fake))
- tf.summary.scalar('dis_loss_real_sequence', dis_loss_real)
- tf.summary.scalar('dis_loss_prob_real_sequence', tf.exp(-dis_loss_real))
-
- if critic_loss is not None:
- with tf.name_scope('critic_losses'):
- tf.summary.scalar('critic_loss', critic_loss)
-
- with tf.name_scope('logits'):
- helper.variable_summaries(fake_logits, 'fake_logits')
-
- for v, g in zip(gen_vars, gen_grads):
- helper.variable_summaries(v, v.op.name)
- helper.variable_summaries(g, 'grad/' + v.op.name)
-
- for v, g in zip(dis_vars, dis_grads):
- helper.variable_summaries(v, v.op.name)
- helper.variable_summaries(g, 'grad/' + v.op.name)
-
- merge_summaries_op = tf.summary.merge_all()
- text_summary_placeholder = tf.placeholder(tf.string)
- text_summary_op = tf.summary.text('Samples', text_summary_placeholder)
-
- # Model saver.
- saver = tf.train.Saver(keep_checkpoint_every_n_hours=1, max_to_keep=5)
-
- # Named tuple that captures elements of the MaskGAN model.
- Model = collections.namedtuple('Model', [
- 'inputs', 'targets', 'present', 'percent_real_update', 'new_rate',
- 'fake_sequence', 'fake_logits', 'fake_rewards', 'fake_baselines',
- 'fake_advantages', 'fake_log_probs', 'fake_predictions',
- 'real_predictions', 'fake_cross_entropy_losses', 'fake_gen_initial_state',
- 'fake_gen_final_state', 'eval_initial_state', 'eval_final_state',
- 'avg_log_perplexity', 'dis_loss', 'gen_loss', 'critic_loss',
- 'cumulative_rewards', 'dis_train_op', 'gen_train_op', 'gen_pretrain_op',
- 'dis_pretrain_op', 'merge_summaries_op', 'global_step',
- 'new_learning_rate', 'learning_rate_update', 'saver', 'text_summary_op',
- 'text_summary_placeholder'
- ])
-
- model = Model(
- inputs, targets, present, percent_real_update, new_rate, fake_sequence,
- fake_logits, fake_rewards, fake_baselines, fake_advantages,
- fake_log_probs, fake_predictions, real_predictions,
- fake_cross_entropy_losses, fake_gen_initial_state, fake_gen_final_state,
- eval_initial_state, eval_final_state, avg_log_perplexity, dis_loss,
- gen_loss, critic_loss, cumulative_rewards, dis_train_op, gen_train_op,
- gen_pretrain_op, dis_pretrain_op, merge_summaries_op, global_step,
- new_learning_rate, learning_rate_update, saver, text_summary_op,
- text_summary_placeholder)
- return model
-
-
-def compute_geometric_average(percent_captured):
- """Compute the geometric average of the n-gram metrics."""
-
- res = 1.
- for _, n_gram_percent in percent_captured.iteritems():
- res *= n_gram_percent
-
- return np.power(res, 1. / float(len(percent_captured)))
-
-
-def compute_arithmetic_average(percent_captured):
- """Compute the arithmetic average of the n-gram metrics."""
- N = len(percent_captured)
-
- res = 0.
- for _, n_gram_percent in percent_captured.iteritems():
- res += n_gram_percent
-
- return res / float(N)
-
-
-def get_iterator(data):
- """Return the data iterator."""
- if FLAGS.data_set == 'ptb':
- iterator = ptb_loader.ptb_iterator(data, FLAGS.batch_size,
- FLAGS.sequence_length,
- FLAGS.epoch_size_override)
- elif FLAGS.data_set == 'imdb':
- iterator = imdb_loader.imdb_iterator(data, FLAGS.batch_size,
- FLAGS.sequence_length)
- return iterator
-
-
-def train_model(hparams, data, log_dir, log, id_to_word, data_ngram_counts):
- """Train model.
-
- Args:
- hparams: Hyperparameters for the MaskGAN.
- data: Data to evaluate.
- log_dir: Directory to save checkpoints.
- log: Readable log for the experiment.
- id_to_word: Dictionary of indices to words.
- data_ngram_counts: Dictionary of hashed(n-gram tuples) to counts in the
- data_set.
- """
- print('Training model.')
- tf.logging.info('Training model.')
-
- # Boolean indicating operational mode.
- is_training = True
-
- # Write all the information to the logs.
- log.write('hparams\n')
- log.write(str(hparams))
- log.flush()
-
- is_chief = FLAGS.task == 0
-
- with tf.Graph().as_default():
- with tf.device(tf.train.replica_device_setter(FLAGS.ps_tasks)):
- container_name = ''
- with tf.container(container_name):
- # Construct the model.
- if FLAGS.num_rollouts == 1:
- model = create_MaskGAN(hparams, is_training)
- elif FLAGS.num_rollouts > 1:
- model = rollout.create_rollout_MaskGAN(hparams, is_training)
- else:
- raise ValueError
-
- print('\nTrainable Variables in Graph:')
- for v in tf.trainable_variables():
- print(v)
-
- ## Retrieve the initial savers.
- init_savers = model_utils.retrieve_init_savers(hparams)
-
- ## Initial saver function to supervisor.
- init_fn = partial(model_utils.init_fn, init_savers)
-
- # Create the supervisor. It will take care of initialization,
- # summaries, checkpoints, and recovery.
- sv = tf.train.Supervisor(
- logdir=log_dir,
- is_chief=is_chief,
- saver=model.saver,
- global_step=model.global_step,
- save_model_secs=60,
- recovery_wait_secs=30,
- summary_op=None,
- init_fn=init_fn)
-
- # Get an initialized, and possibly recovered session. Launch the
- # services: Checkpointing, Summaries, step counting.
- #
- # When multiple replicas of this program are running the services are
- # only launched by the 'chief' replica.
- with sv.managed_session(FLAGS.master) as sess:
-
- ## Pretrain the generator.
- if FLAGS.gen_pretrain_steps:
- pretrain_mask_gan.pretrain_generator(sv, sess, model, data, log,
- id_to_word, data_ngram_counts,
- is_chief)
-
- ## Pretrain the discriminator.
- if FLAGS.dis_pretrain_steps:
- pretrain_mask_gan.pretrain_discriminator(
- sv, sess, model, data, log, id_to_word, data_ngram_counts,
- is_chief)
-
- # Initial indicators for printing and summarizing.
- print_step_division = -1
- summary_step_division = -1
-
- # Run iterative computation in a loop.
- while not sv.ShouldStop():
- is_present_rate = FLAGS.is_present_rate
-
- if FLAGS.is_present_rate_decay is not None:
- is_present_rate *= (1. - FLAGS.is_present_rate_decay)
-
- model_utils.assign_percent_real(sess, model.percent_real_update,
- model.new_rate, is_present_rate)
-
- # GAN training.
- avg_epoch_gen_loss, avg_epoch_dis_loss = [], []
- cumulative_costs = 0.
- gen_iters = 0
-
- # Generator and Discriminator statefulness initial evaluation.
- # TODO(liamfedus): Throughout the code I am implicitly assuming
- # that the Generator and Discriminator are equal sized.
- [gen_initial_state_eval, fake_gen_initial_state_eval] = sess.run(
- [model.eval_initial_state, model.fake_gen_initial_state])
- dis_initial_state_eval = fake_gen_initial_state_eval
-
- # Save zeros state to reset later.
- zeros_state = fake_gen_initial_state_eval
-
- ## Offset Discriminator.
- if FLAGS.ps_tasks == 0:
- dis_offset = 1
- else:
- dis_offset = FLAGS.task * 1000 + 1
- dis_iterator = get_iterator(data)
-
- for i in range(dis_offset):
- try:
- dis_x, dis_y, _ = next(dis_iterator)
- except StopIteration:
- dis_iterator = get_iterator(data)
- dis_initial_state_eval = zeros_state
- dis_x, dis_y, _ = next(dis_iterator)
-
- p = model_utils.generate_mask()
-
- # Construct the train feed.
- train_feed = {
- model.inputs: dis_x,
- model.targets: dis_y,
- model.present: p
- }
-
- if FLAGS.data_set == 'ptb':
- # Statefulness of the Generator being used for Discriminator.
- for i, (c, h) in enumerate(model.fake_gen_initial_state):
- train_feed[c] = dis_initial_state_eval[i].c
- train_feed[h] = dis_initial_state_eval[i].h
-
- # Determine the state had the Generator run over real data. We
- # use this state for the Discriminator.
- [dis_initial_state_eval] = sess.run(
- [model.fake_gen_final_state], train_feed)
-
- ## Training loop.
- iterator = get_iterator(data)
- gen_initial_state_eval = zeros_state
-
- if FLAGS.ps_tasks > 0:
- gen_offset = FLAGS.task * 1000 + 1
- for i in range(gen_offset):
- try:
- next(iterator)
- except StopIteration:
- dis_iterator = get_iterator(data)
- dis_initial_state_eval = zeros_state
- next(dis_iterator)
-
- for x, y, _ in iterator:
- for _ in xrange(hparams.dis_train_iterations):
- try:
- dis_x, dis_y, _ = next(dis_iterator)
- except StopIteration:
- dis_iterator = get_iterator(data)
- dis_initial_state_eval = zeros_state
- dis_x, dis_y, _ = next(dis_iterator)
-
- if FLAGS.data_set == 'ptb':
- [dis_initial_state_eval] = sess.run(
- [model.fake_gen_initial_state])
-
- p = model_utils.generate_mask()
-
- # Construct the train feed.
- train_feed = {
- model.inputs: dis_x,
- model.targets: dis_y,
- model.present: p
- }
-
- # Statefulness for the Discriminator.
- if FLAGS.data_set == 'ptb':
- for i, (c, h) in enumerate(model.fake_gen_initial_state):
- train_feed[c] = dis_initial_state_eval[i].c
- train_feed[h] = dis_initial_state_eval[i].h
-
- _, dis_loss_eval, step = sess.run(
- [model.dis_train_op, model.dis_loss, model.global_step],
- feed_dict=train_feed)
-
- # Determine the state had the Generator run over real data.
- # Use this state for the Discriminator.
- [dis_initial_state_eval] = sess.run(
- [model.fake_gen_final_state], train_feed)
-
- # Randomly mask out tokens.
- p = model_utils.generate_mask()
-
- # Construct the train feed.
- train_feed = {model.inputs: x, model.targets: y, model.present: p}
-
- # Statefulness for Generator.
- if FLAGS.data_set == 'ptb':
- tf.logging.info('Generator is stateful.')
- print('Generator is stateful.')
- # Statefulness for *evaluation* Generator.
- for i, (c, h) in enumerate(model.eval_initial_state):
- train_feed[c] = gen_initial_state_eval[i].c
- train_feed[h] = gen_initial_state_eval[i].h
-
- # Statefulness for Generator.
- for i, (c, h) in enumerate(model.fake_gen_initial_state):
- train_feed[c] = fake_gen_initial_state_eval[i].c
- train_feed[h] = fake_gen_initial_state_eval[i].h
-
- # Determine whether to decay learning rate.
- lr_decay = hparams.gen_learning_rate_decay**max(
- step + 1 - hparams.gen_full_learning_rate_steps, 0.0)
-
- # Assign learning rate.
- gen_learning_rate = hparams.gen_learning_rate * lr_decay
- model_utils.assign_learning_rate(sess, model.learning_rate_update,
- model.new_learning_rate,
- gen_learning_rate)
-
- [_, gen_loss_eval, gen_log_perplexity_eval, step] = sess.run(
- [
- model.gen_train_op, model.gen_loss,
- model.avg_log_perplexity, model.global_step
- ],
- feed_dict=train_feed)
-
- cumulative_costs += gen_log_perplexity_eval
- gen_iters += 1
-
- # Determine the state had the Generator run over real data.
- [gen_initial_state_eval, fake_gen_initial_state_eval] = sess.run(
- [model.eval_final_state,
- model.fake_gen_final_state], train_feed)
-
- avg_epoch_dis_loss.append(dis_loss_eval)
- avg_epoch_gen_loss.append(gen_loss_eval)
-
- ## Summaries.
- # Calulate rolling perplexity.
- perplexity = np.exp(cumulative_costs / gen_iters)
-
- if is_chief and (step / FLAGS.summaries_every >
- summary_step_division):
- summary_step_division = step / FLAGS.summaries_every
-
- # Confirm perplexity is not infinite.
- if (not np.isfinite(perplexity) or
- perplexity >= FLAGS.perplexity_threshold):
- print('Training raising FloatingPoinError.')
- raise FloatingPointError(
- 'Training infinite perplexity: %.3f' % perplexity)
-
- # Graph summaries.
- summary_str = sess.run(
- model.merge_summaries_op, feed_dict=train_feed)
- sv.SummaryComputed(sess, summary_str)
-
- # Summary: n-gram
- avg_percent_captured = {'2': 0., '3': 0., '4': 0.}
- for n, data_ngram_count in data_ngram_counts.iteritems():
- batch_percent_captured = evaluation_utils.sequence_ngram_evaluation(
- sess, model.fake_sequence, log, train_feed,
- data_ngram_count, int(n))
- summary_percent_str = tf.Summary(value=[
- tf.Summary.Value(
- tag='general/%s-grams_percent_correct' % n,
- simple_value=batch_percent_captured)
- ])
- sv.SummaryComputed(
- sess, summary_percent_str, global_step=step)
-
- # Summary: geometric_avg
- geometric_avg = compute_geometric_average(avg_percent_captured)
- summary_geometric_avg_str = tf.Summary(value=[
- tf.Summary.Value(
- tag='general/geometric_avg', simple_value=geometric_avg)
- ])
- sv.SummaryComputed(
- sess, summary_geometric_avg_str, global_step=step)
-
- # Summary: arithmetic_avg
- arithmetic_avg = compute_arithmetic_average(
- avg_percent_captured)
- summary_arithmetic_avg_str = tf.Summary(value=[
- tf.Summary.Value(
- tag='general/arithmetic_avg',
- simple_value=arithmetic_avg)
- ])
- sv.SummaryComputed(
- sess, summary_arithmetic_avg_str, global_step=step)
-
- # Summary: perplexity
- summary_perplexity_str = tf.Summary(value=[
- tf.Summary.Value(
- tag='general/perplexity', simple_value=perplexity)
- ])
- sv.SummaryComputed(
- sess, summary_perplexity_str, global_step=step)
-
- ## Printing and logging
- if is_chief and (step / FLAGS.print_every > print_step_division):
- print_step_division = (step / FLAGS.print_every)
- print('global_step: %d' % step)
- print(' perplexity: %.3f' % perplexity)
- print(' gen_learning_rate: %.6f' % gen_learning_rate)
- log.write('global_step: %d\n' % step)
- log.write(' perplexity: %.3f\n' % perplexity)
- log.write(' gen_learning_rate: %.6f' % gen_learning_rate)
-
- # Average percent captured for each of the n-grams.
- avg_percent_captured = {'2': 0., '3': 0., '4': 0.}
- for n, data_ngram_count in data_ngram_counts.iteritems():
- batch_percent_captured = evaluation_utils.sequence_ngram_evaluation(
- sess, model.fake_sequence, log, train_feed,
- data_ngram_count, int(n))
- avg_percent_captured[n] = batch_percent_captured
- print(' percent of %s-grams captured: %.3f.' %
- (n, batch_percent_captured))
- log.write(' percent of %s-grams captured: %.3f.\n' %
- (n, batch_percent_captured))
- geometric_avg = compute_geometric_average(avg_percent_captured)
- print(' geometric_avg: %.3f.' % geometric_avg)
- log.write(' geometric_avg: %.3f.' % geometric_avg)
- arithmetic_avg = compute_arithmetic_average(
- avg_percent_captured)
- print(' arithmetic_avg: %.3f.' % arithmetic_avg)
- log.write(' arithmetic_avg: %.3f.' % arithmetic_avg)
-
- evaluation_utils.print_and_log_losses(
- log, step, is_present_rate, avg_epoch_dis_loss,
- avg_epoch_gen_loss)
-
- if FLAGS.gen_training_strategy == 'reinforce':
- evaluation_utils.generate_RL_logs(sess, model, log,
- id_to_word, train_feed)
- else:
- evaluation_utils.generate_logs(sess, model, log, id_to_word,
- train_feed)
- log.flush()
-
- log.close()
-
-
-def evaluate_once(data, sv, model, sess, train_dir, log, id_to_word,
- data_ngram_counts, eval_saver):
- """Evaluate model for a number of steps.
-
- Args:
- data: Dataset.
- sv: Supervisor.
- model: The GAN model we have just built.
- sess: A session to use.
- train_dir: Path to a directory containing checkpoints.
- log: Evaluation log for evaluation.
- id_to_word: Dictionary of indices to words.
- data_ngram_counts: Dictionary of hashed(n-gram tuples) to counts in the
- data_set.
- eval_saver: Evaluation saver.r.
- """
- tf.logging.info('Evaluate Once.')
- # Load the last model checkpoint, or initialize the graph.
- model_save_path = tf.latest_checkpoint(train_dir)
- if not model_save_path:
- tf.logging.warning('No checkpoint yet in: %s', train_dir)
- return
-
- tf.logging.info('Starting eval of: %s' % model_save_path)
- tf.logging.info('Only restoring trainable variables.')
- eval_saver.restore(sess, model_save_path)
-
- # Run the requested number of evaluation steps
- avg_epoch_gen_loss, avg_epoch_dis_loss = [], []
- cumulative_costs = 0.
-
- # Average percent captured for each of the n-grams.
- avg_percent_captured = {'2': 0., '3': 0., '4': 0.}
-
- # Set a random seed to keep fixed mask.
- np.random.seed(0)
- gen_iters = 0
-
- # Generator statefulness over the epoch.
- # TODO(liamfedus): Check this.
- [gen_initial_state_eval, fake_gen_initial_state_eval] = sess.run(
- [model.eval_initial_state, model.fake_gen_initial_state])
-
- if FLAGS.eval_language_model:
- is_present_rate = 0.
- tf.logging.info('Overriding is_present_rate=0. for evaluation.')
- print('Overriding is_present_rate=0. for evaluation.')
-
- iterator = get_iterator(data)
-
- for x, y, _ in iterator:
- if FLAGS.eval_language_model:
- is_present_rate = 0.
- else:
- is_present_rate = FLAGS.is_present_rate
- tf.logging.info('Evaluating on is_present_rate=%.3f.' % is_present_rate)
-
- model_utils.assign_percent_real(sess, model.percent_real_update,
- model.new_rate, is_present_rate)
-
- # Randomly mask out tokens.
- p = model_utils.generate_mask()
-
- eval_feed = {model.inputs: x, model.targets: y, model.present: p}
-
- if FLAGS.data_set == 'ptb':
- # Statefulness for *evaluation* Generator.
- for i, (c, h) in enumerate(model.eval_initial_state):
- eval_feed[c] = gen_initial_state_eval[i].c
- eval_feed[h] = gen_initial_state_eval[i].h
-
- # Statefulness for the Generator.
- for i, (c, h) in enumerate(model.fake_gen_initial_state):
- eval_feed[c] = fake_gen_initial_state_eval[i].c
- eval_feed[h] = fake_gen_initial_state_eval[i].h
-
- [
- gen_log_perplexity_eval, dis_loss_eval, gen_loss_eval,
- gen_initial_state_eval, fake_gen_initial_state_eval, step
- ] = sess.run(
- [
- model.avg_log_perplexity, model.dis_loss, model.gen_loss,
- model.eval_final_state, model.fake_gen_final_state,
- model.global_step
- ],
- feed_dict=eval_feed)
-
- for n, data_ngram_count in data_ngram_counts.iteritems():
- batch_percent_captured = evaluation_utils.sequence_ngram_evaluation(
- sess, model.fake_sequence, log, eval_feed, data_ngram_count, int(n))
- avg_percent_captured[n] += batch_percent_captured
-
- cumulative_costs += gen_log_perplexity_eval
-
- avg_epoch_dis_loss.append(dis_loss_eval)
- avg_epoch_gen_loss.append(gen_loss_eval)
-
- gen_iters += 1
-
- # Calulate rolling metrics.
- perplexity = np.exp(cumulative_costs / gen_iters)
- for n, _ in avg_percent_captured.iteritems():
- avg_percent_captured[n] /= gen_iters
-
- # Confirm perplexity is not infinite.
- if not np.isfinite(perplexity) or perplexity >= FLAGS.perplexity_threshold:
- print('Evaluation raising FloatingPointError.')
- raise FloatingPointError(
- 'Evaluation infinite perplexity: %.3f' % perplexity)
-
- ## Printing and logging.
- evaluation_utils.print_and_log_losses(log, step, is_present_rate,
- avg_epoch_dis_loss, avg_epoch_gen_loss)
- print(' perplexity: %.3f' % perplexity)
- log.write(' perplexity: %.3f\n' % perplexity)
-
- for n, n_gram_percent in avg_percent_captured.iteritems():
- n = int(n)
- print(' percent of %d-grams captured: %.3f.' % (n, n_gram_percent))
- log.write(' percent of %d-grams captured: %.3f.\n' % (n, n_gram_percent))
-
- samples = evaluation_utils.generate_logs(sess, model, log, id_to_word,
- eval_feed)
-
- ## Summaries.
- summary_str = sess.run(model.merge_summaries_op, feed_dict=eval_feed)
- sv.SummaryComputed(sess, summary_str)
-
- # Summary: text
- summary_str = sess.run(model.text_summary_op,
- {model.text_summary_placeholder: '\n\n'.join(samples)})
- sv.SummaryComputed(sess, summary_str, global_step=step)
-
- # Summary: n-gram
- for n, n_gram_percent in avg_percent_captured.iteritems():
- n = int(n)
- summary_percent_str = tf.Summary(value=[
- tf.Summary.Value(
- tag='general/%d-grams_percent_correct' % n,
- simple_value=n_gram_percent)
- ])
- sv.SummaryComputed(sess, summary_percent_str, global_step=step)
-
- # Summary: geometric_avg
- geometric_avg = compute_geometric_average(avg_percent_captured)
- summary_geometric_avg_str = tf.Summary(value=[
- tf.Summary.Value(tag='general/geometric_avg', simple_value=geometric_avg)
- ])
- sv.SummaryComputed(sess, summary_geometric_avg_str, global_step=step)
-
- # Summary: arithmetic_avg
- arithmetic_avg = compute_arithmetic_average(avg_percent_captured)
- summary_arithmetic_avg_str = tf.Summary(value=[
- tf.Summary.Value(
- tag='general/arithmetic_avg', simple_value=arithmetic_avg)
- ])
- sv.SummaryComputed(sess, summary_arithmetic_avg_str, global_step=step)
-
- # Summary: perplexity
- summary_perplexity_str = tf.Summary(value=[
- tf.Summary.Value(tag='general/perplexity', simple_value=perplexity)
- ])
- sv.SummaryComputed(sess, summary_perplexity_str, global_step=step)
-
-
-def evaluate_model(hparams, data, train_dir, log, id_to_word,
- data_ngram_counts):
- """Evaluate MaskGAN model.
-
- Args:
- hparams: Hyperparameters for the MaskGAN.
- data: Data to evaluate.
- train_dir: Path to a directory containing checkpoints.
- id_to_word: Dictionary of indices to words.
- data_ngram_counts: Dictionary of hashed(n-gram tuples) to counts in the
- data_set.
- """
- tf.logging.error('Evaluate model.')
-
- # Boolean indicating operational mode.
- is_training = False
-
- if FLAGS.mode == MODE_VALIDATION:
- logdir = FLAGS.base_directory + '/validation'
- elif FLAGS.mode == MODE_TRAIN_EVAL:
- logdir = FLAGS.base_directory + '/train_eval'
- elif FLAGS.mode == MODE_TEST:
- logdir = FLAGS.base_directory + '/test'
- else:
- raise NotImplementedError
-
- # Wait for a checkpoint to exist.
- print(train_dir)
- print(tf.train.latest_checkpoint(train_dir))
- while not tf.train.latest_checkpoint(train_dir):
- tf.logging.error('Waiting for checkpoint...')
- print('Waiting for checkpoint...')
- time.sleep(10)
-
- with tf.Graph().as_default():
- # Use a separate container for each trial
- container_name = ''
- with tf.container(container_name):
-
- # Construct the model.
- if FLAGS.num_rollouts == 1:
- model = create_MaskGAN(hparams, is_training)
- elif FLAGS.num_rollouts > 1:
- model = rollout.create_rollout_MaskGAN(hparams, is_training)
- else:
- raise ValueError
-
- # Create the supervisor. It will take care of initialization, summaries,
- # checkpoints, and recovery. We only pass the trainable variables
- # to load since things like baselines keep batch_size which may not
- # match between training and evaluation.
- evaluation_variables = tf.trainable_variables()
- evaluation_variables.append(model.global_step)
- eval_saver = tf.train.Saver(var_list=evaluation_variables)
- sv = tf.Supervisor(logdir=logdir)
- sess = sv.PrepareSession(FLAGS.eval_master, start_standard_services=False)
-
- tf.logging.info('Before sv.Loop.')
- sv.Loop(FLAGS.eval_interval_secs, evaluate_once,
- (data, sv, model, sess, train_dir, log, id_to_word,
- data_ngram_counts, eval_saver))
-
- sv.WaitForStop()
- tf.logging.info('sv.Stop().')
- sv.Stop()
-
-
-def main(_):
- hparams = create_hparams()
- train_dir = FLAGS.base_directory + '/train'
-
- # Load data set.
- if FLAGS.data_set == 'ptb':
- raw_data = ptb_loader.ptb_raw_data(FLAGS.data_dir)
- train_data, valid_data, test_data, _ = raw_data
- valid_data_flat = valid_data
- elif FLAGS.data_set == 'imdb':
- raw_data = imdb_loader.imdb_raw_data(FLAGS.data_dir)
- # TODO(liamfedus): Get an IMDB test partition.
- train_data, valid_data = raw_data
- valid_data_flat = [word for review in valid_data for word in review]
- else:
- raise NotImplementedError
-
- if FLAGS.mode == MODE_TRAIN or FLAGS.mode == MODE_TRAIN_EVAL:
- data_set = train_data
- elif FLAGS.mode == MODE_VALIDATION:
- data_set = valid_data
- elif FLAGS.mode == MODE_TEST:
- data_set = test_data
- else:
- raise NotImplementedError
-
- # Dictionary and reverse dictionry.
- if FLAGS.data_set == 'ptb':
- word_to_id = ptb_loader.build_vocab(
- os.path.join(FLAGS.data_dir, 'ptb.train.txt'))
- elif FLAGS.data_set == 'imdb':
- word_to_id = imdb_loader.build_vocab(
- os.path.join(FLAGS.data_dir, 'vocab.txt'))
- id_to_word = {v: k for k, v in word_to_id.iteritems()}
-
- # Dictionary of Training Set n-gram counts.
- bigram_tuples = n_gram.find_all_ngrams(valid_data_flat, n=2)
- trigram_tuples = n_gram.find_all_ngrams(valid_data_flat, n=3)
- fourgram_tuples = n_gram.find_all_ngrams(valid_data_flat, n=4)
-
- bigram_counts = n_gram.construct_ngrams_dict(bigram_tuples)
- trigram_counts = n_gram.construct_ngrams_dict(trigram_tuples)
- fourgram_counts = n_gram.construct_ngrams_dict(fourgram_tuples)
- print('Unique %d-grams: %d' % (2, len(bigram_counts)))
- print('Unique %d-grams: %d' % (3, len(trigram_counts)))
- print('Unique %d-grams: %d' % (4, len(fourgram_counts)))
-
- data_ngram_counts = {
- '2': bigram_counts,
- '3': trigram_counts,
- '4': fourgram_counts
- }
-
- # TODO(liamfedus): This was necessary because there was a problem with our
- # originally trained IMDB models. The EOS_INDEX was off by one, which means,
- # two words were mapping to index 86933. The presence of '' is going
- # to throw and out of vocabulary error.
- FLAGS.vocab_size = len(id_to_word)
- print('Vocab size: %d' % FLAGS.vocab_size)
-
- tf.gfile.MakeDirs(FLAGS.base_directory)
-
- if FLAGS.mode == MODE_TRAIN:
- log = tf.gfile.GFile(
- os.path.join(FLAGS.base_directory, 'train-log.txt'), mode='w')
- elif FLAGS.mode == MODE_VALIDATION:
- log = tf.gfile.GFile(
- os.path.join(FLAGS.base_directory, 'validation-log.txt'), mode='w')
- elif FLAGS.mode == MODE_TRAIN_EVAL:
- log = tf.gfile.GFile(
- os.path.join(FLAGS.base_directory, 'train_eval-log.txt'), mode='w')
- else:
- log = tf.gfile.GFile(
- os.path.join(FLAGS.base_directory, 'test-log.txt'), mode='w')
-
- if FLAGS.mode == MODE_TRAIN:
- train_model(hparams, data_set, train_dir, log, id_to_word,
- data_ngram_counts)
-
- elif FLAGS.mode == MODE_VALIDATION:
- evaluate_model(hparams, data_set, train_dir, log, id_to_word,
- data_ngram_counts)
- elif FLAGS.mode == MODE_TRAIN_EVAL:
- evaluate_model(hparams, data_set, train_dir, log, id_to_word,
- data_ngram_counts)
-
- elif FLAGS.mode == MODE_TEST:
- evaluate_model(hparams, data_set, train_dir, log, id_to_word,
- data_ngram_counts)
-
- else:
- raise NotImplementedError
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/namignizer/.gitignore b/research/namignizer/.gitignore
deleted file mode 100644
index 2dae8043534bc7a079f36caa6c673f74c39e5dfa..0000000000000000000000000000000000000000
--- a/research/namignizer/.gitignore
+++ /dev/null
@@ -1,6 +0,0 @@
-# Remove the pyc files
-*.pyc
-
-# Ignore the model and the data
-model/
-data/
diff --git a/research/namignizer/README.md b/research/namignizer/README.md
deleted file mode 100644
index 475a087541913aaa3fca9d2094b4c23de52dbb41..0000000000000000000000000000000000000000
--- a/research/namignizer/README.md
+++ /dev/null
@@ -1,86 +0,0 @@
-
-
-
-
-# Namignizer
-
-Use a variation of the [PTB](https://www.tensorflow.org/versions/r0.8/tutorials/recurrent/index.html#recurrent-neural-networks) model to recognize and generate names using the [Kaggle Baby Name Database](https://www.kaggle.com/kaggle/us-baby-names).
-
-### API
-Namignizer is implemented in Tensorflow 0.8r and uses the python package `pandas` for some data processing.
-
-#### How to use
-Download the data from Kaggle and place it in your data directory (or use the small training data provided). The example data looks like so:
-
-```
-Id,Name,Year,Gender,Count
-1,Mary,1880,F,7065
-2,Anna,1880,F,2604
-3,Emma,1880,F,2003
-4,Elizabeth,1880,F,1939
-5,Minnie,1880,F,1746
-6,Margaret,1880,F,1578
-7,Ida,1880,F,1472
-8,Alice,1880,F,1414
-9,Bertha,1880,F,1320
-```
-
-But any data with the two columns: `Name` and `Count` will work.
-
-With the data, we can then train the model:
-
-```python
-train("data/SmallNames.txt", "model/namignizer", SmallConfig)
-```
-
-And you will get the output:
-
-```
-Reading Name data in data/SmallNames.txt
-Epoch: 1 Learning rate: 1.000
-0.090 perplexity: 18.539 speed: 282 lps
-...
-0.890 perplexity: 1.478 speed: 285 lps
-0.990 perplexity: 1.477 speed: 284 lps
-Epoch: 13 Train Perplexity: 1.477
-```
-
-This will as a side effect write model checkpoints to the `model` directory. With this you will be able to determine the perplexity your model will give you for any arbitrary set of names like so:
-
-```python
-namignize(["mary", "ida", "gazorpazorp", "houyhnhnms", "bob"],
- tf.train.latest_checkpoint("model"), SmallConfig)
-```
-You will provide the same config and the same checkpoint directory. This will allow you to use a the model you just trained. You will then get a perplexity output for each name like so:
-
-```
-Name mary gives us a perplexity of 1.03105580807
-Name ida gives us a perplexity of 1.07770049572
-Name gazorpazorp gives us a perplexity of 175.940353394
-Name houyhnhnms gives us a perplexity of 9.53870773315
-Name bob gives us a perplexity of 6.03938627243
-```
-
-Finally, you will also be able generate names using the model like so:
-
-```python
-namignator(tf.train.latest_checkpoint("model"), SmallConfig)
-```
-
-Again, you will need to provide the same config and the same checkpoint directory. This will allow you to use a the model you just trained. You will then get a single generated name. Examples of output that I got when using the provided data are:
-
-```
-['b', 'e', 'r', 't', 'h', 'a', '`']
-['m', 'a', 'r', 'y', '`']
-['a', 'n', 'n', 'a', '`']
-['m', 'a', 'r', 'y', '`']
-['b', 'e', 'r', 't', 'h', 'a', '`']
-['a', 'n', 'n', 'a', '`']
-['e', 'l', 'i', 'z', 'a', 'b', 'e', 't', 'h', '`']
-```
-
-Notice that each name ends with a backtick. This marks the end of the name.
-
-### Contact Info
-
-Feel free to reach out to me at knt(at google) or k.nathaniel.tucker(at gmail)
diff --git a/research/namignizer/data_utils.py b/research/namignizer/data_utils.py
deleted file mode 100644
index 4320215026ccf7a2b31ffd476c25a153ecd92b86..0000000000000000000000000000000000000000
--- a/research/namignizer/data_utils.py
+++ /dev/null
@@ -1,119 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""Utilities for parsing Kaggle baby names files."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-import os
-
-import numpy as np
-import tensorflow as tf
-import pandas as pd
-
-# the default end of name rep will be zero
-_EON = 0
-
-
-def read_names(names_path):
- """read data from downloaded file. See SmallNames.txt for example format
- or go to https://www.kaggle.com/kaggle/us-baby-names for full lists
-
- Args:
- names_path: path to the csv file similar to the example type
- Returns:
- Dataset: a namedtuple of two elements: deduped names and their associated
- counts. The names contain only 26 chars and are all lower case
- """
- names_data = pd.read_csv(names_path)
- names_data.Name = names_data.Name.str.lower()
-
- name_data = names_data.groupby(by=["Name"])["Count"].sum()
- name_counts = np.array(name_data.tolist())
- names_deduped = np.array(name_data.index.tolist())
-
- Dataset = collections.namedtuple('Dataset', ['Name', 'Count'])
- return Dataset(names_deduped, name_counts)
-
-
-def _letter_to_number(letter):
- """converts letters to numbers between 1 and 27"""
- # ord of lower case 'a' is 97
- return ord(letter) - 96
-
-
-def namignizer_iterator(names, counts, batch_size, num_steps, epoch_size):
- """Takes a list of names and counts like those output from read_names, and
- makes an iterator yielding a batch_size by num_steps array of random names
- separated by an end of name token. The names are chosen randomly according
- to their counts. The batch may end mid-name
-
- Args:
- names: a set of lowercase names composed of 26 characters
- counts: a list of the frequency of those names
- batch_size: int
- num_steps: int
- epoch_size: number of batches to yield
- Yields:
- (x, y): a batch_size by num_steps array of ints representing letters, where
- x will be the input and y will be the target
- """
- name_distribution = counts / counts.sum()
-
- for i in range(epoch_size):
- data = np.zeros(batch_size * num_steps + 1)
- samples = np.random.choice(names, size=batch_size * num_steps // 2,
- replace=True, p=name_distribution)
-
- data_index = 0
- for sample in samples:
- if data_index >= batch_size * num_steps:
- break
- for letter in map(_letter_to_number, sample) + [_EON]:
- if data_index >= batch_size * num_steps:
- break
- data[data_index] = letter
- data_index += 1
-
- x = data[:batch_size * num_steps].reshape((batch_size, num_steps))
- y = data[1:batch_size * num_steps + 1].reshape((batch_size, num_steps))
-
- yield (x, y)
-
-
-def name_to_batch(name, batch_size, num_steps):
- """ Takes a single name and fills a batch with it
-
- Args:
- name: lowercase composed of 26 characters
- batch_size: int
- num_steps: int
- Returns:
- x, y: a batch_size by num_steps array of ints representing letters, where
- x will be the input and y will be the target. The array is filled up
- to the length of the string, the rest is filled with zeros
- """
- data = np.zeros(batch_size * num_steps + 1)
-
- data_index = 0
- for letter in map(_letter_to_number, name) + [_EON]:
- data[data_index] = letter
- data_index += 1
-
- x = data[:batch_size * num_steps].reshape((batch_size, num_steps))
- y = data[1:batch_size * num_steps + 1].reshape((batch_size, num_steps))
-
- return x, y
diff --git a/research/namignizer/model.py b/research/namignizer/model.py
deleted file mode 100644
index 72c5c5ecb61e8a92ec2e74b8cc7ca13bb6ace817..0000000000000000000000000000000000000000
--- a/research/namignizer/model.py
+++ /dev/null
@@ -1,136 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""RNN model with embeddings"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-
-class NamignizerModel(object):
- """The Namignizer model ~ strongly based on PTB"""
-
- def __init__(self, is_training, config):
- self.batch_size = batch_size = config.batch_size
- self.num_steps = num_steps = config.num_steps
- size = config.hidden_size
- # will always be 27
- vocab_size = config.vocab_size
-
- # placeholders for inputs
- self._input_data = tf.placeholder(tf.int32, [batch_size, num_steps])
- self._targets = tf.placeholder(tf.int32, [batch_size, num_steps])
- # weights for the loss function
- self._weights = tf.placeholder(tf.float32, [batch_size * num_steps])
-
- # lstm for our RNN cell (GRU supported too)
- lstm_cells = []
- for layer in range(config.num_layers):
- lstm_cell = tf.contrib.rnn.BasicLSTMCell(size, forget_bias=0.0)
- if is_training and config.keep_prob < 1:
- lstm_cell = tf.contrib.rnn.DropoutWrapper(
- lstm_cell, output_keep_prob=config.keep_prob)
- lstm_cells.append(lstm_cell)
- cell = tf.contrib.rnn.MultiRNNCell(lstm_cells)
-
- self._initial_state = cell.zero_state(batch_size, tf.float32)
-
- with tf.device("/cpu:0"):
- embedding = tf.get_variable("embedding", [vocab_size, size])
- inputs = tf.nn.embedding_lookup(embedding, self._input_data)
-
- if is_training and config.keep_prob < 1:
- inputs = tf.nn.dropout(inputs, config.keep_prob)
-
- outputs = []
- state = self._initial_state
- with tf.variable_scope("RNN"):
- for time_step in range(num_steps):
- if time_step > 0:
- tf.get_variable_scope().reuse_variables()
- (cell_output, state) = cell(inputs[:, time_step, :], state)
- outputs.append(cell_output)
-
- output = tf.reshape(tf.concat(axis=1, values=outputs), [-1, size])
- softmax_w = tf.get_variable("softmax_w", [size, vocab_size])
- softmax_b = tf.get_variable("softmax_b", [vocab_size])
- logits = tf.matmul(output, softmax_w) + softmax_b
- loss = tf.contrib.legacy_seq2seq.sequence_loss_by_example(
- [logits],
- [tf.reshape(self._targets, [-1])],
- [self._weights])
- self._loss = loss
- self._cost = cost = tf.reduce_sum(loss) / batch_size
- self._final_state = state
-
- # probabilities of each letter
- self._activations = tf.nn.softmax(logits)
-
- # ability to save the model
- self.saver = tf.train.Saver(tf.global_variables())
-
- if not is_training:
- return
-
- self._lr = tf.Variable(0.0, trainable=False)
- tvars = tf.trainable_variables()
- grads, _ = tf.clip_by_global_norm(tf.gradients(cost, tvars),
- config.max_grad_norm)
- optimizer = tf.train.GradientDescentOptimizer(self.lr)
- self._train_op = optimizer.apply_gradients(zip(grads, tvars))
-
- def assign_lr(self, session, lr_value):
- session.run(tf.assign(self.lr, lr_value))
-
- @property
- def input_data(self):
- return self._input_data
-
- @property
- def targets(self):
- return self._targets
-
- @property
- def activations(self):
- return self._activations
-
- @property
- def weights(self):
- return self._weights
-
- @property
- def initial_state(self):
- return self._initial_state
-
- @property
- def cost(self):
- return self._cost
-
- @property
- def loss(self):
- return self._loss
-
- @property
- def final_state(self):
- return self._final_state
-
- @property
- def lr(self):
- return self._lr
-
- @property
- def train_op(self):
- return self._train_op
diff --git a/research/namignizer/names.py b/research/namignizer/names.py
deleted file mode 100644
index 253742716391f2f4b7a0c0cf4987e40a2aaa808f..0000000000000000000000000000000000000000
--- a/research/namignizer/names.py
+++ /dev/null
@@ -1,259 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-"""A library showing off sequence recognition and generation with the simple
-example of names.
-
-We use recurrent neural nets to learn complex functions able to recognize and
-generate sequences of a given form. This can be used for natural language
-syntax recognition, dynamically generating maps or puzzles and of course
-baby name generation.
-
-Before using this module, it is recommended to read the Tensorflow tutorial on
-recurrent neural nets, as it explains the basic concepts of this model, and
-will show off another module, the PTB module on which this model bases itself.
-
-Here is an overview of the functions available in this module:
-
-* RNN Module for sequence functions based on PTB
-
-* Name recognition specifically for recognizing names, but can be adapted to
- recognizing sequence patterns
-
-* Name generations specifically for generating names, but can be adapted to
- generating arbitrary sequence patterns
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import time
-
-import tensorflow as tf
-import numpy as np
-
-from model import NamignizerModel
-import data_utils
-
-
-class SmallConfig(object):
- """Small config."""
- init_scale = 0.1
- learning_rate = 1.0
- max_grad_norm = 5
- num_layers = 2
- num_steps = 20
- hidden_size = 200
- max_epoch = 4
- max_max_epoch = 13
- keep_prob = 1.0
- lr_decay = 0.5
- batch_size = 20
- vocab_size = 27
- epoch_size = 100
-
-
-class LargeConfig(object):
- """Medium config."""
- init_scale = 0.05
- learning_rate = 1.0
- max_grad_norm = 5
- num_layers = 2
- num_steps = 35
- hidden_size = 650
- max_epoch = 6
- max_max_epoch = 39
- keep_prob = 0.5
- lr_decay = 0.8
- batch_size = 20
- vocab_size = 27
- epoch_size = 100
-
-
-class TestConfig(object):
- """Tiny config, for testing."""
- init_scale = 0.1
- learning_rate = 1.0
- max_grad_norm = 1
- num_layers = 1
- num_steps = 2
- hidden_size = 2
- max_epoch = 1
- max_max_epoch = 1
- keep_prob = 1.0
- lr_decay = 0.5
- batch_size = 20
- vocab_size = 27
- epoch_size = 100
-
-
-def run_epoch(session, m, names, counts, epoch_size, eval_op, verbose=False):
- """Runs the model on the given data for one epoch
-
- Args:
- session: the tf session holding the model graph
- m: an instance of the NamignizerModel
- names: a set of lowercase names of 26 characters
- counts: a list of the frequency of the above names
- epoch_size: the number of batches to run
- eval_op: whether to change the params or not, and how to do it
- Kwargs:
- verbose: whether to print out state of training during the epoch
- Returns:
- cost: the average cost during the last stage of the epoch
- """
- start_time = time.time()
- costs = 0.0
- iters = 0
- for step, (x, y) in enumerate(data_utils.namignizer_iterator(names, counts,
- m.batch_size, m.num_steps, epoch_size)):
-
- cost, _ = session.run([m.cost, eval_op],
- {m.input_data: x,
- m.targets: y,
- m.weights: np.ones(m.batch_size * m.num_steps)})
- costs += cost
- iters += m.num_steps
-
- if verbose and step % (epoch_size // 10) == 9:
- print("%.3f perplexity: %.3f speed: %.0f lps" %
- (step * 1.0 / epoch_size, np.exp(costs / iters),
- iters * m.batch_size / (time.time() - start_time)))
-
- if step >= epoch_size:
- break
-
- return np.exp(costs / iters)
-
-
-def train(data_dir, checkpoint_path, config):
- """Trains the model with the given data
-
- Args:
- data_dir: path to the data for the model (see data_utils for data
- format)
- checkpoint_path: the path to save the trained model checkpoints
- config: one of the above configs that specify the model and how it
- should be run and trained
- Returns:
- None
- """
- # Prepare Name data.
- print("Reading Name data in %s" % data_dir)
- names, counts = data_utils.read_names(data_dir)
-
- with tf.Graph().as_default(), tf.Session() as session:
- initializer = tf.random_uniform_initializer(-config.init_scale,
- config.init_scale)
- with tf.variable_scope("model", reuse=None, initializer=initializer):
- m = NamignizerModel(is_training=True, config=config)
-
- tf.global_variables_initializer().run()
-
- for i in range(config.max_max_epoch):
- lr_decay = config.lr_decay ** max(i - config.max_epoch, 0.0)
- m.assign_lr(session, config.learning_rate * lr_decay)
-
- print("Epoch: %d Learning rate: %.3f" % (i + 1, session.run(m.lr)))
- train_perplexity = run_epoch(session, m, names, counts, config.epoch_size, m.train_op,
- verbose=True)
- print("Epoch: %d Train Perplexity: %.3f" %
- (i + 1, train_perplexity))
-
- m.saver.save(session, checkpoint_path, global_step=i)
-
-
-def namignize(names, checkpoint_path, config):
- """Recognizes names and prints the Perplexity of the model for each names
- in the list
-
- Args:
- names: a list of names in the model format
- checkpoint_path: the path to restore the trained model from, should not
- include the model name, just the path to
- config: one of the above configs that specify the model and how it
- should be run and trained
- Returns:
- None
- """
- with tf.Graph().as_default(), tf.Session() as session:
-
- with tf.variable_scope("model"):
- m = NamignizerModel(is_training=False, config=config)
-
- m.saver.restore(session, checkpoint_path)
-
- for name in names:
- x, y = data_utils.name_to_batch(name, m.batch_size, m.num_steps)
-
- cost, loss, _ = session.run([m.cost, m.loss, tf.no_op()],
- {m.input_data: x,
- m.targets: y,
- m.weights: np.concatenate((
- np.ones(len(name)), np.zeros(m.batch_size * m.num_steps - len(name))))})
-
- print("Name {} gives us a perplexity of {}".format(
- name, np.exp(cost)))
-
-
-def namignator(checkpoint_path, config):
- """Generates names randomly according to a given model
-
- Args:
- checkpoint_path: the path to restore the trained model from, should not
- include the model name, just the path to
- config: one of the above configs that specify the model and how it
- should be run and trained
- Returns:
- None
- """
- # mutate the config to become a name generator config
- config.num_steps = 1
- config.batch_size = 1
-
- with tf.Graph().as_default(), tf.Session() as session:
-
- with tf.variable_scope("model"):
- m = NamignizerModel(is_training=False, config=config)
-
- m.saver.restore(session, checkpoint_path)
-
- activations, final_state, _ = session.run([m.activations, m.final_state, tf.no_op()],
- {m.input_data: np.zeros((1, 1)),
- m.targets: np.zeros((1, 1)),
- m.weights: np.ones(1)})
-
- # sample from our softmax activations
- next_letter = np.random.choice(27, p=activations[0])
- name = [next_letter]
- while next_letter != 0:
- activations, final_state, _ = session.run([m.activations, m.final_state, tf.no_op()],
- {m.input_data: [[next_letter]],
- m.targets: np.zeros((1, 1)),
- m.initial_state: final_state,
- m.weights: np.ones(1)})
-
- next_letter = np.random.choice(27, p=activations[0])
- name += [next_letter]
-
- print(map(lambda x: chr(x + 96), name))
-
-
-if __name__ == "__main__":
- train("data/SmallNames.txt", "model/namignizer", SmallConfig)
-
- namignize(["mary", "ida", "gazorbazorb", "mmmhmm", "bob"],
- tf.train.latest_checkpoint("model"), SmallConfig)
-
- namignator(tf.train.latest_checkpoint("model"), SmallConfig)
diff --git a/research/neural_gpu/README.md b/research/neural_gpu/README.md
deleted file mode 100644
index 097ef318c4e071f59e4212b0cd901907758d73e7..0000000000000000000000000000000000000000
--- a/research/neural_gpu/README.md
+++ /dev/null
@@ -1,87 +0,0 @@
-
-
-
-
-# NeuralGPU
-Code for the Neural GPU model described in http://arxiv.org/abs/1511.08228.
-The extended version was described in https://arxiv.org/abs/1610.08613.
-
-Requirements:
-* TensorFlow (see tensorflow.org for how to install)
-
-The model can be trained on the following algorithmic tasks:
-
-* `sort` - Sort a symbol list
-* `kvsort` - Sort symbol keys in dictionary
-* `id` - Return the same symbol list
-* `rev` - Reverse a symbol list
-* `rev2` - Reverse a symbol dictionary by key
-* `incr` - Add one to a symbol value
-* `add` - Long decimal addition
-* `left` - First symbol in list
-* `right` - Last symbol in list
-* `left-shift` - Left shift a symbol list
-* `right-shift` - Right shift a symbol list
-* `bmul` - Long binary multiplication
-* `mul` - Long decimal multiplication
-* `dup` - Duplicate a symbol list with padding
-* `badd` - Long binary addition
-* `qadd` - Long quaternary addition
-* `search` - Search for symbol key in dictionary
-
-It can also be trained on the WMT English-French translation task:
-
-* `wmt` - WMT English-French translation (data will be downloaded)
-
-The value range for symbols are defined by the `vocab_size` flag.
-In particular, the values are in the range `vocab_size - 1`.
-So if you set `--vocab_size=16` (the default) then `--problem=rev`
-will be reversing lists of 15 symbols, and `--problem=id` will be identity
-on a list of up to 15 symbols.
-
-
-To train the model on the binary multiplication task run:
-
-```
-python neural_gpu_trainer.py --problem=bmul
-```
-
-This trains the Extended Neural GPU, to train the original model run:
-
-```
-python neural_gpu_trainer.py --problem=bmul --beam_size=0
-```
-
-While training, interim / checkpoint model parameters will be
-written to `/tmp/neural_gpu/`.
-
-Once the amount of error gets down to what you're comfortable
-with, hit `Ctrl-C` to stop the training process. The latest
-model parameters will be in `/tmp/neural_gpu/neural_gpu.ckpt-`
-and used on any subsequent run.
-
-To evaluate a trained model on how well it decodes run:
-
-```
-python neural_gpu_trainer.py --problem=bmul --mode=1
-```
-
-To interact with a model (experimental, see code) run:
-
-```
-python neural_gpu_trainer.py --problem=bmul --mode=2
-```
-
-To train on WMT data, set a larger --nmaps and --vocab_size and avoid curriculum:
-
-```
-python neural_gpu_trainer.py --problem=wmt --vocab_size=32768 --nmaps=256
- --vec_size=256 --curriculum_seq=1.0 --max_length=60 --data_dir ~/wmt
-```
-
-With less memory, try lower batch size, e.g. `--batch_size=4`. With more GPUs
-in your system, there will be a batch on every GPU so you can run larger models.
-For example, `--batch_size=4 --num_gpus=4 --nmaps=512 --vec_size=512` will
-run a large model (512-size) on 4 GPUs, with effective batches of 4*4=16.
-
-Maintained by Lukasz Kaiser (lukaszkaiser)
diff --git a/research/neural_gpu/data_utils.py b/research/neural_gpu/data_utils.py
deleted file mode 100644
index 3c14ff701fce79408fde6505239530dc5b848dd7..0000000000000000000000000000000000000000
--- a/research/neural_gpu/data_utils.py
+++ /dev/null
@@ -1,458 +0,0 @@
-# Copyright 2015 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Neural GPU -- data generation and batching utilities."""
-
-import math
-import os
-import random
-import sys
-import time
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-import program_utils
-
-FLAGS = tf.app.flags.FLAGS
-
-bins = [2 + bin_idx_i for bin_idx_i in xrange(256)]
-all_tasks = ["sort", "kvsort", "id", "rev", "rev2", "incr", "add", "left",
- "right", "left-shift", "right-shift", "bmul", "mul", "dup",
- "badd", "qadd", "search", "progeval", "progsynth"]
-log_filename = ""
-vocab, rev_vocab = None, None
-
-
-def pad(l):
- for b in bins:
- if b >= l: return b
- return bins[-1]
-
-
-def bin_for(l):
- for i, b in enumerate(bins):
- if b >= l: return i
- return len(bins) - 1
-
-
-train_set = {}
-test_set = {}
-for some_task in all_tasks:
- train_set[some_task] = []
- test_set[some_task] = []
- for all_max_len in xrange(10000):
- train_set[some_task].append([])
- test_set[some_task].append([])
-
-
-def read_tmp_file(name):
- """Read from a file with the given name in our log directory or above."""
- dirname = os.path.dirname(log_filename)
- fname = os.path.join(dirname, name + ".txt")
- if not tf.gfile.Exists(fname):
- print_out("== not found file: " + fname)
- fname = os.path.join(dirname, "../" + name + ".txt")
- if not tf.gfile.Exists(fname):
- print_out("== not found file: " + fname)
- fname = os.path.join(dirname, "../../" + name + ".txt")
- if not tf.gfile.Exists(fname):
- print_out("== not found file: " + fname)
- return None
- print_out("== found file: " + fname)
- res = []
- with tf.gfile.GFile(fname, mode="r") as f:
- for line in f:
- res.append(line.strip())
- return res
-
-
-def write_tmp_file(name, lines):
- dirname = os.path.dirname(log_filename)
- fname = os.path.join(dirname, name + ".txt")
- with tf.gfile.GFile(fname, mode="w") as f:
- for line in lines:
- f.write(line + "\n")
-
-
-def add(n1, n2, base=10):
- """Add two numbers represented as lower-endian digit lists."""
- k = max(len(n1), len(n2)) + 1
- d1 = n1 + [0 for _ in xrange(k - len(n1))]
- d2 = n2 + [0 for _ in xrange(k - len(n2))]
- res = []
- carry = 0
- for i in xrange(k):
- if d1[i] + d2[i] + carry < base:
- res.append(d1[i] + d2[i] + carry)
- carry = 0
- else:
- res.append(d1[i] + d2[i] + carry - base)
- carry = 1
- while res and res[-1] == 0:
- res = res[:-1]
- if res: return res
- return [0]
-
-
-def init_data(task, length, nbr_cases, nclass):
- """Data initialization."""
- def rand_pair(l, task):
- """Random data pair for a task. Total length should be <= l."""
- k = int((l-1)/2)
- base = 10
- if task[0] == "b": base = 2
- if task[0] == "q": base = 4
- d1 = [np.random.randint(base) for _ in xrange(k)]
- d2 = [np.random.randint(base) for _ in xrange(k)]
- if task in ["add", "badd", "qadd"]:
- res = add(d1, d2, base)
- elif task in ["mul", "bmul"]:
- d1n = sum([d * (base ** i) for i, d in enumerate(d1)])
- d2n = sum([d * (base ** i) for i, d in enumerate(d2)])
- if task == "bmul":
- res = [int(x) for x in list(reversed(str(bin(d1n * d2n))))[:-2]]
- else:
- res = [int(x) for x in list(reversed(str(d1n * d2n)))]
- else:
- sys.exit()
- sep = [12]
- if task in ["add", "badd", "qadd"]: sep = [11]
- inp = [d + 1 for d in d1] + sep + [d + 1 for d in d2]
- return inp, [r + 1 for r in res]
-
- def rand_dup_pair(l):
- """Random data pair for duplication task. Total length should be <= l."""
- k = int(l/2)
- x = [np.random.randint(nclass - 1) + 1 for _ in xrange(k)]
- inp = x + [0 for _ in xrange(l - k)]
- res = x + x + [0 for _ in xrange(l - 2*k)]
- return inp, res
-
- def rand_rev2_pair(l):
- """Random data pair for reverse2 task. Total length should be <= l."""
- inp = [(np.random.randint(nclass - 1) + 1,
- np.random.randint(nclass - 1) + 1) for _ in xrange(l/2)]
- res = [i for i in reversed(inp)]
- return [x for p in inp for x in p], [x for p in res for x in p]
-
- def rand_search_pair(l):
- """Random data pair for search task. Total length should be <= l."""
- inp = [(np.random.randint(nclass - 1) + 1,
- np.random.randint(nclass - 1) + 1) for _ in xrange(l-1/2)]
- q = np.random.randint(nclass - 1) + 1
- res = 0
- for (k, v) in reversed(inp):
- if k == q:
- res = v
- return [x for p in inp for x in p] + [q], [res]
-
- def rand_kvsort_pair(l):
- """Random data pair for key-value sort. Total length should be <= l."""
- keys = [(np.random.randint(nclass - 1) + 1, i) for i in xrange(l/2)]
- vals = [np.random.randint(nclass - 1) + 1 for _ in xrange(l/2)]
- kv = [(k, vals[i]) for (k, i) in keys]
- sorted_kv = [(k, vals[i]) for (k, i) in sorted(keys)]
- return [x for p in kv for x in p], [x for p in sorted_kv for x in p]
-
- def prog_io_pair(prog, max_len, counter=0):
- try:
- ilen = np.random.randint(max_len - 3) + 1
- bound = max(15 - (counter / 20), 1)
- inp = [random.choice(range(-bound, bound)) for _ in range(ilen)]
- inp_toks = [program_utils.prog_rev_vocab[t]
- for t in program_utils.tokenize(str(inp)) if t != ","]
- out = program_utils.evaluate(prog, {"a": inp})
- out_toks = [program_utils.prog_rev_vocab[t]
- for t in program_utils.tokenize(str(out)) if t != ","]
- if counter > 400:
- out_toks = []
- if (out_toks and out_toks[0] == program_utils.prog_rev_vocab["["] and
- len(out_toks) != len([o for o in out if o == ","]) + 3):
- raise ValueError("generated list with too long ints")
- if (out_toks and out_toks[0] != program_utils.prog_rev_vocab["["] and
- len(out_toks) > 1):
- raise ValueError("generated one int but tokenized it to many")
- if len(out_toks) > max_len:
- raise ValueError("output too long")
- return (inp_toks, out_toks)
- except ValueError:
- return prog_io_pair(prog, max_len, counter+1)
-
- def spec(inp):
- """Return the target given the input for some tasks."""
- if task == "sort":
- return sorted(inp)
- elif task == "id":
- return inp
- elif task == "rev":
- return [i for i in reversed(inp)]
- elif task == "incr":
- carry = 1
- res = []
- for i in xrange(len(inp)):
- if inp[i] + carry < nclass:
- res.append(inp[i] + carry)
- carry = 0
- else:
- res.append(1)
- carry = 1
- return res
- elif task == "left":
- return [inp[0]]
- elif task == "right":
- return [inp[-1]]
- elif task == "left-shift":
- return [inp[l-1] for l in xrange(len(inp))]
- elif task == "right-shift":
- return [inp[l+1] for l in xrange(len(inp))]
- else:
- print_out("Unknown spec for task " + str(task))
- sys.exit()
-
- l = length
- cur_time = time.time()
- total_time = 0.0
-
- is_prog = task in ["progeval", "progsynth"]
- if is_prog:
- inputs_per_prog = 5
- program_utils.make_vocab()
- progs = read_tmp_file("programs_len%d" % (l / 10))
- if not progs:
- progs = program_utils.gen(l / 10, 1.2 * nbr_cases / inputs_per_prog)
- write_tmp_file("programs_len%d" % (l / 10), progs)
- prog_ios = read_tmp_file("programs_len%d_io" % (l / 10))
- nbr_cases = min(nbr_cases, len(progs) * inputs_per_prog) / 1.2
- if not prog_ios:
- # Generate program io data.
- prog_ios = []
- for pidx, prog in enumerate(progs):
- if pidx % 500 == 0:
- print_out("== generating io pairs for program %d" % pidx)
- if pidx * inputs_per_prog > nbr_cases * 1.2:
- break
- ptoks = [program_utils.prog_rev_vocab[t]
- for t in program_utils.tokenize(prog)]
- ptoks.append(program_utils.prog_rev_vocab["_EOS"])
- plen = len(ptoks)
- for _ in xrange(inputs_per_prog):
- if task == "progeval":
- inp, out = prog_io_pair(prog, plen)
- prog_ios.append(str(inp) + "\t" + str(out) + "\t" + prog)
- elif task == "progsynth":
- plen = max(len(ptoks), 8)
- for _ in xrange(3):
- inp, out = prog_io_pair(prog, plen / 2)
- prog_ios.append(str(inp) + "\t" + str(out) + "\t" + prog)
- write_tmp_file("programs_len%d_io" % (l / 10), prog_ios)
- prog_ios_dict = {}
- for s in prog_ios:
- i, o, p = s.split("\t")
- i_clean = "".join([c for c in i if c.isdigit() or c == " "])
- o_clean = "".join([c for c in o if c.isdigit() or c == " "])
- inp = [int(x) for x in i_clean.split()]
- out = [int(x) for x in o_clean.split()]
- if inp and out:
- if p in prog_ios_dict:
- prog_ios_dict[p].append([inp, out])
- else:
- prog_ios_dict[p] = [[inp, out]]
- # Use prog_ios_dict to create data.
- progs = []
- for prog in prog_ios_dict:
- if len([c for c in prog if c == ";"]) <= (l / 10):
- progs.append(prog)
- nbr_cases = min(nbr_cases, len(progs) * inputs_per_prog) / 1.2
- print_out("== %d training cases on %d progs" % (nbr_cases, len(progs)))
- for pidx, prog in enumerate(progs):
- if pidx * inputs_per_prog > nbr_cases * 1.2:
- break
- ptoks = [program_utils.prog_rev_vocab[t]
- for t in program_utils.tokenize(prog)]
- ptoks.append(program_utils.prog_rev_vocab["_EOS"])
- plen = len(ptoks)
- dset = train_set if pidx < nbr_cases / inputs_per_prog else test_set
- for _ in xrange(inputs_per_prog):
- if task == "progeval":
- inp, out = prog_ios_dict[prog].pop()
- dset[task][bin_for(plen)].append([[ptoks, inp, [], []], [out]])
- elif task == "progsynth":
- plen, ilist = max(len(ptoks), 8), [[]]
- for _ in xrange(3):
- inp, out = prog_ios_dict[prog].pop()
- ilist.append(inp + out)
- dset[task][bin_for(plen)].append([ilist, [ptoks]])
-
- for case in xrange(0 if is_prog else nbr_cases):
- total_time += time.time() - cur_time
- cur_time = time.time()
- if l > 10000 and case % 100 == 1:
- print_out(" avg gen time %.4f s" % (total_time / float(case)))
- if task in ["add", "badd", "qadd", "bmul", "mul"]:
- i, t = rand_pair(l, task)
- train_set[task][bin_for(len(i))].append([[[], i, [], []], [t]])
- i, t = rand_pair(l, task)
- test_set[task][bin_for(len(i))].append([[[], i, [], []], [t]])
- elif task == "dup":
- i, t = rand_dup_pair(l)
- train_set[task][bin_for(len(i))].append([[i], [t]])
- i, t = rand_dup_pair(l)
- test_set[task][bin_for(len(i))].append([[i], [t]])
- elif task == "rev2":
- i, t = rand_rev2_pair(l)
- train_set[task][bin_for(len(i))].append([[i], [t]])
- i, t = rand_rev2_pair(l)
- test_set[task][bin_for(len(i))].append([[i], [t]])
- elif task == "search":
- i, t = rand_search_pair(l)
- train_set[task][bin_for(len(i))].append([[i], [t]])
- i, t = rand_search_pair(l)
- test_set[task][bin_for(len(i))].append([[i], [t]])
- elif task == "kvsort":
- i, t = rand_kvsort_pair(l)
- train_set[task][bin_for(len(i))].append([[i], [t]])
- i, t = rand_kvsort_pair(l)
- test_set[task][bin_for(len(i))].append([[i], [t]])
- elif task not in ["progeval", "progsynth"]:
- inp = [np.random.randint(nclass - 1) + 1 for i in xrange(l)]
- target = spec(inp)
- train_set[task][bin_for(l)].append([[inp], [target]])
- inp = [np.random.randint(nclass - 1) + 1 for i in xrange(l)]
- target = spec(inp)
- test_set[task][bin_for(l)].append([[inp], [target]])
-
-
-def to_symbol(i):
- """Covert ids to text."""
- if i == 0: return ""
- if i == 11: return "+"
- if i == 12: return "*"
- return str(i-1)
-
-
-def to_id(s):
- """Covert text to ids."""
- if s == "+": return 11
- if s == "*": return 12
- return int(s) + 1
-
-
-def get_batch(bin_id, batch_size, data_set, height, offset=None, preset=None):
- """Get a batch of data, training or testing."""
- inputs, targets = [], []
- pad_length = bins[bin_id]
- for b in xrange(batch_size):
- if preset is None:
- elem = random.choice(data_set[bin_id])
- if offset is not None and offset + b < len(data_set[bin_id]):
- elem = data_set[bin_id][offset + b]
- else:
- elem = preset
- inpt, targett, inpl, targetl = elem[0], elem[1], [], []
- for inp in inpt:
- inpl.append(inp + [0 for _ in xrange(pad_length - len(inp))])
- if len(inpl) == 1:
- for _ in xrange(height - 1):
- inpl.append([0 for _ in xrange(pad_length)])
- for target in targett:
- targetl.append(target + [0 for _ in xrange(pad_length - len(target))])
- inputs.append(inpl)
- targets.append(targetl)
- res_input = np.array(inputs, dtype=np.int32)
- res_target = np.array(targets, dtype=np.int32)
- assert list(res_input.shape) == [batch_size, height, pad_length]
- assert list(res_target.shape) == [batch_size, 1, pad_length]
- return res_input, res_target
-
-
-def print_out(s, newline=True):
- """Print a message out and log it to file."""
- if log_filename:
- try:
- with tf.gfile.GFile(log_filename, mode="a") as f:
- f.write(s + ("\n" if newline else ""))
- # pylint: disable=bare-except
- except:
- sys.stderr.write("Error appending to %s\n" % log_filename)
- sys.stdout.write(s + ("\n" if newline else ""))
- sys.stdout.flush()
-
-
-def decode(output):
- return [np.argmax(o, axis=1) for o in output]
-
-
-def accuracy(inpt_t, output, target_t, batch_size, nprint,
- beam_out=None, beam_scores=None):
- """Calculate output accuracy given target."""
- assert nprint < batch_size + 1
- inpt = []
- for h in xrange(inpt_t.shape[1]):
- inpt.extend([inpt_t[:, h, l] for l in xrange(inpt_t.shape[2])])
- target = [target_t[:, 0, l] for l in xrange(target_t.shape[2])]
- def tok(i):
- if rev_vocab and i < len(rev_vocab):
- return rev_vocab[i]
- return str(i - 1)
- def task_print(inp, output, target):
- stop_bound = 0
- print_len = 0
- while print_len < len(target) and target[print_len] > stop_bound:
- print_len += 1
- print_out(" i: " + " ".join([tok(i) for i in inp if i > 0]))
- print_out(" o: " +
- " ".join([tok(output[l]) for l in xrange(print_len)]))
- print_out(" t: " +
- " ".join([tok(target[l]) for l in xrange(print_len)]))
- decoded_target = target
- decoded_output = decode(output)
- # Use beam output if given and score is high enough.
- if beam_out is not None:
- for b in xrange(batch_size):
- if beam_scores[b] >= 10.0:
- for l in xrange(min(len(decoded_output), beam_out.shape[2])):
- decoded_output[l][b] = int(beam_out[b, 0, l])
- total = 0
- errors = 0
- seq = [0 for b in xrange(batch_size)]
- for l in xrange(len(decoded_output)):
- for b in xrange(batch_size):
- if decoded_target[l][b] > 0:
- total += 1
- if decoded_output[l][b] != decoded_target[l][b]:
- seq[b] = 1
- errors += 1
- e = 0 # Previous error index
- for _ in xrange(min(nprint, sum(seq))):
- while seq[e] == 0:
- e += 1
- task_print([inpt[l][e] for l in xrange(len(inpt))],
- [decoded_output[l][e] for l in xrange(len(decoded_target))],
- [decoded_target[l][e] for l in xrange(len(decoded_target))])
- e += 1
- for b in xrange(nprint - errors):
- task_print([inpt[l][b] for l in xrange(len(inpt))],
- [decoded_output[l][b] for l in xrange(len(decoded_target))],
- [decoded_target[l][b] for l in xrange(len(decoded_target))])
- return errors, total, sum(seq)
-
-
-def safe_exp(x):
- perp = 10000
- x = float(x)
- if x < 100: perp = math.exp(x)
- if perp > 10000: return 10000
- return perp
diff --git a/research/neural_gpu/neural_gpu.py b/research/neural_gpu/neural_gpu.py
deleted file mode 100644
index 55b2b3e99224b31c672014195e9ef23fa1e892f7..0000000000000000000000000000000000000000
--- a/research/neural_gpu/neural_gpu.py
+++ /dev/null
@@ -1,747 +0,0 @@
-# Copyright 2015 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""The Neural GPU Model."""
-
-import time
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-from tensorflow.python.framework import function
-import data_utils as data
-
-do_jit = False # Gives more speed but experimental for now.
-jit_scope = tf.contrib.compiler.jit.experimental_jit_scope
-
-
-def conv_linear(args, kw, kh, nin, nout, rate, do_bias, bias_start, prefix):
- """Convolutional linear map."""
- if not isinstance(args, (list, tuple)):
- args = [args]
- with tf.variable_scope(prefix):
- with tf.device("/cpu:0"):
- k = tf.get_variable("CvK", [kw, kh, nin, nout])
- if len(args) == 1:
- arg = args[0]
- else:
- arg = tf.concat(axis=3, values=args)
- res = tf.nn.convolution(arg, k, dilation_rate=(rate, 1), padding="SAME")
- if not do_bias: return res
- with tf.device("/cpu:0"):
- bias_term = tf.get_variable(
- "CvB", [nout], initializer=tf.constant_initializer(bias_start))
- bias_term = tf.reshape(bias_term, [1, 1, 1, nout])
- return res + bias_term
-
-
-def sigmoid_cutoff(x, cutoff):
- """Sigmoid with cutoff, e.g., 1.2sigmoid(x) - 0.1."""
- y = tf.sigmoid(x)
- if cutoff < 1.01: return y
- d = (cutoff - 1.0) / 2.0
- return tf.minimum(1.0, tf.maximum(0.0, cutoff * y - d), name="cutoff_min")
-
-
-@function.Defun(tf.float32, noinline=True)
-def sigmoid_cutoff_12(x):
- """Sigmoid with cutoff 1.2, specialized for speed and memory use."""
- y = tf.sigmoid(x)
- return tf.minimum(1.0, tf.maximum(0.0, 1.2 * y - 0.1), name="cutoff_min_12")
-
-
-@function.Defun(tf.float32, noinline=True)
-def sigmoid_hard(x):
- """Hard sigmoid."""
- return tf.minimum(1.0, tf.maximum(0.0, 0.25 * x + 0.5))
-
-
-def place_at14(decided, selected, it):
- """Place selected at it-th coordinate of decided, dim=1 of 4."""
- slice1 = decided[:, :it, :, :]
- slice2 = decided[:, it + 1:, :, :]
- return tf.concat(axis=1, values=[slice1, selected, slice2])
-
-
-def place_at13(decided, selected, it):
- """Place selected at it-th coordinate of decided, dim=1 of 3."""
- slice1 = decided[:, :it, :]
- slice2 = decided[:, it + 1:, :]
- return tf.concat(axis=1, values=[slice1, selected, slice2])
-
-
-def tanh_cutoff(x, cutoff):
- """Tanh with cutoff, e.g., 1.1tanh(x) cut to [-1. 1]."""
- y = tf.tanh(x)
- if cutoff < 1.01: return y
- d = (cutoff - 1.0) / 2.0
- return tf.minimum(1.0, tf.maximum(-1.0, (1.0 + d) * y))
-
-
-@function.Defun(tf.float32, noinline=True)
-def tanh_hard(x):
- """Hard tanh."""
- return tf.minimum(1.0, tf.maximum(0.0, x))
-
-
-def layer_norm(x, nmaps, prefix, epsilon=1e-5):
- """Layer normalize the 4D tensor x, averaging over the last dimension."""
- with tf.variable_scope(prefix):
- scale = tf.get_variable("layer_norm_scale", [nmaps],
- initializer=tf.ones_initializer())
- bias = tf.get_variable("layer_norm_bias", [nmaps],
- initializer=tf.zeros_initializer())
- mean, variance = tf.nn.moments(x, [3], keep_dims=True)
- norm_x = (x - mean) / tf.sqrt(variance + epsilon)
- return norm_x * scale + bias
-
-
-def conv_gru(inpts, mem, kw, kh, nmaps, rate, cutoff, prefix, do_layer_norm,
- args_len=None):
- """Convolutional GRU."""
- def conv_lin(args, suffix, bias_start):
- total_args_len = args_len or len(args) * nmaps
- res = conv_linear(args, kw, kh, total_args_len, nmaps, rate, True,
- bias_start, prefix + "/" + suffix)
- if do_layer_norm:
- return layer_norm(res, nmaps, prefix + "/" + suffix)
- else:
- return res
- if cutoff == 1.2:
- reset = sigmoid_cutoff_12(conv_lin(inpts + [mem], "r", 1.0))
- gate = sigmoid_cutoff_12(conv_lin(inpts + [mem], "g", 1.0))
- elif cutoff > 10:
- reset = sigmoid_hard(conv_lin(inpts + [mem], "r", 1.0))
- gate = sigmoid_hard(conv_lin(inpts + [mem], "g", 1.0))
- else:
- reset = sigmoid_cutoff(conv_lin(inpts + [mem], "r", 1.0), cutoff)
- gate = sigmoid_cutoff(conv_lin(inpts + [mem], "g", 1.0), cutoff)
- if cutoff > 10:
- candidate = tanh_hard(conv_lin(inpts + [reset * mem], "c", 0.0))
- else:
- # candidate = tanh_cutoff(conv_lin(inpts + [reset * mem], "c", 0.0), cutoff)
- candidate = tf.tanh(conv_lin(inpts + [reset * mem], "c", 0.0))
- return gate * mem + (1 - gate) * candidate
-
-
-CHOOSE_K = 256
-
-
-def memory_call(q, l, nmaps, mem_size, vocab_size, num_gpus, update_mem):
- raise ValueError("Fill for experiments with additional memory structures.")
-
-
-def memory_run(step, nmaps, mem_size, batch_size, vocab_size,
- global_step, do_training, update_mem, decay_factor, num_gpus,
- target_emb_weights, output_w, gpu_targets_tn, it):
- """Run memory."""
- q = step[:, 0, it, :]
- mlabels = gpu_targets_tn[:, it, 0]
- res, mask, mem_loss = memory_call(
- q, mlabels, nmaps, mem_size, vocab_size, num_gpus, update_mem)
- res = tf.gather(target_emb_weights, res) * tf.expand_dims(mask[:, 0], 1)
-
- # Mix gold and original in the first steps, 20% later.
- gold = tf.nn.dropout(tf.gather(target_emb_weights, mlabels), 0.7)
- use_gold = 1.0 - tf.cast(global_step, tf.float32) / (1000. * decay_factor)
- use_gold = tf.maximum(use_gold, 0.2) * do_training
- mem = tf.cond(tf.less(tf.random_uniform([]), use_gold),
- lambda: use_gold * gold + (1.0 - use_gold) * res,
- lambda: res)
- mem = tf.reshape(mem, [-1, 1, 1, nmaps])
- return mem, mem_loss, update_mem
-
-
-@tf.RegisterGradient("CustomIdG")
-def _custom_id_grad(_, grads):
- return grads
-
-
-def quantize(t, quant_scale, max_value=1.0):
- """Quantize a tensor t with each element in [-max_value, max_value]."""
- t = tf.minimum(max_value, tf.maximum(t, -max_value))
- big = quant_scale * (t + max_value) + 0.5
- with tf.get_default_graph().gradient_override_map({"Floor": "CustomIdG"}):
- res = (tf.floor(big) / quant_scale) - max_value
- return res
-
-
-def quantize_weights_op(quant_scale, max_value):
- ops = [v.assign(quantize(v, quant_scale, float(max_value)))
- for v in tf.trainable_variables()]
- return tf.group(*ops)
-
-
-def autoenc_quantize(x, nbits, nmaps, do_training, layers=1):
- """Autoencoder into nbits vectors of bits, using noise and sigmoids."""
- enc_x = tf.reshape(x, [-1, nmaps])
- for i in xrange(layers - 1):
- enc_x = tf.layers.dense(enc_x, nmaps, name="autoenc_%d" % i)
- enc_x = tf.layers.dense(enc_x, nbits, name="autoenc_%d" % (layers - 1))
- noise = tf.truncated_normal(tf.shape(enc_x), stddev=2.0)
- dec_x = sigmoid_cutoff_12(enc_x + noise * do_training)
- dec_x = tf.reshape(dec_x, [-1, nbits])
- for i in xrange(layers):
- dec_x = tf.layers.dense(dec_x, nmaps, name="autodec_%d" % i)
- return tf.reshape(dec_x, tf.shape(x))
-
-
-def make_dense(targets, noclass, low_param):
- """Move a batch of targets to a dense 1-hot representation."""
- low = low_param / float(noclass - 1)
- high = 1.0 - low * (noclass - 1)
- targets = tf.cast(targets, tf.int64)
- return tf.one_hot(targets, depth=noclass, on_value=high, off_value=low)
-
-
-def reorder_beam(beam_size, batch_size, beam_val, output, is_first,
- tensors_to_reorder):
- """Reorder to minimize beam costs."""
- # beam_val is [batch_size x beam_size]; let b = batch_size * beam_size
- # decided is len x b x a x b
- # output is b x out_size; step is b x len x a x b;
- outputs = tf.split(axis=0, num_or_size_splits=beam_size, value=tf.nn.log_softmax(output))
- all_beam_vals, all_beam_idx = [], []
- beam_range = 1 if is_first else beam_size
- for i in xrange(beam_range):
- top_out, top_out_idx = tf.nn.top_k(outputs[i], k=beam_size)
- cur_beam_val = beam_val[:, i]
- top_out = tf.Print(top_out, [top_out, top_out_idx, beam_val, i,
- cur_beam_val], "GREPO", summarize=8)
- all_beam_vals.append(top_out + tf.expand_dims(cur_beam_val, 1))
- all_beam_idx.append(top_out_idx)
- all_beam_idx = tf.reshape(tf.transpose(tf.concat(axis=1, values=all_beam_idx), [1, 0]),
- [-1])
- top_beam, top_beam_idx = tf.nn.top_k(tf.concat(axis=1, values=all_beam_vals), k=beam_size)
- top_beam_idx = tf.Print(top_beam_idx, [top_beam, top_beam_idx],
- "GREP", summarize=8)
- reordered = [[] for _ in xrange(len(tensors_to_reorder) + 1)]
- top_out_idx = []
- for i in xrange(beam_size):
- which_idx = top_beam_idx[:, i] * batch_size + tf.range(batch_size)
- top_out_idx.append(tf.gather(all_beam_idx, which_idx))
- which_beam = top_beam_idx[:, i] / beam_size # [batch]
- which_beam = which_beam * batch_size + tf.range(batch_size)
- reordered[0].append(tf.gather(output, which_beam))
- for i, t in enumerate(tensors_to_reorder):
- reordered[i + 1].append(tf.gather(t, which_beam))
- new_tensors = [tf.concat(axis=0, values=t) for t in reordered]
- top_out_idx = tf.concat(axis=0, values=top_out_idx)
- return (top_beam, new_tensors[0], top_out_idx, new_tensors[1:])
-
-
-class NeuralGPU(object):
- """Neural GPU Model."""
-
- def __init__(self, nmaps, vec_size, niclass, noclass, dropout,
- max_grad_norm, cutoff, nconvs, kw, kh, height, mem_size,
- learning_rate, min_length, num_gpus, num_replicas,
- grad_noise_scale, sampling_rate, act_noise=0.0, do_rnn=False,
- atrous=False, beam_size=1, backward=True, do_layer_norm=False,
- autoenc_decay=1.0):
- # Feeds for parameters and ops to update them.
- self.nmaps = nmaps
- if backward:
- self.global_step = tf.Variable(0, trainable=False, name="global_step")
- self.cur_length = tf.Variable(min_length, trainable=False)
- self.cur_length_incr_op = self.cur_length.assign_add(1)
- self.lr = tf.Variable(learning_rate, trainable=False)
- self.lr_decay_op = self.lr.assign(self.lr * 0.995)
- self.do_training = tf.placeholder(tf.float32, name="do_training")
- self.update_mem = tf.placeholder(tf.int32, name="update_mem")
- self.noise_param = tf.placeholder(tf.float32, name="noise_param")
-
- # Feeds for inputs, targets, outputs, losses, etc.
- self.input = tf.placeholder(tf.int32, name="inp")
- self.target = tf.placeholder(tf.int32, name="tgt")
- self.prev_step = tf.placeholder(tf.float32, name="prev_step")
- gpu_input = tf.split(axis=0, num_or_size_splits=num_gpus, value=self.input)
- gpu_target = tf.split(axis=0, num_or_size_splits=num_gpus, value=self.target)
- gpu_prev_step = tf.split(axis=0, num_or_size_splits=num_gpus, value=self.prev_step)
- batch_size = tf.shape(gpu_input[0])[0]
-
- if backward:
- adam_lr = 0.005 * self.lr
- adam = tf.train.AdamOptimizer(adam_lr, epsilon=1e-3)
-
- def adam_update(grads):
- return adam.apply_gradients(zip(grads, tf.trainable_variables()),
- global_step=self.global_step,
- name="adam_update")
-
- # When switching from Adam to SGD we perform reverse-decay.
- if backward:
- global_step_float = tf.cast(self.global_step, tf.float32)
- sampling_decay_exponent = global_step_float / 100000.0
- sampling_decay = tf.maximum(0.05, tf.pow(0.5, sampling_decay_exponent))
- self.sampling = sampling_rate * 0.05 / sampling_decay
- else:
- self.sampling = tf.constant(0.0)
-
- # Cache variables on cpu if needed.
- if num_replicas > 1 or num_gpus > 1:
- with tf.device("/cpu:0"):
- caching_const = tf.constant(0)
- tf.get_variable_scope().set_caching_device(caching_const.op.device)
- # partitioner = tf.variable_axis_size_partitioner(1024*256*4)
- # tf.get_variable_scope().set_partitioner(partitioner)
-
- def gpu_avg(l):
- if l[0] is None:
- for elem in l:
- assert elem is None
- return 0.0
- if len(l) < 2:
- return l[0]
- return sum(l) / float(num_gpus)
-
- self.length_tensor = tf.placeholder(tf.int32, name="length")
-
- with tf.device("/cpu:0"):
- emb_weights = tf.get_variable(
- "embedding", [niclass, vec_size],
- initializer=tf.random_uniform_initializer(-1.7, 1.7))
- if beam_size > 0:
- target_emb_weights = tf.get_variable(
- "target_embedding", [noclass, nmaps],
- initializer=tf.random_uniform_initializer(-1.7, 1.7))
- e0 = tf.scatter_update(emb_weights,
- tf.constant(0, dtype=tf.int32, shape=[1]),
- tf.zeros([1, vec_size]))
- output_w = tf.get_variable("output_w", [nmaps, noclass], tf.float32)
-
- def conv_rate(layer):
- if atrous:
- return 2**layer
- return 1
-
- # pylint: disable=cell-var-from-loop
- def enc_step(step):
- """Encoder step."""
- if autoenc_decay < 1.0:
- quant_step = autoenc_quantize(step, 16, nmaps, self.do_training)
- if backward:
- exp_glob = tf.train.exponential_decay(1.0, self.global_step - 10000,
- 1000, autoenc_decay)
- dec_factor = 1.0 - exp_glob # * self.do_training
- dec_factor = tf.cond(tf.less(self.global_step, 10500),
- lambda: tf.constant(0.05), lambda: dec_factor)
- else:
- dec_factor = 1.0
- cur = tf.cond(tf.less(tf.random_uniform([]), dec_factor),
- lambda: quant_step, lambda: step)
- else:
- cur = step
- if dropout > 0.0001:
- cur = tf.nn.dropout(cur, keep_prob)
- if act_noise > 0.00001:
- cur += tf.truncated_normal(tf.shape(cur)) * act_noise_scale
- # Do nconvs-many CGRU steps.
- if do_jit and tf.get_variable_scope().reuse:
- with jit_scope():
- for layer in xrange(nconvs):
- cur = conv_gru([], cur, kw, kh, nmaps, conv_rate(layer),
- cutoff, "ecgru_%d" % layer, do_layer_norm)
- else:
- for layer in xrange(nconvs):
- cur = conv_gru([], cur, kw, kh, nmaps, conv_rate(layer),
- cutoff, "ecgru_%d" % layer, do_layer_norm)
- return cur
-
- zero_tgt = tf.zeros([batch_size, nmaps, 1])
- zero_tgt.set_shape([None, nmaps, 1])
-
- def dec_substep(step, decided):
- """Decoder sub-step."""
- cur = step
- if dropout > 0.0001:
- cur = tf.nn.dropout(cur, keep_prob)
- if act_noise > 0.00001:
- cur += tf.truncated_normal(tf.shape(cur)) * act_noise_scale
- # Do nconvs-many CGRU steps.
- if do_jit and tf.get_variable_scope().reuse:
- with jit_scope():
- for layer in xrange(nconvs):
- cur = conv_gru([decided], cur, kw, kh, nmaps, conv_rate(layer),
- cutoff, "dcgru_%d" % layer, do_layer_norm)
- else:
- for layer in xrange(nconvs):
- cur = conv_gru([decided], cur, kw, kh, nmaps, conv_rate(layer),
- cutoff, "dcgru_%d" % layer, do_layer_norm)
- return cur
- # pylint: enable=cell-var-from-loop
-
- def dec_step(step, it, it_int, decided, output_ta, tgts,
- mloss, nupd_in, out_idx, beam_cost):
- """Decoder step."""
- nupd, mem_loss = 0, 0.0
- if mem_size > 0:
- it_incr = tf.minimum(it+1, length - 1)
- mem, mem_loss, nupd = memory_run(
- step, nmaps, mem_size, batch_size, noclass, self.global_step,
- self.do_training, self.update_mem, 10, num_gpus,
- target_emb_weights, output_w, gpu_targets_tn, it_incr)
- step = dec_substep(step, decided)
- output_l = tf.expand_dims(tf.expand_dims(step[:, it, 0, :], 1), 1)
- # Calculate argmax output.
- output = tf.reshape(output_l, [-1, nmaps])
- # pylint: disable=cell-var-from-loop
- output = tf.matmul(output, output_w)
- if beam_size > 1:
- beam_cost, output, out, reordered = reorder_beam(
- beam_size, batch_size, beam_cost, output, it_int == 0,
- [output_l, out_idx, step, decided])
- [output_l, out_idx, step, decided] = reordered
- else:
- # Scheduled sampling.
- out = tf.multinomial(tf.stop_gradient(output), 1)
- out = tf.to_int32(tf.squeeze(out, [1]))
- out_write = output_ta.write(it, output_l[:batch_size, :, :, :])
- output = tf.gather(target_emb_weights, out)
- output = tf.reshape(output, [-1, 1, nmaps])
- output = tf.concat(axis=1, values=[output] * height)
- tgt = tgts[it, :, :, :]
- selected = tf.cond(tf.less(tf.random_uniform([]), self.sampling),
- lambda: output, lambda: tgt)
- # pylint: enable=cell-var-from-loop
- dec_write = place_at14(decided, tf.expand_dims(selected, 1), it)
- out_idx = place_at13(
- out_idx, tf.reshape(out, [beam_size * batch_size, 1, 1]), it)
- if mem_size > 0:
- mem = tf.concat(axis=2, values=[mem] * height)
- dec_write = place_at14(dec_write, mem, it_incr)
- return (step, dec_write, out_write, mloss + mem_loss, nupd_in + nupd,
- out_idx, beam_cost)
-
- # Main model construction.
- gpu_outputs = []
- gpu_losses = []
- gpu_grad_norms = []
- grads_list = []
- gpu_out_idx = []
- self.after_enc_step = []
- for gpu in xrange(num_gpus): # Multi-GPU towers, average gradients later.
- length = self.length_tensor
- length_float = tf.cast(length, tf.float32)
- if gpu > 0:
- tf.get_variable_scope().reuse_variables()
- gpu_outputs.append([])
- gpu_losses.append([])
- gpu_grad_norms.append([])
- with tf.name_scope("gpu%d" % gpu), tf.device("/gpu:%d" % gpu):
- # Main graph creation loop.
- data.print_out("Creating model.")
- start_time = time.time()
-
- # Embed inputs and calculate mask.
- with tf.device("/cpu:0"):
- tgt_shape = tf.shape(tf.squeeze(gpu_target[gpu], [1]))
- weights = tf.where(tf.squeeze(gpu_target[gpu], [1]) > 0,
- tf.ones(tgt_shape), tf.zeros(tgt_shape))
-
- # Embed inputs and targets.
- with tf.control_dependencies([e0]):
- start = tf.gather(emb_weights, gpu_input[gpu]) # b x h x l x nmaps
- gpu_targets_tn = gpu_target[gpu] # b x 1 x len
- if beam_size > 0:
- embedded_targets_tn = tf.gather(target_emb_weights,
- gpu_targets_tn)
- embedded_targets_tn = tf.transpose(
- embedded_targets_tn, [2, 0, 1, 3]) # len x b x 1 x nmaps
- embedded_targets_tn = tf.concat(axis=2, values=[embedded_targets_tn] * height)
-
- # First image comes from start by applying convolution and adding 0s.
- start = tf.transpose(start, [0, 2, 1, 3]) # Now b x len x h x vec_s
- first = conv_linear(start, 1, 1, vec_size, nmaps, 1, True, 0.0, "input")
- first = layer_norm(first, nmaps, "input")
-
- # Computation steps.
- keep_prob = dropout * 3.0 / tf.sqrt(length_float)
- keep_prob = 1.0 - self.do_training * keep_prob
- act_noise_scale = act_noise * self.do_training
-
- # Start with a convolutional gate merging previous step.
- step = conv_gru([gpu_prev_step[gpu]], first,
- kw, kh, nmaps, 1, cutoff, "first", do_layer_norm)
-
- # This is just for running a baseline RNN seq2seq model.
- if do_rnn:
- self.after_enc_step.append(step) # Not meaningful here, but needed.
- def lstm_cell():
- return tf.contrib.rnn.BasicLSTMCell(height * nmaps)
- cell = tf.contrib.rnn.MultiRNNCell(
- [lstm_cell() for _ in range(nconvs)])
- with tf.variable_scope("encoder"):
- encoder_outputs, encoder_state = tf.nn.dynamic_rnn(
- cell, tf.reshape(step, [batch_size, length, height * nmaps]),
- dtype=tf.float32, time_major=False)
-
- # Attention.
- attn = tf.layers.dense(
- encoder_outputs, height * nmaps, name="attn1")
-
- # pylint: disable=cell-var-from-loop
- @function.Defun(noinline=True)
- def attention_query(query, attn_v):
- vecs = tf.tanh(attn + tf.expand_dims(query, 1))
- mask = tf.reduce_sum(vecs * tf.reshape(attn_v, [1, 1, -1]), 2)
- mask = tf.nn.softmax(mask)
- return tf.reduce_sum(encoder_outputs * tf.expand_dims(mask, 2), 1)
-
- with tf.variable_scope("decoder"):
- def decoder_loop_fn(state__prev_cell_out__unused, cell_inp__cur_tgt):
- """Decoder loop function."""
- state, prev_cell_out, _ = state__prev_cell_out__unused
- cell_inp, cur_tgt = cell_inp__cur_tgt
- attn_q = tf.layers.dense(prev_cell_out, height * nmaps,
- name="attn_query")
- attn_res = attention_query(attn_q, tf.get_variable(
- "attn_v", [height * nmaps],
- initializer=tf.random_uniform_initializer(-0.1, 0.1)))
- concatenated = tf.reshape(tf.concat(axis=1, values=[cell_inp, attn_res]),
- [batch_size, 2 * height * nmaps])
- cell_inp = tf.layers.dense(
- concatenated, height * nmaps, name="attn_merge")
- output, new_state = cell(cell_inp, state)
-
- mem_loss = 0.0
- if mem_size > 0:
- res, mask, mem_loss = memory_call(
- output, cur_tgt, height * nmaps, mem_size, noclass,
- num_gpus, self.update_mem)
- res = tf.gather(target_emb_weights, res)
- res *= tf.expand_dims(mask[:, 0], 1)
- output = tf.layers.dense(
- tf.concat(axis=1, values=[output, res]), height * nmaps, name="rnnmem")
-
- return new_state, output, mem_loss
- # pylint: enable=cell-var-from-loop
- gpu_targets = tf.squeeze(gpu_target[gpu], [1]) # b x len
- gpu_tgt_trans = tf.transpose(gpu_targets, [1, 0])
- dec_zero = tf.zeros([batch_size, 1], dtype=tf.int32)
- dec_inp = tf.concat(axis=1, values=[dec_zero, gpu_targets])
- dec_inp = dec_inp[:, :length]
- embedded_dec_inp = tf.gather(target_emb_weights, dec_inp)
- embedded_dec_inp_proj = tf.layers.dense(
- embedded_dec_inp, height * nmaps, name="dec_proj")
- embedded_dec_inp_proj = tf.transpose(embedded_dec_inp_proj,
- [1, 0, 2])
- init_vals = (encoder_state,
- tf.zeros([batch_size, height * nmaps]), 0.0)
- _, dec_outputs, mem_losses = tf.scan(
- decoder_loop_fn, (embedded_dec_inp_proj, gpu_tgt_trans),
- initializer=init_vals)
- mem_loss = tf.reduce_mean(mem_losses)
- outputs = tf.layers.dense(dec_outputs, nmaps, name="out_proj")
- # Final convolution to get logits, list outputs.
- outputs = tf.matmul(tf.reshape(outputs, [-1, nmaps]), output_w)
- outputs = tf.reshape(outputs, [length, batch_size, noclass])
- gpu_out_idx.append(tf.argmax(outputs, 2))
- else: # Here we go with the Neural GPU.
- # Encoder.
- enc_length = length
- step = enc_step(step) # First step hard-coded.
- # pylint: disable=cell-var-from-loop
- i = tf.constant(1)
- c = lambda i, _s: tf.less(i, enc_length)
- def enc_step_lambda(i, step):
- with tf.variable_scope(tf.get_variable_scope(), reuse=True):
- new_step = enc_step(step)
- return (i + 1, new_step)
- _, step = tf.while_loop(
- c, enc_step_lambda, [i, step],
- parallel_iterations=1, swap_memory=True)
- # pylint: enable=cell-var-from-loop
-
- self.after_enc_step.append(step)
-
- # Decoder.
- if beam_size > 0:
- output_ta = tf.TensorArray(
- dtype=tf.float32, size=length, dynamic_size=False,
- infer_shape=False, name="outputs")
- out_idx = tf.zeros([beam_size * batch_size, length, 1],
- dtype=tf.int32)
- decided_t = tf.zeros([beam_size * batch_size, length,
- height, vec_size])
-
- # Prepare for beam search.
- tgts = tf.concat(axis=1, values=[embedded_targets_tn] * beam_size)
- beam_cost = tf.zeros([batch_size, beam_size])
- step = tf.concat(axis=0, values=[step] * beam_size)
- # First step hard-coded.
- step, decided_t, output_ta, mem_loss, nupd, oi, bc = dec_step(
- step, 0, 0, decided_t, output_ta, tgts, 0.0, 0, out_idx,
- beam_cost)
- tf.get_variable_scope().reuse_variables()
- # pylint: disable=cell-var-from-loop
- def step_lambda(i, step, dec_t, out_ta, ml, nu, oi, bc):
- with tf.variable_scope(tf.get_variable_scope(), reuse=True):
- s, d, t, nml, nu, oi, bc = dec_step(
- step, i, 1, dec_t, out_ta, tgts, ml, nu, oi, bc)
- return (i + 1, s, d, t, nml, nu, oi, bc)
- i = tf.constant(1)
- c = lambda i, _s, _d, _o, _ml, _nu, _oi, _bc: tf.less(i, length)
- _, step, _, output_ta, mem_loss, nupd, out_idx, _ = tf.while_loop(
- c, step_lambda,
- [i, step, decided_t, output_ta, mem_loss, nupd, oi, bc],
- parallel_iterations=1, swap_memory=True)
- # pylint: enable=cell-var-from-loop
- gpu_out_idx.append(tf.squeeze(out_idx, [2]))
- outputs = output_ta.stack()
- outputs = tf.squeeze(outputs, [2, 3]) # Now l x b x nmaps
- else:
- # If beam_size is 0 or less, we don't have a decoder.
- mem_loss = 0.0
- outputs = tf.transpose(step[:, :, 1, :], [1, 0, 2])
- gpu_out_idx.append(tf.argmax(outputs, 2))
-
- # Final convolution to get logits, list outputs.
- outputs = tf.matmul(tf.reshape(outputs, [-1, nmaps]), output_w)
- outputs = tf.reshape(outputs, [length, batch_size, noclass])
- gpu_outputs[gpu] = tf.nn.softmax(outputs)
-
- # Calculate cross-entropy loss and normalize it.
- targets_soft = make_dense(tf.squeeze(gpu_target[gpu], [1]),
- noclass, 0.1)
- targets_soft = tf.reshape(targets_soft, [-1, noclass])
- targets_hard = make_dense(tf.squeeze(gpu_target[gpu], [1]),
- noclass, 0.0)
- targets_hard = tf.reshape(targets_hard, [-1, noclass])
- output = tf.transpose(outputs, [1, 0, 2])
- xent_soft = tf.reshape(tf.nn.softmax_cross_entropy_with_logits(
- logits=tf.reshape(output, [-1, noclass]), labels=targets_soft),
- [batch_size, length])
- xent_hard = tf.reshape(tf.nn.softmax_cross_entropy_with_logits(
- logits=tf.reshape(output, [-1, noclass]), labels=targets_hard),
- [batch_size, length])
- low, high = 0.1 / float(noclass - 1), 0.9
- const = high * tf.log(high) + float(noclass - 1) * low * tf.log(low)
- weight_sum = tf.reduce_sum(weights) + 1e-20
- true_perp = tf.reduce_sum(xent_hard * weights) / weight_sum
- soft_loss = tf.reduce_sum(xent_soft * weights) / weight_sum
- perp_loss = soft_loss + const
- # Final loss: cross-entropy + shared parameter relaxation part + extra.
- mem_loss = 0.5 * tf.reduce_mean(mem_loss) / length_float
- total_loss = perp_loss + mem_loss
- gpu_losses[gpu].append(true_perp)
-
- # Gradients.
- if backward:
- data.print_out("Creating backward pass for the model.")
- grads = tf.gradients(
- total_loss, tf.trainable_variables(),
- colocate_gradients_with_ops=True)
- for g_i, g in enumerate(grads):
- if isinstance(g, tf.IndexedSlices):
- grads[g_i] = tf.convert_to_tensor(g)
- grads, norm = tf.clip_by_global_norm(grads, max_grad_norm)
- gpu_grad_norms[gpu].append(norm)
- for g in grads:
- if grad_noise_scale > 0.001:
- g += tf.truncated_normal(tf.shape(g)) * self.noise_param
- grads_list.append(grads)
- else:
- gpu_grad_norms[gpu].append(0.0)
- data.print_out("Created model for gpu %d in %.2f s."
- % (gpu, time.time() - start_time))
-
- self.updates = []
- self.after_enc_step = tf.concat(axis=0, values=self.after_enc_step) # Concat GPUs.
- if backward:
- tf.get_variable_scope()._reuse = False
- tf.get_variable_scope().set_caching_device(None)
- grads = [gpu_avg([grads_list[g][i] for g in xrange(num_gpus)])
- for i in xrange(len(grads_list[0]))]
- update = adam_update(grads)
- self.updates.append(update)
- else:
- self.updates.append(tf.no_op())
-
- self.losses = [gpu_avg([gpu_losses[g][i] for g in xrange(num_gpus)])
- for i in xrange(len(gpu_losses[0]))]
- self.out_idx = tf.concat(axis=0, values=gpu_out_idx)
- self.grad_norms = [gpu_avg([gpu_grad_norms[g][i] for g in xrange(num_gpus)])
- for i in xrange(len(gpu_grad_norms[0]))]
- self.outputs = [tf.concat(axis=1, values=[gpu_outputs[g] for g in xrange(num_gpus)])]
- self.quantize_op = quantize_weights_op(512, 8)
- if backward:
- self.saver = tf.train.Saver(tf.global_variables(), max_to_keep=10)
-
- def step(self, sess, inp, target, do_backward_in, noise_param=None,
- beam_size=2, eos_id=2, eos_cost=0.0, update_mem=None, state=None):
- """Run a step of the network."""
- batch_size, height, length = inp.shape[0], inp.shape[1], inp.shape[2]
- do_backward = do_backward_in
- train_mode = True
- if do_backward_in is None:
- do_backward = False
- train_mode = False
- if update_mem is None:
- update_mem = do_backward
- feed_in = {}
- # print " feeding sequences of length %d" % length
- if state is None:
- state = np.zeros([batch_size, length, height, self.nmaps])
- feed_in[self.prev_step.name] = state
- feed_in[self.length_tensor.name] = length
- feed_in[self.noise_param.name] = noise_param if noise_param else 0.0
- feed_in[self.do_training.name] = 1.0 if do_backward else 0.0
- feed_in[self.update_mem.name] = 1 if update_mem else 0
- if do_backward_in is False:
- feed_in[self.sampling.name] = 0.0
- index = 0 # We're dynamic now.
- feed_out = []
- if do_backward:
- feed_out.append(self.updates[index])
- feed_out.append(self.grad_norms[index])
- if train_mode:
- feed_out.append(self.losses[index])
- feed_in[self.input.name] = inp
- feed_in[self.target.name] = target
- feed_out.append(self.outputs[index])
- if train_mode:
- # Make a full-sequence training step with one call to session.run.
- res = sess.run([self.after_enc_step] + feed_out, feed_in)
- after_enc_state, res = res[0], res[1:]
- else:
- # Make a full-sequence decoding step with one call to session.run.
- feed_in[self.sampling.name] = 1.1 # Sample every time.
- res = sess.run([self.after_enc_step, self.out_idx] + feed_out, feed_in)
- after_enc_state, out_idx = res[0], res[1]
- res = [res[2][l] for l in xrange(length)]
- outputs = [out_idx[:, i] for i in xrange(length)]
- cost = [0.0 for _ in xrange(beam_size * batch_size)]
- seen_eos = [0 for _ in xrange(beam_size * batch_size)]
- for idx, logit in enumerate(res):
- best = outputs[idx]
- for b in xrange(batch_size):
- if seen_eos[b] > 1:
- cost[b] -= eos_cost
- else:
- cost[b] += np.log(logit[b][best[b]])
- if best[b] in [eos_id]:
- seen_eos[b] += 1
- res = [[-c for c in cost]] + outputs
- # Collect and output results.
- offset = 0
- norm = None
- if do_backward:
- offset = 2
- norm = res[1]
- if train_mode:
- outputs = res[offset + 1]
- outputs = [outputs[l] for l in xrange(length)]
- return res[offset], outputs, norm, after_enc_state
diff --git a/research/neural_gpu/neural_gpu_trainer.py b/research/neural_gpu/neural_gpu_trainer.py
deleted file mode 100644
index 1f704b0da880dbde4b09bf2cc108edb034d7b1a0..0000000000000000000000000000000000000000
--- a/research/neural_gpu/neural_gpu_trainer.py
+++ /dev/null
@@ -1,1027 +0,0 @@
-# Copyright 2015 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Neural GPU."""
-
-from __future__ import print_function
-
-import math
-import os
-import random
-import sys
-import threading
-import time
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-import program_utils
-import data_utils as data
-import neural_gpu as ngpu
-import wmt_utils as wmt
-
-tf.app.flags.DEFINE_float("lr", 0.1, "Learning rate.")
-tf.app.flags.DEFINE_float("init_weight", 0.8, "Initial weights deviation.")
-tf.app.flags.DEFINE_float("max_grad_norm", 4.0, "Clip gradients to this norm.")
-tf.app.flags.DEFINE_float("cutoff", 1.2, "Cutoff at the gates.")
-tf.app.flags.DEFINE_float("curriculum_ppx", 9.9, "Move curriculum if ppl < X.")
-tf.app.flags.DEFINE_float("curriculum_seq", 0.3, "Move curriculum if seq < X.")
-tf.app.flags.DEFINE_float("dropout", 0.1, "Dropout that much.")
-tf.app.flags.DEFINE_float("grad_noise_scale", 0.0, "Gradient noise scale.")
-tf.app.flags.DEFINE_float("max_sampling_rate", 0.1, "Maximal sampling rate.")
-tf.app.flags.DEFINE_float("length_norm", 0.0, "Length normalization.")
-tf.app.flags.DEFINE_float("train_beam_freq", 0.0, "Beam-based training.")
-tf.app.flags.DEFINE_float("train_beam_anneal", 20000, "How many steps anneal.")
-tf.app.flags.DEFINE_integer("eval_beam_steps", 4, "How many beam steps eval.")
-tf.app.flags.DEFINE_integer("batch_size", 32, "Batch size.")
-tf.app.flags.DEFINE_integer("steps_per_checkpoint", 100, "Steps per epoch.")
-tf.app.flags.DEFINE_integer("nmaps", 64, "Number of floats in each cell.")
-tf.app.flags.DEFINE_integer("vec_size", 64, "Size of word vectors.")
-tf.app.flags.DEFINE_integer("train_data_size", 1000, "Training examples/len.")
-tf.app.flags.DEFINE_integer("max_length", 40, "Maximum length.")
-tf.app.flags.DEFINE_integer("random_seed", 125459, "Random seed.")
-tf.app.flags.DEFINE_integer("nconvs", 2, "How many convolutions / 1 step.")
-tf.app.flags.DEFINE_integer("kw", 3, "Kernel width.")
-tf.app.flags.DEFINE_integer("kh", 3, "Kernel height.")
-tf.app.flags.DEFINE_integer("height", 4, "Height.")
-tf.app.flags.DEFINE_integer("mem_size", -1, "Memory size (sqrt)")
-tf.app.flags.DEFINE_integer("soft_mem_size", 1024, "Softmax memory this size.")
-tf.app.flags.DEFINE_integer("num_gpus", 1, "Number of GPUs to use.")
-tf.app.flags.DEFINE_integer("num_replicas", 1, "Number of replicas in use.")
-tf.app.flags.DEFINE_integer("beam_size", 1, "Beam size during decoding. "
- "If 0, no decoder, the non-extended Neural GPU.")
-tf.app.flags.DEFINE_integer("max_target_vocab", 0,
- "Maximal size of target vocabulary.")
-tf.app.flags.DEFINE_integer("decode_offset", 0, "Offset for decoding.")
-tf.app.flags.DEFINE_integer("task", -1, "Task id when running on borg.")
-tf.app.flags.DEFINE_integer("nprint", 0, "How many test examples to print out.")
-tf.app.flags.DEFINE_integer("eval_bin_print", 3, "How many bins step in eval.")
-tf.app.flags.DEFINE_integer("mode", 0, "Mode: 0-train other-decode.")
-tf.app.flags.DEFINE_bool("atrous", False, "Whether to use atrous convs.")
-tf.app.flags.DEFINE_bool("layer_norm", False, "Do layer normalization.")
-tf.app.flags.DEFINE_bool("quantize", False, "Whether to quantize variables.")
-tf.app.flags.DEFINE_bool("do_train", True, "If false, only update memory.")
-tf.app.flags.DEFINE_bool("rnn_baseline", False, "If true build an RNN instead.")
-tf.app.flags.DEFINE_bool("simple_tokenizer", False,
- "If true, tokenize on spaces only, digits are 0.")
-tf.app.flags.DEFINE_bool("normalize_digits", True,
- "Whether to normalize digits with simple tokenizer.")
-tf.app.flags.DEFINE_integer("vocab_size", 16, "Joint vocabulary size.")
-tf.app.flags.DEFINE_string("data_dir", "/tmp", "Data directory")
-tf.app.flags.DEFINE_string("train_dir", "/tmp/", "Directory to store models.")
-tf.app.flags.DEFINE_string("test_file_prefix", "", "Files to test (.en,.fr).")
-tf.app.flags.DEFINE_integer("max_train_data_size", 0,
- "Limit on the size of training data (0: no limit).")
-tf.app.flags.DEFINE_string("word_vector_file_en", "",
- "Optional file with word vectors to start training.")
-tf.app.flags.DEFINE_string("word_vector_file_fr", "",
- "Optional file with word vectors to start training.")
-tf.app.flags.DEFINE_string("problem", "wmt", "What problem are we solving?.")
-
-tf.app.flags.DEFINE_integer("ps_tasks", 0, "Number of ps tasks used.")
-tf.app.flags.DEFINE_string("master", "", "Name of the TensorFlow master.")
-
-FLAGS = tf.app.flags.FLAGS
-EXTRA_EVAL = 10
-EVAL_LEN_INCR = 8
-MAXLEN_F = 2.0
-
-
-def zero_split(tok_list, append=None):
- """Split tok_list (list of ints) on 0s, append int to all parts if given."""
- res, cur, l = [], [], 0
- for tok in tok_list:
- if tok == 0:
- if append is not None:
- cur.append(append)
- res.append(cur)
- l = max(l, len(cur))
- cur = []
- else:
- cur.append(tok)
- if append is not None:
- cur.append(append)
- res.append(cur)
- l = max(l, len(cur))
- return res, l
-
-
-def read_data(source_path, target_path, buckets, max_size=None, print_out=True):
- """Read data from source and target files and put into buckets.
-
- Args:
- source_path: path to the files with token-ids for the source language.
- target_path: path to the file with token-ids for the target language;
- it must be aligned with the source file: n-th line contains the desired
- output for n-th line from the source_path.
- buckets: the buckets to use.
- max_size: maximum number of lines to read, all other will be ignored;
- if 0 or None, data files will be read completely (no limit).
- If set to 1, no data will be returned (empty lists of the right form).
- print_out: whether to print out status or not.
-
- Returns:
- data_set: a list of length len(_buckets); data_set[n] contains a list of
- (source, target) pairs read from the provided data files that fit
- into the n-th bucket, i.e., such that len(source) < _buckets[n][0] and
- len(target) < _buckets[n][1]; source and target are lists of token-ids.
- """
- data_set = [[] for _ in buckets]
- counter = 0
- if max_size != 1:
- with tf.gfile.GFile(source_path, mode="r") as source_file:
- with tf.gfile.GFile(target_path, mode="r") as target_file:
- source, target = source_file.readline(), target_file.readline()
- while source and target and (not max_size or counter < max_size):
- counter += 1
- if counter % 100000 == 0 and print_out:
- print(" reading data line %d" % counter)
- sys.stdout.flush()
- source_ids = [int(x) for x in source.split()]
- target_ids = [int(x) for x in target.split()]
- source_ids, source_len = zero_split(source_ids)
- target_ids, target_len = zero_split(target_ids, append=wmt.EOS_ID)
- for bucket_id, size in enumerate(buckets):
- if source_len <= size and target_len <= size:
- data_set[bucket_id].append([source_ids, target_ids])
- break
- source, target = source_file.readline(), target_file.readline()
- return data_set
-
-
-global_train_set = {"wmt": []}
-train_buckets_scale = {"wmt": []}
-
-
-def calculate_buckets_scale(data_set, buckets, problem):
- """Calculate buckets scales for the given data set."""
- train_bucket_sizes = [len(data_set[b]) for b in xrange(len(buckets))]
- train_total_size = max(1, float(sum(train_bucket_sizes)))
-
- # A bucket scale is a list of increasing numbers from 0 to 1 that we'll use
- # to select a bucket. Length of [scale[i], scale[i+1]] is proportional to
- # the size if i-th training bucket, as used later.
- if problem not in train_buckets_scale:
- train_buckets_scale[problem] = []
- train_buckets_scale[problem].append(
- [sum(train_bucket_sizes[:i + 1]) / train_total_size
- for i in xrange(len(train_bucket_sizes))])
- return train_total_size
-
-
-def read_data_into_global(source_path, target_path, buckets,
- max_size=None, print_out=True):
- """Read data into the global variables (can be in a separate thread)."""
- # pylint: disable=global-variable-not-assigned
- global global_train_set, train_buckets_scale
- # pylint: enable=global-variable-not-assigned
- data_set = read_data(source_path, target_path, buckets, max_size, print_out)
- global_train_set["wmt"].append(data_set)
- train_total_size = calculate_buckets_scale(data_set, buckets, "wmt")
- if print_out:
- print(" Finished global data reading (%d)." % train_total_size)
-
-
-def initialize(sess=None):
- """Initialize data and model."""
- global MAXLEN_F
- # Create training directory if it does not exist.
- if not tf.gfile.IsDirectory(FLAGS.train_dir):
- data.print_out("Creating training directory %s." % FLAGS.train_dir)
- tf.gfile.MkDir(FLAGS.train_dir)
- decode_suffix = "beam%dln%d" % (FLAGS.beam_size,
- int(100 * FLAGS.length_norm))
- if FLAGS.mode == 0:
- decode_suffix = ""
- if FLAGS.task >= 0:
- data.log_filename = os.path.join(FLAGS.train_dir,
- "log%d%s" % (FLAGS.task, decode_suffix))
- else:
- data.log_filename = os.path.join(FLAGS.train_dir, "neural_gpu/log")
-
- # Set random seed.
- if FLAGS.random_seed > 0:
- seed = FLAGS.random_seed + max(0, FLAGS.task)
- tf.set_random_seed(seed)
- random.seed(seed)
- np.random.seed(seed)
-
- # Check data sizes.
- assert data.bins
- max_length = min(FLAGS.max_length, data.bins[-1])
- while len(data.bins) > 1 and data.bins[-2] >= max_length + EXTRA_EVAL:
- data.bins = data.bins[:-1]
- if sess is None and FLAGS.task == 0 and FLAGS.num_replicas > 1:
- if max_length > 60:
- max_length = max_length * 1 / 2 # Save memory on chief.
- min_length = min(14, max_length - 3) if FLAGS.problem == "wmt" else 3
- for p in FLAGS.problem.split("-"):
- if p in ["progeval", "progsynth"]:
- min_length = max(26, min_length)
- assert max_length + 1 > min_length
- while len(data.bins) > 1 and data.bins[-2] >= max_length + EXTRA_EVAL:
- data.bins = data.bins[:-1]
-
- # Create checkpoint directory if it does not exist.
- if FLAGS.mode == 0 or FLAGS.task < 0:
- checkpoint_dir = os.path.join(FLAGS.train_dir, "neural_gpu%s"
- % ("" if FLAGS.task < 0 else str(FLAGS.task)))
- else:
- checkpoint_dir = FLAGS.train_dir
- if not tf.gfile.IsDirectory(checkpoint_dir):
- data.print_out("Creating checkpoint directory %s." % checkpoint_dir)
- tf.gfile.MkDir(checkpoint_dir)
-
- # Prepare data.
- if FLAGS.problem == "wmt":
- # Prepare WMT data.
- data.print_out("Preparing WMT data in %s" % FLAGS.data_dir)
- if FLAGS.simple_tokenizer:
- MAXLEN_F = 3.5
- (en_train, fr_train, en_dev, fr_dev,
- en_path, fr_path) = wmt.prepare_wmt_data(
- FLAGS.data_dir, FLAGS.vocab_size,
- tokenizer=wmt.space_tokenizer,
- normalize_digits=FLAGS.normalize_digits)
- else:
- (en_train, fr_train, en_dev, fr_dev,
- en_path, fr_path) = wmt.prepare_wmt_data(
- FLAGS.data_dir, FLAGS.vocab_size)
-
- # Read data into buckets and compute their sizes.
- fr_vocab, rev_fr_vocab = wmt.initialize_vocabulary(fr_path)
- data.vocab = fr_vocab
- data.rev_vocab = rev_fr_vocab
- data.print_out("Reading development and training data (limit: %d)."
- % FLAGS.max_train_data_size)
- dev_set = {}
- dev_set["wmt"] = read_data(en_dev, fr_dev, data.bins)
- def data_read(size, print_out):
- read_data_into_global(en_train, fr_train, data.bins, size, print_out)
- data_read(50000, False)
- read_thread_small = threading.Thread(
- name="reading-data-small", target=lambda: data_read(900000, False))
- read_thread_small.start()
- read_thread_full = threading.Thread(
- name="reading-data-full",
- target=lambda: data_read(FLAGS.max_train_data_size, True))
- read_thread_full.start()
- data.print_out("Data reading set up.")
- else:
- # Prepare algorithmic data.
- en_path, fr_path = None, None
- tasks = FLAGS.problem.split("-")
- data_size = FLAGS.train_data_size
- for t in tasks:
- data.print_out("Generating data for %s." % t)
- if t in ["progeval", "progsynth"]:
- data.init_data(t, data.bins[-1], 20 * data_size, FLAGS.vocab_size)
- if len(program_utils.prog_vocab) > FLAGS.vocab_size - 2:
- raise ValueError("Increase vocab_size to %d for prog-tasks."
- % (len(program_utils.prog_vocab) + 2))
- data.rev_vocab = program_utils.prog_vocab
- data.vocab = program_utils.prog_rev_vocab
- else:
- for l in xrange(max_length + EXTRA_EVAL - 1):
- data.init_data(t, l, data_size, FLAGS.vocab_size)
- data.init_data(t, data.bins[-2], data_size, FLAGS.vocab_size)
- data.init_data(t, data.bins[-1], data_size, FLAGS.vocab_size)
- if t not in global_train_set:
- global_train_set[t] = []
- global_train_set[t].append(data.train_set[t])
- calculate_buckets_scale(data.train_set[t], data.bins, t)
- dev_set = data.test_set
-
- # Grid-search parameters.
- lr = FLAGS.lr
- init_weight = FLAGS.init_weight
- max_grad_norm = FLAGS.max_grad_norm
- if sess is not None and FLAGS.task > -1:
- def job_id_factor(step):
- """If jobid / step mod 3 is 0, 1, 2: say 0, 1, -1."""
- return ((((FLAGS.task / step) % 3) + 1) % 3) - 1
- lr *= math.pow(2, job_id_factor(1))
- init_weight *= math.pow(1.5, job_id_factor(3))
- max_grad_norm *= math.pow(2, job_id_factor(9))
-
- # Print out parameters.
- curriculum = FLAGS.curriculum_seq
- msg1 = ("layers %d kw %d h %d kh %d batch %d noise %.2f"
- % (FLAGS.nconvs, FLAGS.kw, FLAGS.height, FLAGS.kh,
- FLAGS.batch_size, FLAGS.grad_noise_scale))
- msg2 = ("cut %.2f lr %.3f iw %.2f cr %.2f nm %d d%.4f gn %.2f %s"
- % (FLAGS.cutoff, lr, init_weight, curriculum, FLAGS.nmaps,
- FLAGS.dropout, max_grad_norm, msg1))
- data.print_out(msg2)
-
- # Create model and initialize it.
- tf.get_variable_scope().set_initializer(
- tf.orthogonal_initializer(gain=1.8 * init_weight))
- max_sampling_rate = FLAGS.max_sampling_rate if FLAGS.mode == 0 else 0.0
- o = FLAGS.vocab_size if FLAGS.max_target_vocab < 1 else FLAGS.max_target_vocab
- ngpu.CHOOSE_K = FLAGS.soft_mem_size
- do_beam_model = FLAGS.train_beam_freq > 0.0001 and FLAGS.beam_size > 1
- beam_size = FLAGS.beam_size if FLAGS.mode > 0 and not do_beam_model else 1
- beam_size = min(beam_size, FLAGS.beam_size)
- beam_model = None
- def make_ngpu(cur_beam_size, back):
- return ngpu.NeuralGPU(
- FLAGS.nmaps, FLAGS.vec_size, FLAGS.vocab_size, o,
- FLAGS.dropout, max_grad_norm, FLAGS.cutoff, FLAGS.nconvs,
- FLAGS.kw, FLAGS.kh, FLAGS.height, FLAGS.mem_size,
- lr / math.sqrt(FLAGS.num_replicas), min_length + 3, FLAGS.num_gpus,
- FLAGS.num_replicas, FLAGS.grad_noise_scale, max_sampling_rate,
- atrous=FLAGS.atrous, do_rnn=FLAGS.rnn_baseline,
- do_layer_norm=FLAGS.layer_norm, beam_size=cur_beam_size, backward=back)
- if sess is None:
- with tf.device(tf.train.replica_device_setter(FLAGS.ps_tasks)):
- model = make_ngpu(beam_size, True)
- if do_beam_model:
- tf.get_variable_scope().reuse_variables()
- beam_model = make_ngpu(FLAGS.beam_size, False)
- else:
- model = make_ngpu(beam_size, True)
- if do_beam_model:
- tf.get_variable_scope().reuse_variables()
- beam_model = make_ngpu(FLAGS.beam_size, False)
-
- sv = None
- if sess is None:
- # The supervisor configuration has a few overriden options.
- sv = tf.train.Supervisor(logdir=checkpoint_dir,
- is_chief=(FLAGS.task < 1),
- saver=model.saver,
- summary_op=None,
- save_summaries_secs=60,
- save_model_secs=15 * 60,
- global_step=model.global_step)
-
- config = tf.ConfigProto(allow_soft_placement=True)
- sess = sv.PrepareSession(FLAGS.master, config=config)
-
- data.print_out("Created model. Checkpoint dir %s" % checkpoint_dir)
-
- # Load model from parameters if a checkpoint exists.
- ckpt = tf.train.get_checkpoint_state(checkpoint_dir)
- if ckpt and tf.gfile.Exists(ckpt.model_checkpoint_path + ".index"):
- data.print_out("Reading model parameters from %s"
- % ckpt.model_checkpoint_path)
- model.saver.restore(sess, ckpt.model_checkpoint_path)
- elif sv is None:
- sess.run(tf.global_variables_initializer())
- data.print_out("Initialized variables (no supervisor mode).")
- elif FLAGS.task < 1 and FLAGS.mem_size > 0:
- # sess.run(model.mem_norm_op)
- data.print_out("Created new model and normalized mem (on chief).")
-
- # Return the model and needed variables.
- return (model, beam_model, min_length, max_length, checkpoint_dir,
- (global_train_set, dev_set, en_path, fr_path), sv, sess)
-
-
-def m_step(model, beam_model, sess, batch_size, inp, target, bucket, nsteps, p):
- """Evaluation multi-step for program synthesis."""
- state, scores, hist = None, [[-11.0 for _ in xrange(batch_size)]], []
- for _ in xrange(nsteps):
- # Get the best beam (no training, just forward model).
- new_target, new_first, new_inp, new_scores = get_best_beam(
- beam_model, sess, inp, target,
- batch_size, FLAGS.beam_size, bucket, hist, p, test_mode=True)
- hist.append(new_first)
- _, _, _, state = model.step(sess, inp, new_target, False, state=state)
- inp = new_inp
- scores.append([max(scores[-1][i], new_scores[i])
- for i in xrange(batch_size)])
- # The final step with the true target.
- loss, res, _, _ = model.step(sess, inp, target, False, state=state)
- return loss, res, new_target, scores[1:]
-
-
-def single_test(bin_id, model, sess, nprint, batch_size, dev, p, print_out=True,
- offset=None, beam_model=None):
- """Test model on test data of length l using the given session."""
- if not dev[p][bin_id]:
- data.print_out(" bin %d (%d)\t%s\tppl NA errors NA seq-errors NA"
- % (bin_id, data.bins[bin_id], p))
- return 1.0, 1.0, 0.0
- inpt, target = data.get_batch(
- bin_id, batch_size, dev[p], FLAGS.height, offset)
- if FLAGS.beam_size > 1 and beam_model:
- loss, res, new_tgt, scores = m_step(
- model, beam_model, sess, batch_size, inpt, target, bin_id,
- FLAGS.eval_beam_steps, p)
- score_avgs = [sum(s) / float(len(s)) for s in scores]
- score_maxs = [max(s) for s in scores]
- score_str = ["(%.2f, %.2f)" % (score_avgs[i], score_maxs[i])
- for i in xrange(FLAGS.eval_beam_steps)]
- data.print_out(" == scores (avg, max): %s" % "; ".join(score_str))
- errors, total, seq_err = data.accuracy(inpt, res, target, batch_size,
- nprint, new_tgt, scores[-1])
- else:
- loss, res, _, _ = model.step(sess, inpt, target, False)
- errors, total, seq_err = data.accuracy(inpt, res, target, batch_size,
- nprint)
- seq_err = float(seq_err) / batch_size
- if total > 0:
- errors = float(errors) / total
- if print_out:
- data.print_out(" bin %d (%d)\t%s\tppl %.2f errors %.2f seq-errors %.2f"
- % (bin_id, data.bins[bin_id], p, data.safe_exp(loss),
- 100 * errors, 100 * seq_err))
- return (errors, seq_err, loss)
-
-
-def assign_vectors(word_vector_file, embedding_key, vocab_path, sess):
- """Assign the embedding_key variable from the given word vectors file."""
- # For words in the word vector file, set their embedding at start.
- if not tf.gfile.Exists(word_vector_file):
- data.print_out("Word vector file does not exist: %s" % word_vector_file)
- sys.exit(1)
- vocab, _ = wmt.initialize_vocabulary(vocab_path)
- vectors_variable = [v for v in tf.trainable_variables()
- if embedding_key == v.name]
- if len(vectors_variable) != 1:
- data.print_out("Word vector variable not found or too many.")
- sys.exit(1)
- vectors_variable = vectors_variable[0]
- vectors = vectors_variable.eval()
- data.print_out("Pre-setting word vectors from %s" % word_vector_file)
- with tf.gfile.GFile(word_vector_file, mode="r") as f:
- # Lines have format: dog 0.045123 -0.61323 0.413667 ...
- for line in f:
- line_parts = line.split()
- # The first part is the word.
- word = line_parts[0]
- if word in vocab:
- # Remaining parts are components of the vector.
- word_vector = np.array(map(float, line_parts[1:]))
- if len(word_vector) != FLAGS.vec_size:
- data.print_out("Warn: Word '%s', Expecting vector size %d, "
- "found %d" % (word, FLAGS.vec_size,
- len(word_vector)))
- else:
- vectors[vocab[word]] = word_vector
- # Assign the modified vectors to the vectors_variable in the graph.
- sess.run([vectors_variable.initializer],
- {vectors_variable.initializer.inputs[1]: vectors})
-
-
-def print_vectors(embedding_key, vocab_path, word_vector_file):
- """Print vectors from the given variable."""
- _, rev_vocab = wmt.initialize_vocabulary(vocab_path)
- vectors_variable = [v for v in tf.trainable_variables()
- if embedding_key == v.name]
- if len(vectors_variable) != 1:
- data.print_out("Word vector variable not found or too many.")
- sys.exit(1)
- vectors_variable = vectors_variable[0]
- vectors = vectors_variable.eval()
- l, s = vectors.shape[0], vectors.shape[1]
- data.print_out("Printing %d word vectors from %s to %s."
- % (l, embedding_key, word_vector_file))
- with tf.gfile.GFile(word_vector_file, mode="w") as f:
- # Lines have format: dog 0.045123 -0.61323 0.413667 ...
- for i in xrange(l):
- f.write(rev_vocab[i])
- for j in xrange(s):
- f.write(" %.8f" % vectors[i][j])
- f.write("\n")
-
-
-def get_bucket_id(train_buckets_scale_c, max_cur_length, data_set):
- """Get a random bucket id."""
- # Choose a bucket according to data distribution. Pick a random number
- # in [0, 1] and use the corresponding interval in train_buckets_scale.
- random_number_01 = np.random.random_sample()
- bucket_id = min([i for i in xrange(len(train_buckets_scale_c))
- if train_buckets_scale_c[i] > random_number_01])
- while bucket_id > 0 and not data_set[bucket_id]:
- bucket_id -= 1
- for _ in xrange(10 if np.random.random_sample() < 0.9 else 1):
- if data.bins[bucket_id] > max_cur_length:
- random_number_01 = min(random_number_01, np.random.random_sample())
- bucket_id = min([i for i in xrange(len(train_buckets_scale_c))
- if train_buckets_scale_c[i] > random_number_01])
- while bucket_id > 0 and not data_set[bucket_id]:
- bucket_id -= 1
- return bucket_id
-
-
-def score_beams(beams, target, inp, history, p,
- print_out=False, test_mode=False):
- """Score beams."""
- if p == "progsynth":
- return score_beams_prog(beams, target, inp, history, print_out, test_mode)
- elif test_mode:
- return beams[0], 10.0 if str(beams[0][:len(target)]) == str(target) else 0.0
- else:
- history_s = [str(h) for h in history]
- best, best_score, tgt, eos_id = None, -1000.0, target, None
- if p == "wmt":
- eos_id = wmt.EOS_ID
- if eos_id and eos_id in target:
- tgt = target[:target.index(eos_id)]
- for beam in beams:
- if eos_id and eos_id in beam:
- beam = beam[:beam.index(eos_id)]
- l = min(len(tgt), len(beam))
- score = len([i for i in xrange(l) if tgt[i] == beam[i]]) / float(len(tgt))
- hist_score = 20.0 if str([b for b in beam if b > 0]) in history_s else 0.0
- if score < 1.0:
- score -= hist_score
- if score > best_score:
- best = beam
- best_score = score
- return best, best_score
-
-
-def score_beams_prog(beams, target, inp, history, print_out=False,
- test_mode=False):
- """Score beams for program synthesis."""
- tgt_prog = linearize(target, program_utils.prog_vocab, True, 1)
- hist_progs = [linearize(h, program_utils.prog_vocab, True, 1)
- for h in history]
- tgt_set = set(target)
- if print_out:
- print("target: ", tgt_prog)
- inps, tgt_outs = [], []
- for i in xrange(3):
- ilist = [inp[i + 1, l] for l in xrange(inp.shape[1])]
- clist = [program_utils.prog_vocab[x] for x in ilist if x > 0]
- olist = clist[clist.index("]") + 1:] # outputs
- clist = clist[1:clist.index("]")] # inputs
- inps.append([int(x) for x in clist])
- if olist[0] == "[": # olist may be [int] or just int
- tgt_outs.append(str([int(x) for x in olist[1:-1]]))
- else:
- if len(olist) == 1:
- tgt_outs.append(olist[0])
- else:
- print([program_utils.prog_vocab[x] for x in ilist if x > 0])
- print(olist)
- print(tgt_prog)
- print(program_utils.evaluate(tgt_prog, {"a": inps[-1]}))
- print("AAAAA")
- tgt_outs.append(olist[0])
- if not test_mode:
- for _ in xrange(7):
- ilen = np.random.randint(len(target) - 3) + 1
- inps.append([random.choice(range(-15, 15)) for _ in range(ilen)])
- tgt_outs.extend([program_utils.evaluate(tgt_prog, {"a": inp})
- for inp in inps[3:]])
- best, best_prog, best_score = None, "", -1000.0
- for beam in beams:
- b_prog = linearize(beam, program_utils.prog_vocab, True, 1)
- b_set = set(beam)
- jsim = len(tgt_set & b_set) / float(len(tgt_set | b_set))
- b_outs = [program_utils.evaluate(b_prog, {"a": inp}) for inp in inps]
- errs = len([x for x in b_outs if x == "ERROR"])
- imatches = len([i for i in xrange(3) if b_outs[i] == tgt_outs[i]])
- perfect = 10.0 if imatches == 3 else 0.0
- hist_score = 20.0 if b_prog in hist_progs else 0.0
- if test_mode:
- score = perfect - errs
- else:
- matches = len([i for i in xrange(10) if b_outs[i] == tgt_outs[i]])
- score = perfect + matches + jsim - errs
- if score < 10.0:
- score -= hist_score
- # print b_prog
- # print "jsim: ", jsim, " errs: ", errs, " mtchs: ", matches, " s: ", score
- if score > best_score:
- best = beam
- best_prog = b_prog
- best_score = score
- if print_out:
- print("best score: ", best_score, " best prog: ", best_prog)
- return best, best_score
-
-
-def get_best_beam(beam_model, sess, inp, target, batch_size, beam_size,
- bucket, history, p, test_mode=False):
- """Run beam_model, score beams, and return the best as target and in input."""
- _, output_logits, _, _ = beam_model.step(
- sess, inp, target, None, beam_size=FLAGS.beam_size)
- new_targets, new_firsts, scores, new_inp = [], [], [], np.copy(inp)
- for b in xrange(batch_size):
- outputs = []
- history_b = [[h[b, 0, l] for l in xrange(data.bins[bucket])]
- for h in history]
- for beam_idx in xrange(beam_size):
- outputs.append([int(o[beam_idx * batch_size + b])
- for o in output_logits])
- target_t = [target[b, 0, l] for l in xrange(data.bins[bucket])]
- best, best_score = score_beams(
- outputs, [t for t in target_t if t > 0], inp[b, :, :],
- [[t for t in h if t > 0] for h in history_b], p, test_mode=test_mode)
- scores.append(best_score)
- if 1 in best: # Only until _EOS.
- best = best[:best.index(1) + 1]
- best += [0 for _ in xrange(len(target_t) - len(best))]
- new_targets.append([best])
- first, _ = score_beams(
- outputs, [t for t in target_t if t > 0], inp[b, :, :],
- [[t for t in h if t > 0] for h in history_b], p, test_mode=True)
- if 1 in first: # Only until _EOS.
- first = first[:first.index(1) + 1]
- first += [0 for _ in xrange(len(target_t) - len(first))]
- new_inp[b, 0, :] = np.array(first, dtype=np.int32)
- new_firsts.append([first])
- # Change target if we found a great answer.
- new_target = np.array(new_targets, dtype=np.int32)
- for b in xrange(batch_size):
- if scores[b] >= 10.0:
- target[b, 0, :] = new_target[b, 0, :]
- new_first = np.array(new_firsts, dtype=np.int32)
- return new_target, new_first, new_inp, scores
-
-
-def train():
- """Train the model."""
- batch_size = FLAGS.batch_size * FLAGS.num_gpus
- (model, beam_model, min_length, max_length, checkpoint_dir,
- (train_set, dev_set, en_vocab_path, fr_vocab_path), sv, sess) = initialize()
- with sess.as_default():
- quant_op = model.quantize_op
- max_cur_length = min(min_length + 3, max_length)
- prev_acc_perp = [1000000 for _ in xrange(5)]
- prev_seq_err = 1.0
- is_chief = FLAGS.task < 1
- do_report = False
-
- # Main traning loop.
- while not sv.ShouldStop():
- global_step, max_cur_length, learning_rate = sess.run(
- [model.global_step, model.cur_length, model.lr])
- acc_loss, acc_l1, acc_total, acc_errors, acc_seq_err = 0.0, 0.0, 0, 0, 0
- acc_grad_norm, step_count, step_c1, step_time = 0.0, 0, 0, 0.0
-
- # For words in the word vector file, set their embedding at start.
- bound1 = FLAGS.steps_per_checkpoint - 1
- if FLAGS.word_vector_file_en and global_step < bound1 and is_chief:
- assign_vectors(FLAGS.word_vector_file_en, "embedding:0",
- en_vocab_path, sess)
- if FLAGS.max_target_vocab < 1:
- assign_vectors(FLAGS.word_vector_file_en, "target_embedding:0",
- en_vocab_path, sess)
-
- if FLAGS.word_vector_file_fr and global_step < bound1 and is_chief:
- assign_vectors(FLAGS.word_vector_file_fr, "embedding:0",
- fr_vocab_path, sess)
- if FLAGS.max_target_vocab < 1:
- assign_vectors(FLAGS.word_vector_file_fr, "target_embedding:0",
- fr_vocab_path, sess)
-
- for _ in xrange(FLAGS.steps_per_checkpoint):
- step_count += 1
- step_c1 += 1
- global_step = int(model.global_step.eval())
- train_beam_anneal = global_step / float(FLAGS.train_beam_anneal)
- train_beam_freq = FLAGS.train_beam_freq * min(1.0, train_beam_anneal)
- p = random.choice(FLAGS.problem.split("-"))
- train_set = global_train_set[p][-1]
- bucket_id = get_bucket_id(train_buckets_scale[p][-1], max_cur_length,
- train_set)
- # Prefer longer stuff 60% of time if not wmt.
- if np.random.randint(100) < 60 and FLAGS.problem != "wmt":
- bucket1 = get_bucket_id(train_buckets_scale[p][-1], max_cur_length,
- train_set)
- bucket_id = max(bucket1, bucket_id)
-
- # Run a step and time it.
- start_time = time.time()
- inp, target = data.get_batch(bucket_id, batch_size, train_set,
- FLAGS.height)
- noise_param = math.sqrt(math.pow(global_step + 1, -0.55) *
- prev_seq_err) * FLAGS.grad_noise_scale
- # In multi-step mode, we use best from beam for middle steps.
- state, new_target, scores, history = None, None, None, []
- while (FLAGS.beam_size > 1 and
- train_beam_freq > np.random.random_sample()):
- # Get the best beam (no training, just forward model).
- new_target, new_first, new_inp, scores = get_best_beam(
- beam_model, sess, inp, target,
- batch_size, FLAGS.beam_size, bucket_id, history, p)
- history.append(new_first)
- # Training step with the previous input and the best beam as target.
- _, _, _, state = model.step(sess, inp, new_target, FLAGS.do_train,
- noise_param, update_mem=True, state=state)
- # Change input to the new one for the next step.
- inp = new_inp
- # If all results are great, stop (todo: not to wait for all?).
- if FLAGS.nprint > 1:
- print(scores)
- if sum(scores) / float(len(scores)) >= 10.0:
- break
- # The final step with the true target.
- loss, res, gnorm, _ = model.step(
- sess, inp, target, FLAGS.do_train, noise_param,
- update_mem=True, state=state)
- step_time += time.time() - start_time
- acc_grad_norm += 0.0 if gnorm is None else float(gnorm)
-
- # Accumulate statistics.
- acc_loss += loss
- acc_l1 += loss
- errors, total, seq_err = data.accuracy(
- inp, res, target, batch_size, 0, new_target, scores)
- if FLAGS.nprint > 1:
- print("seq_err: ", seq_err)
- acc_total += total
- acc_errors += errors
- acc_seq_err += seq_err
-
- # Report summary every 10 steps.
- if step_count + 3 > FLAGS.steps_per_checkpoint:
- do_report = True # Don't polute plot too early.
- if is_chief and step_count % 10 == 1 and do_report:
- cur_loss = acc_l1 / float(step_c1)
- acc_l1, step_c1 = 0.0, 0
- cur_perp = data.safe_exp(cur_loss)
- summary = tf.Summary()
- summary.value.extend(
- [tf.Summary.Value(tag="log_perplexity", simple_value=cur_loss),
- tf.Summary.Value(tag="perplexity", simple_value=cur_perp)])
- sv.SummaryComputed(sess, summary, global_step)
-
- # Normalize and print out accumulated statistics.
- acc_loss /= step_count
- step_time /= FLAGS.steps_per_checkpoint
- acc_seq_err = float(acc_seq_err) / (step_count * batch_size)
- prev_seq_err = max(0.0, acc_seq_err - 0.02) # No noise at error < 2%.
- acc_errors = float(acc_errors) / acc_total if acc_total > 0 else 1.0
- t_size = float(sum([len(x) for x in train_set])) / float(1000000)
- msg = ("step %d step-time %.2f train-size %.3f lr %.6f grad-norm %.4f"
- % (global_step + 1, step_time, t_size, learning_rate,
- acc_grad_norm / FLAGS.steps_per_checkpoint))
- data.print_out("%s len %d ppl %.6f errors %.2f sequence-errors %.2f" %
- (msg, max_cur_length, data.safe_exp(acc_loss),
- 100*acc_errors, 100*acc_seq_err))
-
- # If errors are below the curriculum threshold, move curriculum forward.
- is_good = FLAGS.curriculum_ppx > data.safe_exp(acc_loss)
- is_good = is_good and FLAGS.curriculum_seq > acc_seq_err
- if is_good and is_chief:
- if FLAGS.quantize:
- # Quantize weights.
- data.print_out(" Quantizing parameters.")
- sess.run([quant_op])
- # Increase current length (until the next with training data).
- sess.run(model.cur_length_incr_op)
- # Forget last perplexities if we're not yet at the end.
- if max_cur_length < max_length:
- prev_acc_perp.append(1000000)
-
- # Lower learning rate if we're worse than the last 5 checkpoints.
- acc_perp = data.safe_exp(acc_loss)
- if acc_perp > max(prev_acc_perp[-5:]) and is_chief:
- sess.run(model.lr_decay_op)
- prev_acc_perp.append(acc_perp)
-
- # Save checkpoint.
- if is_chief:
- checkpoint_path = os.path.join(checkpoint_dir, "neural_gpu.ckpt")
- model.saver.save(sess, checkpoint_path,
- global_step=model.global_step)
-
- # Run evaluation.
- bin_bound = 4
- for p in FLAGS.problem.split("-"):
- total_loss, total_err, tl_counter = 0.0, 0.0, 0
- for bin_id in xrange(len(data.bins)):
- if bin_id < bin_bound or bin_id % FLAGS.eval_bin_print == 1:
- err, _, loss = single_test(bin_id, model, sess, FLAGS.nprint,
- batch_size * 4, dev_set, p,
- beam_model=beam_model)
- if loss > 0.0:
- total_loss += loss
- total_err += err
- tl_counter += 1
- test_loss = total_loss / max(1, tl_counter)
- test_err = total_err / max(1, tl_counter)
- test_perp = data.safe_exp(test_loss)
- summary = tf.Summary()
- summary.value.extend(
- [tf.Summary.Value(tag="test/%s/loss" % p, simple_value=test_loss),
- tf.Summary.Value(tag="test/%s/error" % p, simple_value=test_err),
- tf.Summary.Value(tag="test/%s/perplexity" % p,
- simple_value=test_perp)])
- sv.SummaryComputed(sess, summary, global_step)
-
-
-def linearize(output, rev_fr_vocab, simple_tokenizer=None, eos_id=wmt.EOS_ID):
- # If there is an EOS symbol in outputs, cut them at that point (WMT).
- if eos_id in output:
- output = output[:output.index(eos_id)]
- # Print out French sentence corresponding to outputs.
- if simple_tokenizer or FLAGS.simple_tokenizer:
- vlen = len(rev_fr_vocab)
- def vget(o):
- if o < vlen:
- return rev_fr_vocab[o]
- return "UNK"
- return " ".join([vget(o) for o in output])
- else:
- return wmt.basic_detokenizer([rev_fr_vocab[o] for o in output])
-
-
-def evaluate():
- """Evaluate an existing model."""
- batch_size = FLAGS.batch_size * FLAGS.num_gpus
- with tf.Session(config=tf.ConfigProto(allow_soft_placement=True)) as sess:
- (model, beam_model, _, _, _,
- (_, dev_set, en_vocab_path, fr_vocab_path), _, sess) = initialize(sess)
- for p in FLAGS.problem.split("-"):
- for bin_id in xrange(len(data.bins)):
- if (FLAGS.task >= 0 and bin_id > 4) or (FLAGS.nprint == 0 and
- bin_id > 8 and p == "wmt"):
- break
- single_test(bin_id, model, sess, FLAGS.nprint, batch_size, dev_set, p,
- beam_model=beam_model)
- path = FLAGS.test_file_prefix
- xid = "" if FLAGS.task < 0 else ("%.4d" % (FLAGS.task+FLAGS.decode_offset))
- en_path, fr_path = path + ".en" + xid, path + ".fr" + xid
- # Evaluate the test file if they exist.
- if path and tf.gfile.Exists(en_path) and tf.gfile.Exists(fr_path):
- data.print_out("Translating test set %s" % en_path)
- # Read lines.
- en_lines, fr_lines = [], []
- with tf.gfile.GFile(en_path, mode="r") as f:
- for line in f:
- en_lines.append(line.strip())
- with tf.gfile.GFile(fr_path, mode="r") as f:
- for line in f:
- fr_lines.append(line.strip())
- # Tokenize and convert to ids.
- en_vocab, _ = wmt.initialize_vocabulary(en_vocab_path)
- _, rev_fr_vocab = wmt.initialize_vocabulary(fr_vocab_path)
- if FLAGS.simple_tokenizer:
- en_ids = [wmt.sentence_to_token_ids(
- l, en_vocab, tokenizer=wmt.space_tokenizer,
- normalize_digits=FLAGS.normalize_digits)
- for l in en_lines]
- else:
- en_ids = [wmt.sentence_to_token_ids(l, en_vocab) for l in en_lines]
- # Translate.
- results = []
- for idx, token_ids in enumerate(en_ids):
- if idx % 5 == 0:
- data.print_out("Translating example %d of %d." % (idx, len(en_ids)))
- # Which bucket does it belong to?
- buckets = [b for b in xrange(len(data.bins))
- if data.bins[b] >= len(token_ids)]
- if buckets:
- result, result_cost = [], 100000000.0
- for bucket_id in buckets:
- if data.bins[bucket_id] > MAXLEN_F * len(token_ids) + EVAL_LEN_INCR:
- break
- # Get a 1-element batch to feed the sentence to the model.
- used_batch_size = 1 # batch_size
- inp, target = data.get_batch(
- bucket_id, used_batch_size, None, FLAGS.height,
- preset=([token_ids], [[]]))
- loss, output_logits, _, _ = model.step(
- sess, inp, target, None, beam_size=FLAGS.beam_size)
- outputs = [int(o[0]) for o in output_logits]
- loss = loss[0] - (data.bins[bucket_id] * FLAGS.length_norm)
- if FLAGS.simple_tokenizer:
- cur_out = outputs
- if wmt.EOS_ID in cur_out:
- cur_out = cur_out[:cur_out.index(wmt.EOS_ID)]
- res_tags = [rev_fr_vocab[o] for o in cur_out]
- bad_words, bad_brack = wmt.parse_constraints(token_ids, res_tags)
- loss += 1000.0 * bad_words + 100.0 * bad_brack
- # print (bucket_id, loss)
- if loss < result_cost:
- result = outputs
- result_cost = loss
- final = linearize(result, rev_fr_vocab)
- results.append("%s\t%s\n" % (final, fr_lines[idx]))
- # print result_cost
- sys.stderr.write(results[-1])
- sys.stderr.flush()
- else:
- sys.stderr.write("TOOO_LONG\t%s\n" % fr_lines[idx])
- sys.stderr.flush()
- if xid:
- decode_suffix = "beam%dln%dn" % (FLAGS.beam_size,
- int(100 * FLAGS.length_norm))
- with tf.gfile.GFile(path + ".res" + decode_suffix + xid, mode="w") as f:
- for line in results:
- f.write(line)
-
-
-def mul(l):
- res = 1.0
- for s in l:
- res *= s
- return res
-
-
-def interactive():
- """Interactively probe an existing model."""
- with tf.Session(config=tf.ConfigProto(allow_soft_placement=True)) as sess:
- # Initialize model.
- (model, _, _, _, _, (_, _, en_path, fr_path), _, _) = initialize(sess)
- # Load vocabularies.
- en_vocab, rev_en_vocab = wmt.initialize_vocabulary(en_path)
- _, rev_fr_vocab = wmt.initialize_vocabulary(fr_path)
- # Print out vectors and variables.
- if FLAGS.nprint > 0 and FLAGS.word_vector_file_en:
- print_vectors("embedding:0", en_path, FLAGS.word_vector_file_en)
- if FLAGS.nprint > 0 and FLAGS.word_vector_file_fr:
- print_vectors("target_embedding:0", fr_path, FLAGS.word_vector_file_fr)
- total = 0
- for v in tf.trainable_variables():
- shape = v.get_shape().as_list()
- total += mul(shape)
- print(v.name, shape, mul(shape))
- print(total)
- # Start interactive loop.
- sys.stdout.write("Input to Neural GPU Translation Model.\n")
- sys.stdout.write("> ")
- sys.stdout.flush()
- inpt = sys.stdin.readline(), ""
- while inpt:
- cures = []
- # Get token-ids for the input sentence.
- if FLAGS.simple_tokenizer:
- token_ids = wmt.sentence_to_token_ids(
- inpt, en_vocab, tokenizer=wmt.space_tokenizer,
- normalize_digits=FLAGS.normalize_digits)
- else:
- token_ids = wmt.sentence_to_token_ids(inpt, en_vocab)
- print([rev_en_vocab[t] for t in token_ids])
- # Which bucket does it belong to?
- buckets = [b for b in xrange(len(data.bins))
- if data.bins[b] >= max(len(token_ids), len(cures))]
- if cures:
- buckets = [buckets[0]]
- if buckets:
- result, result_cost = [], 10000000.0
- for bucket_id in buckets:
- if data.bins[bucket_id] > MAXLEN_F * len(token_ids) + EVAL_LEN_INCR:
- break
- glen = 1
- for gen_idx in xrange(glen):
- # Get a 1-element batch to feed the sentence to the model.
- inp, target = data.get_batch(
- bucket_id, 1, None, FLAGS.height, preset=([token_ids], [cures]))
- loss, output_logits, _, _ = model.step(
- sess, inp, target, None, beam_size=FLAGS.beam_size,
- update_mem=False)
- # If it is a greedy decoder, outputs are argmaxes of output_logits.
- if FLAGS.beam_size > 1:
- outputs = [int(o) for o in output_logits]
- else:
- loss = loss[0] - (data.bins[bucket_id] * FLAGS.length_norm)
- outputs = [int(np.argmax(logit, axis=1))
- for logit in output_logits]
- print([rev_fr_vocab[t] for t in outputs])
- print(loss, data.bins[bucket_id])
- print(linearize(outputs, rev_fr_vocab))
- cures.append(outputs[gen_idx])
- print(cures)
- print(linearize(cures, rev_fr_vocab))
- if FLAGS.simple_tokenizer:
- cur_out = outputs
- if wmt.EOS_ID in cur_out:
- cur_out = cur_out[:cur_out.index(wmt.EOS_ID)]
- res_tags = [rev_fr_vocab[o] for o in cur_out]
- bad_words, bad_brack = wmt.parse_constraints(token_ids, res_tags)
- loss += 1000.0 * bad_words + 100.0 * bad_brack
- if loss < result_cost:
- result = outputs
- result_cost = loss
- print("FINAL", result_cost)
- print([rev_fr_vocab[t] for t in result])
- print(linearize(result, rev_fr_vocab))
- else:
- print("TOOO_LONG")
- sys.stdout.write("> ")
- sys.stdout.flush()
- inpt = sys.stdin.readline(), ""
-
-
-def main(_):
- if FLAGS.mode == 0:
- train()
- elif FLAGS.mode == 1:
- evaluate()
- else:
- interactive()
-
-if __name__ == "__main__":
- tf.app.run()
diff --git a/research/neural_gpu/program_utils.py b/research/neural_gpu/program_utils.py
deleted file mode 100644
index 1f49d01292012487c4a01a5832fb044a378645ff..0000000000000000000000000000000000000000
--- a/research/neural_gpu/program_utils.py
+++ /dev/null
@@ -1,444 +0,0 @@
-# Copyright 2015 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Utilities for generating program synthesis and evaluation data."""
-
-import contextlib
-import sys
-import random
-import os
-
-try:
- import StringIO
-except ImportError:
- from io import StringIO
-
-class ListType(object):
- def __init__(self, arg):
- self.arg = arg
-
- def __str__(self):
- return "[" + str(self.arg) + "]"
-
- def __eq__(self, other):
- if not isinstance(other, ListType):
- return False
- return self.arg == other.arg
-
- def __hash__(self):
- return hash(self.arg)
-
-class VarType(object):
- def __init__(self, arg):
- self.arg = arg
-
- def __str__(self):
- return str(self.arg)
-
- def __eq__(self, other):
- if not isinstance(other, VarType):
- return False
- return self.arg == other.arg
-
- def __hash__(self):
- return hash(self.arg)
-
-class FunctionType(object):
- def __init__(self, args):
- self.args = args
-
- def __str__(self):
- return str(self.args[0]) + " -> " + str(self.args[1])
-
- def __eq__(self, other):
- if not isinstance(other, FunctionType):
- return False
- return self.args == other.args
-
- def __hash__(self):
- return hash(tuple(self.args))
-
-
-class Function(object):
- def __init__(self, name, arg_types, output_type, fn_arg_types = None):
- self.name = name
- self.arg_types = arg_types
- self.fn_arg_types = fn_arg_types or []
- self.output_type = output_type
-
-Null = 100
-## Functions
-f_head = Function("c_head", [ListType("Int")], "Int")
-def c_head(xs): return xs[0] if len(xs) > 0 else Null
-
-f_last = Function("c_last", [ListType("Int")], "Int")
-def c_last(xs): return xs[-1] if len(xs) > 0 else Null
-
-f_take = Function("c_take", ["Int", ListType("Int")], ListType("Int"))
-def c_take(n, xs): return xs[:n]
-
-f_drop = Function("c_drop", ["Int", ListType("Int")], ListType("Int"))
-def c_drop(n, xs): return xs[n:]
-
-f_access = Function("c_access", ["Int", ListType("Int")], "Int")
-def c_access(n, xs): return xs[n] if n >= 0 and len(xs) > n else Null
-
-f_max = Function("c_max", [ListType("Int")], "Int")
-def c_max(xs): return max(xs) if len(xs) > 0 else Null
-
-f_min = Function("c_min", [ListType("Int")], "Int")
-def c_min(xs): return min(xs) if len(xs) > 0 else Null
-
-f_reverse = Function("c_reverse", [ListType("Int")], ListType("Int"))
-def c_reverse(xs): return list(reversed(xs))
-
-f_sort = Function("sorted", [ListType("Int")], ListType("Int"))
-# def c_sort(xs): return sorted(xs)
-
-f_sum = Function("sum", [ListType("Int")], "Int")
-# def c_sum(xs): return sum(xs)
-
-
-## Lambdas
-# Int -> Int
-def plus_one(x): return x + 1
-def minus_one(x): return x - 1
-def times_two(x): return x * 2
-def neg(x): return x * (-1)
-def div_two(x): return int(x/2)
-def sq(x): return x**2
-def times_three(x): return x * 3
-def div_three(x): return int(x/3)
-def times_four(x): return x * 4
-def div_four(x): return int(x/4)
-
-# Int -> Bool
-def pos(x): return x > 0
-def neg(x): return x < 0
-def even(x): return x%2 == 0
-def odd(x): return x%2 == 1
-
-# Int -> Int -> Int
-def add(x, y): return x + y
-def sub(x, y): return x - y
-def mul(x, y): return x * y
-
-# HOFs
-f_map = Function("map", [ListType("Int")],
- ListType("Int"),
- [FunctionType(["Int", "Int"])])
-f_filter = Function("filter", [ListType("Int")],
- ListType("Int"),
- [FunctionType(["Int", "Bool"])])
-f_count = Function("c_count", [ListType("Int")],
- "Int",
- [FunctionType(["Int", "Bool"])])
-def c_count(f, xs): return len([x for x in xs if f(x)])
-
-f_zipwith = Function("c_zipwith", [ListType("Int"), ListType("Int")],
- ListType("Int"),
- [FunctionType(["Int", "Int", "Int"])]) #FIX
-def c_zipwith(f, xs, ys): return [f(x, y) for (x, y) in zip(xs, ys)]
-
-f_scan = Function("c_scan", [ListType("Int")],
- ListType("Int"),
- [FunctionType(["Int", "Int", "Int"])])
-def c_scan(f, xs):
- out = xs
- for i in range(1, len(xs)):
- out[i] = f(xs[i], xs[i -1])
- return out
-
-@contextlib.contextmanager
-def stdoutIO(stdout=None):
- old = sys.stdout
- if stdout is None:
- stdout = StringIO.StringIO()
- sys.stdout = stdout
- yield stdout
- sys.stdout = old
-
-
-def evaluate(program_str, input_names_to_vals, default="ERROR"):
- exec_str = []
- for name, val in input_names_to_vals.iteritems():
- exec_str += name + " = " + str(val) + "; "
- exec_str += program_str
- if type(exec_str) is list:
- exec_str = "".join(exec_str)
-
- with stdoutIO() as s:
- # pylint: disable=bare-except
- try:
- exec(exec_str + " print(out)")
- return s.getvalue()[:-1]
- except:
- return default
- # pylint: enable=bare-except
-
-
-class Statement(object):
- """Statement class."""
-
- def __init__(self, fn, output_var, arg_vars, fn_args=None):
- self.fn = fn
- self.output_var = output_var
- self.arg_vars = arg_vars
- self.fn_args = fn_args or []
-
- def __str__(self):
- return "%s = %s(%s%s%s)"%(self.output_var,
- self.fn.name,
- ", ".join(self.fn_args),
- ", " if self.fn_args else "",
- ", ".join(self.arg_vars))
-
- def substitute(self, env):
- self.output_var = env.get(self.output_var, self.output_var)
- self.arg_vars = [env.get(v, v) for v in self.arg_vars]
-
-
-class ProgramGrower(object):
- """Grow programs."""
-
- def __init__(self, functions, types_to_lambdas):
- self.functions = functions
- self.types_to_lambdas = types_to_lambdas
-
- def grow_body(self, new_var_name, dependencies, types_to_vars):
- """Grow the program body."""
- choices = []
- for f in self.functions:
- if all([a in types_to_vars.keys() for a in f.arg_types]):
- choices.append(f)
-
- f = random.choice(choices)
- args = []
- for t in f.arg_types:
- possible_vars = random.choice(types_to_vars[t])
- var = random.choice(possible_vars)
- args.append(var)
- dependencies.setdefault(new_var_name, []).extend(
- [var] + (dependencies[var]))
-
- fn_args = [random.choice(self.types_to_lambdas[t]) for t in f.fn_arg_types]
- types_to_vars.setdefault(f.output_type, []).append(new_var_name)
-
- return Statement(f, new_var_name, args, fn_args)
-
- def grow(self, program_len, input_types):
- """Grow the program."""
- var_names = list(reversed(map(chr, range(97, 123))))
- dependencies = dict()
- types_to_vars = dict()
- input_names = []
- for t in input_types:
- var = var_names.pop()
- dependencies[var] = []
- types_to_vars.setdefault(t, []).append(var)
- input_names.append(var)
-
- statements = []
- for _ in range(program_len - 1):
- var = var_names.pop()
- statements.append(self.grow_body(var, dependencies, types_to_vars))
- statements.append(self.grow_body("out", dependencies, types_to_vars))
-
- new_var_names = [c for c in map(chr, range(97, 123))
- if c not in input_names]
- new_var_names.reverse()
- keep_statements = []
- env = dict()
- for s in statements:
- if s.output_var in dependencies["out"]:
- keep_statements.append(s)
- env[s.output_var] = new_var_names.pop()
- if s.output_var == "out":
- keep_statements.append(s)
-
- for k in keep_statements:
- k.substitute(env)
-
- return Program(input_names, input_types, ";".join(
- [str(k) for k in keep_statements]))
-
-
-class Program(object):
- """The program class."""
-
- def __init__(self, input_names, input_types, body):
- self.input_names = input_names
- self.input_types = input_types
- self.body = body
-
- def evaluate(self, inputs):
- """Evaluate this program."""
- if len(inputs) != len(self.input_names):
- raise AssertionError("inputs and input_names have to"
- "have the same len. inp: %s , names: %s" %
- (str(inputs), str(self.input_names)))
- inp_str = ""
- for (name, inp) in zip(self.input_names, inputs):
- inp_str += name + " = " + str(inp) + "; "
-
- with stdoutIO() as s:
- # pylint: disable=exec-used
- exec(inp_str + self.body + "; print(out)")
- # pylint: enable=exec-used
- return s.getvalue()[:-1]
-
- def flat_str(self):
- out = ""
- for s in self.body.split(";"):
- out += s + ";"
- return out
-
- def __str__(self):
- out = ""
- for (n, t) in zip(self.input_names, self.input_types):
- out += n + " = " + str(t) + "\n"
- for s in self.body.split(";"):
- out += s + "\n"
- return out
-
-
-prog_vocab = []
-prog_rev_vocab = {}
-
-
-def tokenize(string, tokens=None):
- """Tokenize the program string."""
- if tokens is None:
- tokens = prog_vocab
- tokens = sorted(tokens, key=len, reverse=True)
- out = []
- string = string.strip()
- while string:
- found = False
- for t in tokens:
- if string.startswith(t):
- out.append(t)
- string = string[len(t):]
- found = True
- break
- if not found:
- raise ValueError("Couldn't tokenize this: " + string)
- string = string.strip()
- return out
-
-
-def clean_up(output, max_val=100):
- o = eval(str(output))
- if isinstance(o, bool):
- return o
- if isinstance(o, int):
- if o >= 0:
- return min(o, max_val)
- else:
- return max(o, -1 * max_val)
- if isinstance(o, list):
- return [clean_up(l) for l in o]
-
-
-def make_vocab():
- gen(2, 0)
-
-
-def gen(max_len, how_many):
- """Generate some programs."""
- functions = [f_head, f_last, f_take, f_drop, f_access, f_max, f_min,
- f_reverse, f_sort, f_sum, f_map, f_filter, f_count, f_zipwith,
- f_scan]
-
- types_to_lambdas = {
- FunctionType(["Int", "Int"]): ["plus_one", "minus_one", "times_two",
- "div_two", "sq", "times_three",
- "div_three", "times_four", "div_four"],
- FunctionType(["Int", "Bool"]): ["pos", "neg", "even", "odd"],
- FunctionType(["Int", "Int", "Int"]): ["add", "sub", "mul"]
- }
-
- tokens = []
- for f in functions:
- tokens.append(f.name)
- for v in types_to_lambdas.values():
- tokens.extend(v)
- tokens.extend(["=", ";", ",", "(", ")", "[", "]", "Int", "out"])
- tokens.extend(map(chr, range(97, 123)))
-
- io_tokens = map(str, range(-220, 220))
- if not prog_vocab:
- prog_vocab.extend(["_PAD", "_EOS"] + tokens + io_tokens)
- for i, t in enumerate(prog_vocab):
- prog_rev_vocab[t] = i
-
- io_tokens += [",", "[", "]", ")", "(", "None"]
- grower = ProgramGrower(functions=functions,
- types_to_lambdas=types_to_lambdas)
-
- def mk_inp(l):
- return [random.choice(range(-5, 5)) for _ in range(l)]
-
- tar = [ListType("Int")]
- inps = [[mk_inp(3)], [mk_inp(5)], [mk_inp(7)], [mk_inp(15)]]
-
- save_prefix = None
- outcomes_to_programs = dict()
- tried = set()
- counter = 0
- choices = [0] if max_len == 0 else range(max_len)
- while counter < 100 * how_many and len(outcomes_to_programs) < how_many:
- counter += 1
- length = random.choice(choices)
- t = grower.grow(length, tar)
- while t in tried:
- length = random.choice(choices)
- t = grower.grow(length, tar)
- # print(t.flat_str())
- tried.add(t)
- outcomes = [clean_up(t.evaluate(i)) for i in inps]
- outcome_str = str(zip(inps, outcomes))
- if outcome_str in outcomes_to_programs:
- outcomes_to_programs[outcome_str] = min(
- [t.flat_str(), outcomes_to_programs[outcome_str]],
- key=lambda x: len(tokenize(x, tokens)))
- else:
- outcomes_to_programs[outcome_str] = t.flat_str()
- if counter % 5000 == 0:
- print("== proggen: tried: " + str(counter))
- print("== proggen: kept: " + str(len(outcomes_to_programs)))
-
- if counter % 250000 == 0 and save_prefix is not None:
- print("saving...")
- save_counter = 0
- progfilename = os.path.join(save_prefix, "prog_" + str(counter) + ".txt")
- iofilename = os.path.join(save_prefix, "io_" + str(counter) + ".txt")
- prog_token_filename = os.path.join(save_prefix,
- "prog_tokens_" + str(counter) + ".txt")
- io_token_filename = os.path.join(save_prefix,
- "io_tokens_" + str(counter) + ".txt")
- with open(progfilename, "a+") as fp, \
- open(iofilename, "a+") as fi, \
- open(prog_token_filename, "a+") as ftp, \
- open(io_token_filename, "a+") as fti:
- for (o, p) in outcomes_to_programs.iteritems():
- save_counter += 1
- if save_counter % 500 == 0:
- print("saving %d of %d" % (save_counter, len(outcomes_to_programs)))
- fp.write(p+"\n")
- fi.write(o+"\n")
- ftp.write(str(tokenize(p, tokens))+"\n")
- fti.write(str(tokenize(o, io_tokens))+"\n")
-
- return list(outcomes_to_programs.values())
diff --git a/research/neural_gpu/wmt_utils.py b/research/neural_gpu/wmt_utils.py
deleted file mode 100644
index ef831918f9c9279eb1c6e560e5730739e5fe9521..0000000000000000000000000000000000000000
--- a/research/neural_gpu/wmt_utils.py
+++ /dev/null
@@ -1,437 +0,0 @@
-# Copyright 2015 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Utilities for downloading data from WMT, tokenizing, vocabularies."""
-
-from __future__ import print_function
-
-import gzip
-import os
-import re
-import tarfile
-
-from six.moves import urllib
-import tensorflow as tf
-
-# Special vocabulary symbols - we always put them at the start.
-_PAD = b"_PAD"
-_GO = b"_GO"
-_EOS = b"_EOS"
-_UNK = b"_CHAR_UNK"
-_SPACE = b"_SPACE"
-_START_VOCAB = [_PAD, _GO, _EOS, _UNK, _SPACE]
-
-PAD_ID = 0
-GO_ID = 1
-EOS_ID = 2
-UNK_ID = 3
-SPACE_ID = 4
-
-# Regular expressions used to tokenize.
-_CHAR_MARKER = "_CHAR_"
-_CHAR_MARKER_LEN = len(_CHAR_MARKER)
-_SPEC_CHARS = "" + chr(226) + chr(153) + chr(128)
-_PUNCTUATION = "][.,!?\"':;%$#@&*+}{|><=/^~)(_`,0123456789" + _SPEC_CHARS + "-"
-_WORD_SPLIT = re.compile("([" + _PUNCTUATION + "])")
-_OLD_WORD_SPLIT = re.compile(b"([.,!?\"':;)(])")
-_DIGIT_RE = re.compile(br"\d")
-
-# URLs for WMT data.
-_WMT_ENFR_TRAIN_URL = "http://www.statmt.org/wmt10/training-giga-fren.tar"
-_WMT_ENFR_DEV_URL = "http://www.statmt.org/wmt15/dev-v2.tgz"
-
-
-def maybe_download(directory, filename, url):
- """Download filename from url unless it's already in directory."""
- if not tf.gfile.Exists(directory):
- print("Creating directory %s" % directory)
- os.mkdir(directory)
- filepath = os.path.join(directory, filename)
- if not tf.gfile.Exists(filepath):
- print("Downloading %s to %s" % (url, filepath))
- filepath, _ = urllib.request.urlretrieve(url, filepath)
- statinfo = os.stat(filepath)
- print("Successfully downloaded", filename, statinfo.st_size, "bytes")
- return filepath
-
-
-def gunzip_file(gz_path, new_path):
- """Unzips from gz_path into new_path."""
- print("Unpacking %s to %s" % (gz_path, new_path))
- with gzip.open(gz_path, "rb") as gz_file:
- with open(new_path, "wb") as new_file:
- for line in gz_file:
- new_file.write(line)
-
-
-def get_wmt_enfr_train_set(directory):
- """Download the WMT en-fr training corpus to directory unless it's there."""
- train_path = os.path.join(directory, "giga-fren.release2.fixed")
- if not (tf.gfile.Exists(train_path +".fr") and
- tf.gfile.Exists(train_path +".en")):
- corpus_file = maybe_download(directory, "training-giga-fren.tar",
- _WMT_ENFR_TRAIN_URL)
- print("Extracting tar file %s" % corpus_file)
- with tarfile.open(corpus_file, "r") as corpus_tar:
- corpus_tar.extractall(directory)
- gunzip_file(train_path + ".fr.gz", train_path + ".fr")
- gunzip_file(train_path + ".en.gz", train_path + ".en")
- return train_path
-
-
-def get_wmt_enfr_dev_set(directory):
- """Download the WMT en-fr training corpus to directory unless it's there."""
- dev_name = "newstest2013"
- dev_path = os.path.join(directory, dev_name)
- if not (tf.gfile.Exists(dev_path + ".fr") and
- tf.gfile.Exists(dev_path + ".en")):
- dev_file = maybe_download(directory, "dev-v2.tgz", _WMT_ENFR_DEV_URL)
- print("Extracting tgz file %s" % dev_file)
- with tarfile.open(dev_file, "r:gz") as dev_tar:
- fr_dev_file = dev_tar.getmember("dev/" + dev_name + ".fr")
- en_dev_file = dev_tar.getmember("dev/" + dev_name + ".en")
- fr_dev_file.name = dev_name + ".fr" # Extract without "dev/" prefix.
- en_dev_file.name = dev_name + ".en"
- dev_tar.extract(fr_dev_file, directory)
- dev_tar.extract(en_dev_file, directory)
- return dev_path
-
-
-def is_char(token):
- if len(token) > _CHAR_MARKER_LEN:
- if token[:_CHAR_MARKER_LEN] == _CHAR_MARKER:
- return True
- return False
-
-
-def basic_detokenizer(tokens):
- """Reverse the process of the basic tokenizer below."""
- result = []
- previous_nospace = True
- for t in tokens:
- if is_char(t):
- result.append(t[_CHAR_MARKER_LEN:])
- previous_nospace = True
- elif t == _SPACE:
- result.append(" ")
- previous_nospace = True
- elif previous_nospace:
- result.append(t)
- previous_nospace = False
- else:
- result.extend([" ", t])
- previous_nospace = False
- return "".join(result)
-
-
-old_style = False
-
-
-def basic_tokenizer(sentence):
- """Very basic tokenizer: split the sentence into a list of tokens."""
- words = []
- if old_style:
- for space_separated_fragment in sentence.strip().split():
- words.extend(re.split(_OLD_WORD_SPLIT, space_separated_fragment))
- return [w for w in words if w]
- for space_separated_fragment in sentence.strip().split():
- tokens = [t for t in re.split(_WORD_SPLIT, space_separated_fragment) if t]
- first_is_char = False
- for i, t in enumerate(tokens):
- if len(t) == 1 and t in _PUNCTUATION:
- tokens[i] = _CHAR_MARKER + t
- if i == 0:
- first_is_char = True
- if words and words[-1] != _SPACE and (first_is_char or is_char(words[-1])):
- tokens = [_SPACE] + tokens
- spaced_tokens = []
- for i, tok in enumerate(tokens):
- spaced_tokens.append(tokens[i])
- if i < len(tokens) - 1:
- if tok != _SPACE and not (is_char(tok) or is_char(tokens[i+1])):
- spaced_tokens.append(_SPACE)
- words.extend(spaced_tokens)
- return words
-
-
-def space_tokenizer(sentence):
- return sentence.strip().split()
-
-
-def is_pos_tag(token):
- """Check if token is a part-of-speech tag."""
- return(token in ["CC", "CD", "DT", "EX", "FW", "IN", "JJ", "JJR",
- "JJS", "LS", "MD", "NN", "NNS", "NNP", "NNPS", "PDT",
- "POS", "PRP", "PRP$", "RB", "RBR", "RBS", "RP", "SYM", "TO",
- "UH", "VB", "VBD", "VBG", "VBN", "VBP", "VBZ", "WDT", "WP",
- "WP$", "WRB", ".", ",", ":", ")", "-LRB-", "(", "-RRB-",
- "HYPH", "$", "``", "''", "ADD", "AFX", "QTR", "BES", "-DFL-",
- "GW", "HVS", "NFP"])
-
-
-def parse_constraints(inpt, res):
- ntags = len(res)
- nwords = len(inpt)
- npostags = len([x for x in res if is_pos_tag(x)])
- nclose = len([x for x in res if x[0] == "/"])
- nopen = ntags - nclose - npostags
- return (abs(npostags - nwords), abs(nclose - nopen))
-
-
-def create_vocabulary(vocabulary_path, data_path, max_vocabulary_size,
- tokenizer=None, normalize_digits=False):
- """Create vocabulary file (if it does not exist yet) from data file.
-
- Data file is assumed to contain one sentence per line. Each sentence is
- tokenized and digits are normalized (if normalize_digits is set).
- Vocabulary contains the most-frequent tokens up to max_vocabulary_size.
- We write it to vocabulary_path in a one-token-per-line format, so that later
- token in the first line gets id=0, second line gets id=1, and so on.
-
- Args:
- vocabulary_path: path where the vocabulary will be created.
- data_path: data file that will be used to create vocabulary.
- max_vocabulary_size: limit on the size of the created vocabulary.
- tokenizer: a function to use to tokenize each data sentence;
- if None, basic_tokenizer will be used.
- normalize_digits: Boolean; if true, all digits are replaced by 0s.
- """
- if not tf.gfile.Exists(vocabulary_path):
- print("Creating vocabulary %s from data %s" % (vocabulary_path, data_path))
- vocab, chars = {}, {}
- for c in _PUNCTUATION:
- chars[c] = 1
-
- # Read French file.
- with tf.gfile.GFile(data_path + ".fr", mode="rb") as f:
- counter = 0
- for line_in in f:
- line = " ".join(line_in.split())
- counter += 1
- if counter % 100000 == 0:
- print(" processing fr line %d" % counter)
- for c in line:
- if c in chars:
- chars[c] += 1
- else:
- chars[c] = 1
- tokens = tokenizer(line) if tokenizer else basic_tokenizer(line)
- tokens = [t for t in tokens if not is_char(t) and t != _SPACE]
- for w in tokens:
- word = re.sub(_DIGIT_RE, b"0", w) if normalize_digits else w
- if word in vocab:
- vocab[word] += 1000000000 # We want target words first.
- else:
- vocab[word] = 1000000000
-
- # Read English file.
- with tf.gfile.GFile(data_path + ".en", mode="rb") as f:
- counter = 0
- for line_in in f:
- line = " ".join(line_in.split())
- counter += 1
- if counter % 100000 == 0:
- print(" processing en line %d" % counter)
- for c in line:
- if c in chars:
- chars[c] += 1
- else:
- chars[c] = 1
- tokens = tokenizer(line) if tokenizer else basic_tokenizer(line)
- tokens = [t for t in tokens if not is_char(t) and t != _SPACE]
- for w in tokens:
- word = re.sub(_DIGIT_RE, b"0", w) if normalize_digits else w
- if word in vocab:
- vocab[word] += 1
- else:
- vocab[word] = 1
-
- sorted_vocab = sorted(vocab, key=vocab.get, reverse=True)
- sorted_chars = sorted(chars, key=vocab.get, reverse=True)
- sorted_chars = [_CHAR_MARKER + c for c in sorted_chars]
- vocab_list = _START_VOCAB + sorted_chars + sorted_vocab
- if tokenizer:
- vocab_list = _START_VOCAB + sorted_vocab
- if len(vocab_list) > max_vocabulary_size:
- vocab_list = vocab_list[:max_vocabulary_size]
- with tf.gfile.GFile(vocabulary_path, mode="wb") as vocab_file:
- for w in vocab_list:
- vocab_file.write(w + b"\n")
-
-
-def initialize_vocabulary(vocabulary_path):
- """Initialize vocabulary from file.
-
- We assume the vocabulary is stored one-item-per-line, so a file:
- dog
- cat
- will result in a vocabulary {"dog": 0, "cat": 1}, and this function will
- also return the reversed-vocabulary ["dog", "cat"].
-
- Args:
- vocabulary_path: path to the file containing the vocabulary.
-
- Returns:
- a pair: the vocabulary (a dictionary mapping string to integers), and
- the reversed vocabulary (a list, which reverses the vocabulary mapping).
-
- Raises:
- ValueError: if the provided vocabulary_path does not exist.
- """
- if tf.gfile.Exists(vocabulary_path):
- rev_vocab = []
- with tf.gfile.GFile(vocabulary_path, mode="rb") as f:
- rev_vocab.extend(f.readlines())
- rev_vocab = [line.strip() for line in rev_vocab]
- vocab = dict([(x, y) for (y, x) in enumerate(rev_vocab)])
- return vocab, rev_vocab
- else:
- raise ValueError("Vocabulary file %s not found.", vocabulary_path)
-
-
-def sentence_to_token_ids_raw(sentence, vocabulary,
- tokenizer=None, normalize_digits=old_style):
- """Convert a string to list of integers representing token-ids.
-
- For example, a sentence "I have a dog" may become tokenized into
- ["I", "have", "a", "dog"] and with vocabulary {"I": 1, "have": 2,
- "a": 4, "dog": 7"} this function will return [1, 2, 4, 7].
-
- Args:
- sentence: the sentence in bytes format to convert to token-ids.
- vocabulary: a dictionary mapping tokens to integers.
- tokenizer: a function to use to tokenize each sentence;
- if None, basic_tokenizer will be used.
- normalize_digits: Boolean; if true, all digits are replaced by 0s.
-
- Returns:
- a list of integers, the token-ids for the sentence.
- """
- if tokenizer:
- words = tokenizer(sentence)
- else:
- words = basic_tokenizer(sentence)
- result = []
- for w in words:
- if normalize_digits:
- w = re.sub(_DIGIT_RE, b"0", w)
- if w in vocabulary:
- result.append(vocabulary[w])
- else:
- if tokenizer:
- result.append(UNK_ID)
- else:
- result.append(SPACE_ID)
- for c in w:
- result.append(vocabulary.get(_CHAR_MARKER + c, UNK_ID))
- result.append(SPACE_ID)
- while result and result[0] == SPACE_ID:
- result = result[1:]
- while result and result[-1] == SPACE_ID:
- result = result[:-1]
- return result
-
-
-def sentence_to_token_ids(sentence, vocabulary,
- tokenizer=None, normalize_digits=old_style):
- """Convert a string to list of integers representing token-ids, tab=0."""
- tab_parts = sentence.strip().split("\t")
- toks = [sentence_to_token_ids_raw(t, vocabulary, tokenizer, normalize_digits)
- for t in tab_parts]
- res = []
- for t in toks:
- res.extend(t)
- res.append(0)
- return res[:-1]
-
-
-def data_to_token_ids(data_path, target_path, vocabulary_path,
- tokenizer=None, normalize_digits=False):
- """Tokenize data file and turn into token-ids using given vocabulary file.
-
- This function loads data line-by-line from data_path, calls the above
- sentence_to_token_ids, and saves the result to target_path. See comment
- for sentence_to_token_ids on the details of token-ids format.
-
- Args:
- data_path: path to the data file in one-sentence-per-line format.
- target_path: path where the file with token-ids will be created.
- vocabulary_path: path to the vocabulary file.
- tokenizer: a function to use to tokenize each sentence;
- if None, basic_tokenizer will be used.
- normalize_digits: Boolean; if true, all digits are replaced by 0s.
- """
- if not tf.gfile.Exists(target_path):
- print("Tokenizing data in %s" % data_path)
- vocab, _ = initialize_vocabulary(vocabulary_path)
- with tf.gfile.GFile(data_path, mode="rb") as data_file:
- with tf.gfile.GFile(target_path, mode="w") as tokens_file:
- counter = 0
- for line in data_file:
- counter += 1
- if counter % 100000 == 0:
- print(" tokenizing line %d" % counter)
- token_ids = sentence_to_token_ids(line, vocab, tokenizer,
- normalize_digits)
- tokens_file.write(" ".join([str(tok) for tok in token_ids]) + "\n")
-
-
-def prepare_wmt_data(data_dir, vocabulary_size,
- tokenizer=None, normalize_digits=False):
- """Get WMT data into data_dir, create vocabularies and tokenize data.
-
- Args:
- data_dir: directory in which the data sets will be stored.
- vocabulary_size: size of the joint vocabulary to create and use.
- tokenizer: a function to use to tokenize each data sentence;
- if None, basic_tokenizer will be used.
- normalize_digits: Boolean; if true, all digits are replaced by 0s.
-
- Returns:
- A tuple of 6 elements:
- (1) path to the token-ids for English training data-set,
- (2) path to the token-ids for French training data-set,
- (3) path to the token-ids for English development data-set,
- (4) path to the token-ids for French development data-set,
- (5) path to the vocabulary file,
- (6) path to the vocabulary file (for compatibility with non-joint vocab).
- """
- # Get wmt data to the specified directory.
- train_path = get_wmt_enfr_train_set(data_dir)
- dev_path = get_wmt_enfr_dev_set(data_dir)
-
- # Create vocabularies of the appropriate sizes.
- vocab_path = os.path.join(data_dir, "vocab%d.txt" % vocabulary_size)
- create_vocabulary(vocab_path, train_path, vocabulary_size,
- tokenizer=tokenizer, normalize_digits=normalize_digits)
-
- # Create token ids for the training data.
- fr_train_ids_path = train_path + (".ids%d.fr" % vocabulary_size)
- en_train_ids_path = train_path + (".ids%d.en" % vocabulary_size)
- data_to_token_ids(train_path + ".fr", fr_train_ids_path, vocab_path,
- tokenizer=tokenizer, normalize_digits=normalize_digits)
- data_to_token_ids(train_path + ".en", en_train_ids_path, vocab_path,
- tokenizer=tokenizer, normalize_digits=normalize_digits)
-
- # Create token ids for the development data.
- fr_dev_ids_path = dev_path + (".ids%d.fr" % vocabulary_size)
- en_dev_ids_path = dev_path + (".ids%d.en" % vocabulary_size)
- data_to_token_ids(dev_path + ".fr", fr_dev_ids_path, vocab_path,
- tokenizer=tokenizer, normalize_digits=normalize_digits)
- data_to_token_ids(dev_path + ".en", en_dev_ids_path, vocab_path,
- tokenizer=tokenizer, normalize_digits=normalize_digits)
-
- return (en_train_ids_path, fr_train_ids_path,
- en_dev_ids_path, fr_dev_ids_path,
- vocab_path, vocab_path)
diff --git a/research/neural_programmer/README.md b/research/neural_programmer/README.md
deleted file mode 100644
index dcc27f6fb015ec625935a0ea37d814a2ba10d2e3..0000000000000000000000000000000000000000
--- a/research/neural_programmer/README.md
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-# Neural Programmer
-
-Implementation of the Neural Programmer model as described in this [paper](https://openreview.net/pdf?id=ry2YOrcge).
-
-Download and extract the data from the [WikiTableQuestions](https://ppasupat.github.io/WikiTableQuestions/) site. The dataset contains
-11321, 2831, and 4344 examples for training, development, and testing respectively. We use their tokenization, number and date pre-processing. Please note that the above paper used the [initial release](https://github.com/ppasupat/WikiTableQuestions/releases/tag/v0.2) for training, development and testing.
-
-Change the `data_dir FLAG` to the location of the data.
-
-### Training
-Run `python neural_programmer.py`
-
-The models are written to `FLAGS.output_dir`.
-
-### Testing
-Run `python neural_programmer.py --evaluator_job=True`
-
-The models are loaded from `FLAGS.output_dir`. The evaluation is done on development data.
-
-In case of errors because of encoding, add `"# -*- coding: utf-8 -*-"` as the first line in `wiki_data.py`
-
-Maintained by Arvind Neelakantan (arvind2505)
diff --git a/research/neural_programmer/data_utils.py b/research/neural_programmer/data_utils.py
deleted file mode 100644
index 4df80c66ad21d2e046fabf78446dd199ae117b44..0000000000000000000000000000000000000000
--- a/research/neural_programmer/data_utils.py
+++ /dev/null
@@ -1,666 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Functions for constructing vocabulary, converting the examples to integer format and building the required masks for batch computation Author: aneelakantan (Arvind Neelakantan)
-"""
-
-from __future__ import print_function
-
-import copy
-import numbers
-import numpy as np
-import wiki_data
-
-
-def return_index(a):
- for i in range(len(a)):
- if (a[i] == 1.0):
- return i
-
-
-def construct_vocab(data, utility, add_word=False):
- ans = []
- for example in data:
- sent = ""
- for word in example.question:
- if (not (isinstance(word, numbers.Number))):
- sent += word + " "
- example.original_nc = copy.deepcopy(example.number_columns)
- example.original_wc = copy.deepcopy(example.word_columns)
- example.original_nc_names = copy.deepcopy(example.number_column_names)
- example.original_wc_names = copy.deepcopy(example.word_column_names)
- if (add_word):
- continue
- number_found = 0
- if (not (example.is_bad_example)):
- for word in example.question:
- if (isinstance(word, numbers.Number)):
- number_found += 1
- else:
- if (not (utility.word_ids.has_key(word))):
- utility.words.append(word)
- utility.word_count[word] = 1
- utility.word_ids[word] = len(utility.word_ids)
- utility.reverse_word_ids[utility.word_ids[word]] = word
- else:
- utility.word_count[word] += 1
- for col_name in example.word_column_names:
- for word in col_name:
- if (isinstance(word, numbers.Number)):
- number_found += 1
- else:
- if (not (utility.word_ids.has_key(word))):
- utility.words.append(word)
- utility.word_count[word] = 1
- utility.word_ids[word] = len(utility.word_ids)
- utility.reverse_word_ids[utility.word_ids[word]] = word
- else:
- utility.word_count[word] += 1
- for col_name in example.number_column_names:
- for word in col_name:
- if (isinstance(word, numbers.Number)):
- number_found += 1
- else:
- if (not (utility.word_ids.has_key(word))):
- utility.words.append(word)
- utility.word_count[word] = 1
- utility.word_ids[word] = len(utility.word_ids)
- utility.reverse_word_ids[utility.word_ids[word]] = word
- else:
- utility.word_count[word] += 1
-
-
-def word_lookup(word, utility):
- if (utility.word_ids.has_key(word)):
- return word
- else:
- return utility.unk_token
-
-
-def convert_to_int_2d_and_pad(a, utility):
- ans = []
- #print a
- for b in a:
- temp = []
- if (len(b) > utility.FLAGS.max_entry_length):
- b = b[0:utility.FLAGS.max_entry_length]
- for remaining in range(len(b), utility.FLAGS.max_entry_length):
- b.append(utility.dummy_token)
- assert len(b) == utility.FLAGS.max_entry_length
- for word in b:
- temp.append(utility.word_ids[word_lookup(word, utility)])
- ans.append(temp)
- #print ans
- return ans
-
-
-def convert_to_bool_and_pad(a, utility):
- a = a.tolist()
- for i in range(len(a)):
- for j in range(len(a[i])):
- if (a[i][j] < 1):
- a[i][j] = False
- else:
- a[i][j] = True
- a[i] = a[i] + [False] * (utility.FLAGS.max_elements - len(a[i]))
- return a
-
-
-seen_tables = {}
-
-
-def partial_match(question, table, number):
- answer = []
- match = {}
- for i in range(len(table)):
- temp = []
- for j in range(len(table[i])):
- temp.append(0)
- answer.append(temp)
- for i in range(len(table)):
- for j in range(len(table[i])):
- for word in question:
- if (number):
- if (word == table[i][j]):
- answer[i][j] = 1.0
- match[i] = 1.0
- else:
- if (word in table[i][j]):
- answer[i][j] = 1.0
- match[i] = 1.0
- return answer, match
-
-
-def exact_match(question, table, number):
- #performs exact match operation
- answer = []
- match = {}
- matched_indices = []
- for i in range(len(table)):
- temp = []
- for j in range(len(table[i])):
- temp.append(0)
- answer.append(temp)
- for i in range(len(table)):
- for j in range(len(table[i])):
- if (number):
- for word in question:
- if (word == table[i][j]):
- match[i] = 1.0
- answer[i][j] = 1.0
- else:
- table_entry = table[i][j]
- for k in range(len(question)):
- if (k + len(table_entry) <= len(question)):
- if (table_entry == question[k:(k + len(table_entry))]):
- #if(len(table_entry) == 1):
- #print "match: ", table_entry, question
- match[i] = 1.0
- answer[i][j] = 1.0
- matched_indices.append((k, len(table_entry)))
- return answer, match, matched_indices
-
-
-def partial_column_match(question, table, number):
- answer = []
- for i in range(len(table)):
- answer.append(0)
- for i in range(len(table)):
- for word in question:
- if (word in table[i]):
- answer[i] = 1.0
- return answer
-
-
-def exact_column_match(question, table, number):
- #performs exact match on column names
- answer = []
- matched_indices = []
- for i in range(len(table)):
- answer.append(0)
- for i in range(len(table)):
- table_entry = table[i]
- for k in range(len(question)):
- if (k + len(table_entry) <= len(question)):
- if (table_entry == question[k:(k + len(table_entry))]):
- answer[i] = 1.0
- matched_indices.append((k, len(table_entry)))
- return answer, matched_indices
-
-
-def get_max_entry(a):
- e = {}
- for w in a:
- if (w != "UNK, "):
- if (e.has_key(w)):
- e[w] += 1
- else:
- e[w] = 1
- if (len(e) > 0):
- (key, val) = sorted(e.items(), key=lambda x: -1 * x[1])[0]
- if (val > 1):
- return key
- else:
- return -1.0
- else:
- return -1.0
-
-
-def list_join(a):
- ans = ""
- for w in a:
- ans += str(w) + ", "
- return ans
-
-
-def group_by_max(table, number):
- #computes the most frequently occurring entry in a column
- answer = []
- for i in range(len(table)):
- temp = []
- for j in range(len(table[i])):
- temp.append(0)
- answer.append(temp)
- for i in range(len(table)):
- if (number):
- curr = table[i]
- else:
- curr = [list_join(w) for w in table[i]]
- max_entry = get_max_entry(curr)
- #print i, max_entry
- for j in range(len(curr)):
- if (max_entry == curr[j]):
- answer[i][j] = 1.0
- else:
- answer[i][j] = 0.0
- return answer
-
-
-def pick_one(a):
- for i in range(len(a)):
- if (1.0 in a[i]):
- return True
- return False
-
-
-def check_processed_cols(col, utility):
- return True in [
- True for y in col
- if (y != utility.FLAGS.pad_int and y !=
- utility.FLAGS.bad_number_pre_process)
- ]
-
-
-def complete_wiki_processing(data, utility, train=True):
- #convert to integers and padding
- processed_data = []
- num_bad_examples = 0
- for example in data:
- number_found = 0
- if (example.is_bad_example):
- num_bad_examples += 1
- if (not (example.is_bad_example)):
- example.string_question = example.question[:]
- #entry match
- example.processed_number_columns = example.processed_number_columns[:]
- example.processed_word_columns = example.processed_word_columns[:]
- example.word_exact_match, word_match, matched_indices = exact_match(
- example.string_question, example.original_wc, number=False)
- example.number_exact_match, number_match, _ = exact_match(
- example.string_question, example.original_nc, number=True)
- if (not (pick_one(example.word_exact_match)) and not (
- pick_one(example.number_exact_match))):
- assert len(word_match) == 0
- assert len(number_match) == 0
- example.word_exact_match, word_match = partial_match(
- example.string_question, example.original_wc, number=False)
- #group by max
- example.word_group_by_max = group_by_max(example.original_wc, False)
- example.number_group_by_max = group_by_max(example.original_nc, True)
- #column name match
- example.word_column_exact_match, wcol_matched_indices = exact_column_match(
- example.string_question, example.original_wc_names, number=False)
- example.number_column_exact_match, ncol_matched_indices = exact_column_match(
- example.string_question, example.original_nc_names, number=False)
- if (not (1.0 in example.word_column_exact_match) and not (
- 1.0 in example.number_column_exact_match)):
- example.word_column_exact_match = partial_column_match(
- example.string_question, example.original_wc_names, number=False)
- example.number_column_exact_match = partial_column_match(
- example.string_question, example.original_nc_names, number=False)
- if (len(word_match) > 0 or len(number_match) > 0):
- example.question.append(utility.entry_match_token)
- if (1.0 in example.word_column_exact_match or
- 1.0 in example.number_column_exact_match):
- example.question.append(utility.column_match_token)
- example.string_question = example.question[:]
- example.number_lookup_matrix = np.transpose(
- example.number_lookup_matrix)[:]
- example.word_lookup_matrix = np.transpose(example.word_lookup_matrix)[:]
- example.columns = example.number_columns[:]
- example.word_columns = example.word_columns[:]
- example.len_total_cols = len(example.word_column_names) + len(
- example.number_column_names)
- example.column_names = example.number_column_names[:]
- example.word_column_names = example.word_column_names[:]
- example.string_column_names = example.number_column_names[:]
- example.string_word_column_names = example.word_column_names[:]
- example.sorted_number_index = []
- example.sorted_word_index = []
- example.column_mask = []
- example.word_column_mask = []
- example.processed_column_mask = []
- example.processed_word_column_mask = []
- example.word_column_entry_mask = []
- example.question_attention_mask = []
- example.question_number = example.question_number_1 = -1
- example.question_attention_mask = []
- example.ordinal_question = []
- example.ordinal_question_one = []
- new_question = []
- if (len(example.number_columns) > 0):
- example.len_col = len(example.number_columns[0])
- else:
- example.len_col = len(example.word_columns[0])
- for (start, length) in matched_indices:
- for j in range(length):
- example.question[start + j] = utility.unk_token
- #print example.question
- for word in example.question:
- if (isinstance(word, numbers.Number) or wiki_data.is_date(word)):
- if (not (isinstance(word, numbers.Number)) and
- wiki_data.is_date(word)):
- word = word.replace("X", "").replace("-", "")
- number_found += 1
- if (number_found == 1):
- example.question_number = word
- if (len(example.ordinal_question) > 0):
- example.ordinal_question[len(example.ordinal_question) - 1] = 1.0
- else:
- example.ordinal_question.append(1.0)
- elif (number_found == 2):
- example.question_number_1 = word
- if (len(example.ordinal_question_one) > 0):
- example.ordinal_question_one[len(example.ordinal_question_one) -
- 1] = 1.0
- else:
- example.ordinal_question_one.append(1.0)
- else:
- new_question.append(word)
- example.ordinal_question.append(0.0)
- example.ordinal_question_one.append(0.0)
- example.question = [
- utility.word_ids[word_lookup(w, utility)] for w in new_question
- ]
- example.question_attention_mask = [0.0] * len(example.question)
- #when the first question number occurs before a word
- example.ordinal_question = example.ordinal_question[0:len(
- example.question)]
- example.ordinal_question_one = example.ordinal_question_one[0:len(
- example.question)]
- #question-padding
- example.question = [utility.word_ids[utility.dummy_token]] * (
- utility.FLAGS.question_length - len(example.question)
- ) + example.question
- example.question_attention_mask = [-10000.0] * (
- utility.FLAGS.question_length - len(example.question_attention_mask)
- ) + example.question_attention_mask
- example.ordinal_question = [0.0] * (utility.FLAGS.question_length -
- len(example.ordinal_question)
- ) + example.ordinal_question
- example.ordinal_question_one = [0.0] * (utility.FLAGS.question_length -
- len(example.ordinal_question_one)
- ) + example.ordinal_question_one
- if (True):
- #number columns and related-padding
- num_cols = len(example.columns)
- start = 0
- for column in example.number_columns:
- if (check_processed_cols(example.processed_number_columns[start],
- utility)):
- example.processed_column_mask.append(0.0)
- sorted_index = sorted(
- range(len(example.processed_number_columns[start])),
- key=lambda k: example.processed_number_columns[start][k],
- reverse=True)
- sorted_index = sorted_index + [utility.FLAGS.pad_int] * (
- utility.FLAGS.max_elements - len(sorted_index))
- example.sorted_number_index.append(sorted_index)
- example.columns[start] = column + [utility.FLAGS.pad_int] * (
- utility.FLAGS.max_elements - len(column))
- example.processed_number_columns[start] += [utility.FLAGS.pad_int] * (
- utility.FLAGS.max_elements -
- len(example.processed_number_columns[start]))
- start += 1
- example.column_mask.append(0.0)
- for remaining in range(num_cols, utility.FLAGS.max_number_cols):
- example.sorted_number_index.append([utility.FLAGS.pad_int] *
- (utility.FLAGS.max_elements))
- example.columns.append([utility.FLAGS.pad_int] *
- (utility.FLAGS.max_elements))
- example.processed_number_columns.append([utility.FLAGS.pad_int] *
- (utility.FLAGS.max_elements))
- example.number_exact_match.append([0.0] *
- (utility.FLAGS.max_elements))
- example.number_group_by_max.append([0.0] *
- (utility.FLAGS.max_elements))
- example.column_mask.append(-100000000.0)
- example.processed_column_mask.append(-100000000.0)
- example.number_column_exact_match.append(0.0)
- example.column_names.append([utility.dummy_token])
- #word column and related-padding
- start = 0
- word_num_cols = len(example.word_columns)
- for column in example.word_columns:
- if (check_processed_cols(example.processed_word_columns[start],
- utility)):
- example.processed_word_column_mask.append(0.0)
- sorted_index = sorted(
- range(len(example.processed_word_columns[start])),
- key=lambda k: example.processed_word_columns[start][k],
- reverse=True)
- sorted_index = sorted_index + [utility.FLAGS.pad_int] * (
- utility.FLAGS.max_elements - len(sorted_index))
- example.sorted_word_index.append(sorted_index)
- column = convert_to_int_2d_and_pad(column, utility)
- example.word_columns[start] = column + [[
- utility.word_ids[utility.dummy_token]
- ] * utility.FLAGS.max_entry_length] * (utility.FLAGS.max_elements -
- len(column))
- example.processed_word_columns[start] += [utility.FLAGS.pad_int] * (
- utility.FLAGS.max_elements -
- len(example.processed_word_columns[start]))
- example.word_column_entry_mask.append([0] * len(column) + [
- utility.word_ids[utility.dummy_token]
- ] * (utility.FLAGS.max_elements - len(column)))
- start += 1
- example.word_column_mask.append(0.0)
- for remaining in range(word_num_cols, utility.FLAGS.max_word_cols):
- example.sorted_word_index.append([utility.FLAGS.pad_int] *
- (utility.FLAGS.max_elements))
- example.word_columns.append([[utility.word_ids[utility.dummy_token]] *
- utility.FLAGS.max_entry_length] *
- (utility.FLAGS.max_elements))
- example.word_column_entry_mask.append(
- [utility.word_ids[utility.dummy_token]] *
- (utility.FLAGS.max_elements))
- example.word_exact_match.append([0.0] * (utility.FLAGS.max_elements))
- example.word_group_by_max.append([0.0] * (utility.FLAGS.max_elements))
- example.processed_word_columns.append([utility.FLAGS.pad_int] *
- (utility.FLAGS.max_elements))
- example.word_column_mask.append(-100000000.0)
- example.processed_word_column_mask.append(-100000000.0)
- example.word_column_exact_match.append(0.0)
- example.word_column_names.append([utility.dummy_token] *
- utility.FLAGS.max_entry_length)
- seen_tables[example.table_key] = 1
- #convert column and word column names to integers
- example.column_ids = convert_to_int_2d_and_pad(example.column_names,
- utility)
- example.word_column_ids = convert_to_int_2d_and_pad(
- example.word_column_names, utility)
- for i_em in range(len(example.number_exact_match)):
- example.number_exact_match[i_em] = example.number_exact_match[
- i_em] + [0.0] * (utility.FLAGS.max_elements -
- len(example.number_exact_match[i_em]))
- example.number_group_by_max[i_em] = example.number_group_by_max[
- i_em] + [0.0] * (utility.FLAGS.max_elements -
- len(example.number_group_by_max[i_em]))
- for i_em in range(len(example.word_exact_match)):
- example.word_exact_match[i_em] = example.word_exact_match[
- i_em] + [0.0] * (utility.FLAGS.max_elements -
- len(example.word_exact_match[i_em]))
- example.word_group_by_max[i_em] = example.word_group_by_max[
- i_em] + [0.0] * (utility.FLAGS.max_elements -
- len(example.word_group_by_max[i_em]))
- example.exact_match = example.number_exact_match + example.word_exact_match
- example.group_by_max = example.number_group_by_max + example.word_group_by_max
- example.exact_column_match = example.number_column_exact_match + example.word_column_exact_match
- #answer and related mask, padding
- if (example.is_lookup):
- example.answer = example.calc_answer
- example.number_print_answer = example.number_lookup_matrix.tolist()
- example.word_print_answer = example.word_lookup_matrix.tolist()
- for i_answer in range(len(example.number_print_answer)):
- example.number_print_answer[i_answer] = example.number_print_answer[
- i_answer] + [0.0] * (utility.FLAGS.max_elements -
- len(example.number_print_answer[i_answer]))
- for i_answer in range(len(example.word_print_answer)):
- example.word_print_answer[i_answer] = example.word_print_answer[
- i_answer] + [0.0] * (utility.FLAGS.max_elements -
- len(example.word_print_answer[i_answer]))
- example.number_lookup_matrix = convert_to_bool_and_pad(
- example.number_lookup_matrix, utility)
- example.word_lookup_matrix = convert_to_bool_and_pad(
- example.word_lookup_matrix, utility)
- for remaining in range(num_cols, utility.FLAGS.max_number_cols):
- example.number_lookup_matrix.append([False] *
- utility.FLAGS.max_elements)
- example.number_print_answer.append([0.0] * utility.FLAGS.max_elements)
- for remaining in range(word_num_cols, utility.FLAGS.max_word_cols):
- example.word_lookup_matrix.append([False] *
- utility.FLAGS.max_elements)
- example.word_print_answer.append([0.0] * utility.FLAGS.max_elements)
- example.print_answer = example.number_print_answer + example.word_print_answer
- else:
- example.answer = example.calc_answer
- example.print_answer = [[0.0] * (utility.FLAGS.max_elements)] * (
- utility.FLAGS.max_number_cols + utility.FLAGS.max_word_cols)
- #question_number masks
- if (example.question_number == -1):
- example.question_number_mask = np.zeros([utility.FLAGS.max_elements])
- else:
- example.question_number_mask = np.ones([utility.FLAGS.max_elements])
- if (example.question_number_1 == -1):
- example.question_number_one_mask = -10000.0
- else:
- example.question_number_one_mask = np.float64(0.0)
- if (example.len_col > utility.FLAGS.max_elements):
- continue
- processed_data.append(example)
- return processed_data
-
-
-def add_special_words(utility):
- utility.words.append(utility.entry_match_token)
- utility.word_ids[utility.entry_match_token] = len(utility.word_ids)
- utility.reverse_word_ids[utility.word_ids[
- utility.entry_match_token]] = utility.entry_match_token
- utility.entry_match_token_id = utility.word_ids[utility.entry_match_token]
- print("entry match token: ", utility.word_ids[
- utility.entry_match_token], utility.entry_match_token_id)
- utility.words.append(utility.column_match_token)
- utility.word_ids[utility.column_match_token] = len(utility.word_ids)
- utility.reverse_word_ids[utility.word_ids[
- utility.column_match_token]] = utility.column_match_token
- utility.column_match_token_id = utility.word_ids[utility.column_match_token]
- print("entry match token: ", utility.word_ids[
- utility.column_match_token], utility.column_match_token_id)
- utility.words.append(utility.dummy_token)
- utility.word_ids[utility.dummy_token] = len(utility.word_ids)
- utility.reverse_word_ids[utility.word_ids[
- utility.dummy_token]] = utility.dummy_token
- utility.dummy_token_id = utility.word_ids[utility.dummy_token]
- utility.words.append(utility.unk_token)
- utility.word_ids[utility.unk_token] = len(utility.word_ids)
- utility.reverse_word_ids[utility.word_ids[
- utility.unk_token]] = utility.unk_token
-
-
-def perform_word_cutoff(utility):
- if (utility.FLAGS.word_cutoff > 0):
- for word in utility.word_ids.keys():
- if (utility.word_count.has_key(word) and utility.word_count[word] <
- utility.FLAGS.word_cutoff and word != utility.unk_token and
- word != utility.dummy_token and word != utility.entry_match_token and
- word != utility.column_match_token):
- utility.word_ids.pop(word)
- utility.words.remove(word)
-
-
-def word_dropout(question, utility):
- if (utility.FLAGS.word_dropout_prob > 0.0):
- new_question = []
- for i in range(len(question)):
- if (question[i] != utility.dummy_token_id and
- utility.random.random() > utility.FLAGS.word_dropout_prob):
- new_question.append(utility.word_ids[utility.unk_token])
- else:
- new_question.append(question[i])
- return new_question
- else:
- return question
-
-
-def generate_feed_dict(data, curr, batch_size, gr, train=False, utility=None):
- #prepare feed dict dictionary
- feed_dict = {}
- feed_examples = []
- for j in range(batch_size):
- feed_examples.append(data[curr + j])
- if (train):
- feed_dict[gr.batch_question] = [
- word_dropout(feed_examples[j].question, utility)
- for j in range(batch_size)
- ]
- else:
- feed_dict[gr.batch_question] = [
- feed_examples[j].question for j in range(batch_size)
- ]
- feed_dict[gr.batch_question_attention_mask] = [
- feed_examples[j].question_attention_mask for j in range(batch_size)
- ]
- feed_dict[
- gr.batch_answer] = [feed_examples[j].answer for j in range(batch_size)]
- feed_dict[gr.batch_number_column] = [
- feed_examples[j].columns for j in range(batch_size)
- ]
- feed_dict[gr.batch_processed_number_column] = [
- feed_examples[j].processed_number_columns for j in range(batch_size)
- ]
- feed_dict[gr.batch_processed_sorted_index_number_column] = [
- feed_examples[j].sorted_number_index for j in range(batch_size)
- ]
- feed_dict[gr.batch_processed_sorted_index_word_column] = [
- feed_examples[j].sorted_word_index for j in range(batch_size)
- ]
- feed_dict[gr.batch_question_number] = np.array(
- [feed_examples[j].question_number for j in range(batch_size)]).reshape(
- (batch_size, 1))
- feed_dict[gr.batch_question_number_one] = np.array(
- [feed_examples[j].question_number_1 for j in range(batch_size)]).reshape(
- (batch_size, 1))
- feed_dict[gr.batch_question_number_mask] = [
- feed_examples[j].question_number_mask for j in range(batch_size)
- ]
- feed_dict[gr.batch_question_number_one_mask] = np.array(
- [feed_examples[j].question_number_one_mask for j in range(batch_size)
- ]).reshape((batch_size, 1))
- feed_dict[gr.batch_print_answer] = [
- feed_examples[j].print_answer for j in range(batch_size)
- ]
- feed_dict[gr.batch_exact_match] = [
- feed_examples[j].exact_match for j in range(batch_size)
- ]
- feed_dict[gr.batch_group_by_max] = [
- feed_examples[j].group_by_max for j in range(batch_size)
- ]
- feed_dict[gr.batch_column_exact_match] = [
- feed_examples[j].exact_column_match for j in range(batch_size)
- ]
- feed_dict[gr.batch_ordinal_question] = [
- feed_examples[j].ordinal_question for j in range(batch_size)
- ]
- feed_dict[gr.batch_ordinal_question_one] = [
- feed_examples[j].ordinal_question_one for j in range(batch_size)
- ]
- feed_dict[gr.batch_number_column_mask] = [
- feed_examples[j].column_mask for j in range(batch_size)
- ]
- feed_dict[gr.batch_number_column_names] = [
- feed_examples[j].column_ids for j in range(batch_size)
- ]
- feed_dict[gr.batch_processed_word_column] = [
- feed_examples[j].processed_word_columns for j in range(batch_size)
- ]
- feed_dict[gr.batch_word_column_mask] = [
- feed_examples[j].word_column_mask for j in range(batch_size)
- ]
- feed_dict[gr.batch_word_column_names] = [
- feed_examples[j].word_column_ids for j in range(batch_size)
- ]
- feed_dict[gr.batch_word_column_entry_mask] = [
- feed_examples[j].word_column_entry_mask for j in range(batch_size)
- ]
- return feed_dict
diff --git a/research/neural_programmer/model.py b/research/neural_programmer/model.py
deleted file mode 100644
index 610d66699e6e41188be58cc1f623c030d243c689..0000000000000000000000000000000000000000
--- a/research/neural_programmer/model.py
+++ /dev/null
@@ -1,679 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Author: aneelakantan (Arvind Neelakantan)
-"""
-
-from __future__ import print_function
-
-import numpy as np
-import tensorflow as tf
-import nn_utils
-
-
-class Graph():
-
- def __init__(self, utility, batch_size, max_passes, mode="train"):
- self.utility = utility
- self.data_type = self.utility.tf_data_type[self.utility.FLAGS.data_type]
- self.max_elements = self.utility.FLAGS.max_elements
- max_elements = self.utility.FLAGS.max_elements
- self.num_cols = self.utility.FLAGS.max_number_cols
- self.num_word_cols = self.utility.FLAGS.max_word_cols
- self.question_length = self.utility.FLAGS.question_length
- self.batch_size = batch_size
- self.max_passes = max_passes
- self.mode = mode
- self.embedding_dims = self.utility.FLAGS.embedding_dims
- #input question and a mask
- self.batch_question = tf.placeholder(tf.int32,
- [batch_size, self.question_length])
- self.batch_question_attention_mask = tf.placeholder(
- self.data_type, [batch_size, self.question_length])
- #ground truth scalar answer and lookup answer
- self.batch_answer = tf.placeholder(self.data_type, [batch_size])
- self.batch_print_answer = tf.placeholder(
- self.data_type,
- [batch_size, self.num_cols + self.num_word_cols, max_elements])
- #number columns and its processed version
- self.batch_number_column = tf.placeholder(
- self.data_type, [batch_size, self.num_cols, max_elements
- ]) #columns with numeric entries
- self.batch_processed_number_column = tf.placeholder(
- self.data_type, [batch_size, self.num_cols, max_elements])
- self.batch_processed_sorted_index_number_column = tf.placeholder(
- tf.int32, [batch_size, self.num_cols, max_elements])
- #word columns and its processed version
- self.batch_processed_word_column = tf.placeholder(
- self.data_type, [batch_size, self.num_word_cols, max_elements])
- self.batch_processed_sorted_index_word_column = tf.placeholder(
- tf.int32, [batch_size, self.num_word_cols, max_elements])
- self.batch_word_column_entry_mask = tf.placeholder(
- tf.int32, [batch_size, self.num_word_cols, max_elements])
- #names of word and number columns along with their mask
- self.batch_word_column_names = tf.placeholder(
- tf.int32,
- [batch_size, self.num_word_cols, self.utility.FLAGS.max_entry_length])
- self.batch_word_column_mask = tf.placeholder(
- self.data_type, [batch_size, self.num_word_cols])
- self.batch_number_column_names = tf.placeholder(
- tf.int32,
- [batch_size, self.num_cols, self.utility.FLAGS.max_entry_length])
- self.batch_number_column_mask = tf.placeholder(self.data_type,
- [batch_size, self.num_cols])
- #exact match and group by max operation
- self.batch_exact_match = tf.placeholder(
- self.data_type,
- [batch_size, self.num_cols + self.num_word_cols, max_elements])
- self.batch_column_exact_match = tf.placeholder(
- self.data_type, [batch_size, self.num_cols + self.num_word_cols])
- self.batch_group_by_max = tf.placeholder(
- self.data_type,
- [batch_size, self.num_cols + self.num_word_cols, max_elements])
- #numbers in the question along with their position. This is used to compute arguments to the comparison operations
- self.batch_question_number = tf.placeholder(self.data_type, [batch_size, 1])
- self.batch_question_number_one = tf.placeholder(self.data_type,
- [batch_size, 1])
- self.batch_question_number_mask = tf.placeholder(
- self.data_type, [batch_size, max_elements])
- self.batch_question_number_one_mask = tf.placeholder(self.data_type,
- [batch_size, 1])
- self.batch_ordinal_question = tf.placeholder(
- self.data_type, [batch_size, self.question_length])
- self.batch_ordinal_question_one = tf.placeholder(
- self.data_type, [batch_size, self.question_length])
-
- def LSTM_question_embedding(self, sentence, sentence_length):
- #LSTM processes the input question
- lstm_params = "question_lstm"
- hidden_vectors = []
- sentence = self.batch_question
- question_hidden = tf.zeros(
- [self.batch_size, self.utility.FLAGS.embedding_dims], self.data_type)
- question_c_hidden = tf.zeros(
- [self.batch_size, self.utility.FLAGS.embedding_dims], self.data_type)
- if (self.utility.FLAGS.rnn_dropout > 0.0):
- if (self.mode == "train"):
- rnn_dropout_mask = tf.cast(
- tf.random_uniform(
- tf.shape(question_hidden), minval=0.0, maxval=1.0) <
- self.utility.FLAGS.rnn_dropout,
- self.data_type) / self.utility.FLAGS.rnn_dropout
- else:
- rnn_dropout_mask = tf.ones_like(question_hidden)
- for question_iterator in range(self.question_length):
- curr_word = sentence[:, question_iterator]
- question_vector = nn_utils.apply_dropout(
- nn_utils.get_embedding(curr_word, self.utility, self.params),
- self.utility.FLAGS.dropout, self.mode)
- question_hidden, question_c_hidden = nn_utils.LSTMCell(
- question_vector, question_hidden, question_c_hidden, lstm_params,
- self.params)
- if (self.utility.FLAGS.rnn_dropout > 0.0):
- question_hidden = question_hidden * rnn_dropout_mask
- hidden_vectors.append(tf.expand_dims(question_hidden, 0))
- hidden_vectors = tf.concat(axis=0, values=hidden_vectors)
- return question_hidden, hidden_vectors
-
- def history_recurrent_step(self, curr_hprev, hprev):
- #A single RNN step for controller or history RNN
- return tf.tanh(
- tf.matmul(
- tf.concat(axis=1, values=[hprev, curr_hprev]), self.params[
- "history_recurrent"])) + self.params["history_recurrent_bias"]
-
- def question_number_softmax(self, hidden_vectors):
- #Attention on quetsion to decide the question number to passed to comparison ops
- def compute_ans(op_embedding, comparison):
- op_embedding = tf.expand_dims(op_embedding, 0)
- #dot product of operation embedding with hidden state to the left of the number occurrence
- first = tf.transpose(
- tf.matmul(op_embedding,
- tf.transpose(
- tf.reduce_sum(hidden_vectors * tf.tile(
- tf.expand_dims(
- tf.transpose(self.batch_ordinal_question), 2),
- [1, 1, self.utility.FLAGS.embedding_dims]), 0))))
- second = self.batch_question_number_one_mask + tf.transpose(
- tf.matmul(op_embedding,
- tf.transpose(
- tf.reduce_sum(hidden_vectors * tf.tile(
- tf.expand_dims(
- tf.transpose(self.batch_ordinal_question_one), 2
- ), [1, 1, self.utility.FLAGS.embedding_dims]), 0))))
- question_number_softmax = tf.nn.softmax(tf.concat(axis=1, values=[first, second]))
- if (self.mode == "test"):
- cond = tf.equal(question_number_softmax,
- tf.reshape(
- tf.reduce_max(question_number_softmax, 1),
- [self.batch_size, 1]))
- question_number_softmax = tf.where(
- cond,
- tf.fill(tf.shape(question_number_softmax), 1.0),
- tf.fill(tf.shape(question_number_softmax), 0.0))
- question_number_softmax = tf.cast(question_number_softmax,
- self.data_type)
- ans = tf.reshape(
- tf.reduce_sum(question_number_softmax * tf.concat(
- axis=1, values=[self.batch_question_number, self.batch_question_number_one]),
- 1), [self.batch_size, 1])
- return ans
-
- def compute_op_position(op_name):
- for i in range(len(self.utility.operations_set)):
- if (op_name == self.utility.operations_set[i]):
- return i
-
- def compute_question_number(op_name):
- op_embedding = tf.nn.embedding_lookup(self.params_unit,
- compute_op_position(op_name))
- return compute_ans(op_embedding, op_name)
-
- curr_greater_question_number = compute_question_number("greater")
- curr_lesser_question_number = compute_question_number("lesser")
- curr_geq_question_number = compute_question_number("geq")
- curr_leq_question_number = compute_question_number("leq")
- return curr_greater_question_number, curr_lesser_question_number, curr_geq_question_number, curr_leq_question_number
-
- def perform_attention(self, context_vector, hidden_vectors, length, mask):
- #Performs attention on hiddent_vectors using context vector
- context_vector = tf.tile(
- tf.expand_dims(context_vector, 0), [length, 1, 1]) #time * bs * d
- attention_softmax = tf.nn.softmax(
- tf.transpose(tf.reduce_sum(context_vector * hidden_vectors, 2)) +
- mask) #batch_size * time
- attention_softmax = tf.tile(
- tf.expand_dims(tf.transpose(attention_softmax), 2),
- [1, 1, self.embedding_dims])
- ans_vector = tf.reduce_sum(attention_softmax * hidden_vectors, 0)
- return ans_vector
-
- #computes embeddings for column names using parameters of question module
- def get_column_hidden_vectors(self):
- #vector representations for the column names
- self.column_hidden_vectors = tf.reduce_sum(
- nn_utils.get_embedding(self.batch_number_column_names, self.utility,
- self.params), 2)
- self.word_column_hidden_vectors = tf.reduce_sum(
- nn_utils.get_embedding(self.batch_word_column_names, self.utility,
- self.params), 2)
-
- def create_summary_embeddings(self):
- #embeddings for each text entry in the table using parameters of the question module
- self.summary_text_entry_embeddings = tf.reduce_sum(
- tf.expand_dims(self.batch_exact_match, 3) * tf.expand_dims(
- tf.expand_dims(
- tf.expand_dims(
- nn_utils.get_embedding(self.utility.entry_match_token_id,
- self.utility, self.params), 0), 1),
- 2), 2)
-
- def compute_column_softmax(self, column_controller_vector, time_step):
- #compute softmax over all the columns using column controller vector
- column_controller_vector = tf.tile(
- tf.expand_dims(column_controller_vector, 1),
- [1, self.num_cols + self.num_word_cols, 1]) #max_cols * bs * d
- column_controller_vector = nn_utils.apply_dropout(
- column_controller_vector, self.utility.FLAGS.dropout, self.mode)
- self.full_column_hidden_vectors = tf.concat(
- axis=1, values=[self.column_hidden_vectors, self.word_column_hidden_vectors])
- self.full_column_hidden_vectors += self.summary_text_entry_embeddings
- self.full_column_hidden_vectors = nn_utils.apply_dropout(
- self.full_column_hidden_vectors, self.utility.FLAGS.dropout, self.mode)
- column_logits = tf.reduce_sum(
- column_controller_vector * self.full_column_hidden_vectors, 2) + (
- self.params["word_match_feature_column_name"] *
- self.batch_column_exact_match) + self.full_column_mask
- column_softmax = tf.nn.softmax(column_logits) #batch_size * max_cols
- return column_softmax
-
- def compute_first_or_last(self, select, first=True):
- #perform first ot last operation on row select with probabilistic row selection
- answer = tf.zeros_like(select)
- running_sum = tf.zeros([self.batch_size, 1], self.data_type)
- for i in range(self.max_elements):
- if (first):
- current = tf.slice(select, [0, i], [self.batch_size, 1])
- else:
- current = tf.slice(select, [0, self.max_elements - 1 - i],
- [self.batch_size, 1])
- curr_prob = current * (1 - running_sum)
- curr_prob = curr_prob * tf.cast(curr_prob >= 0.0, self.data_type)
- running_sum += curr_prob
- temp_ans = []
- curr_prob = tf.expand_dims(tf.reshape(curr_prob, [self.batch_size]), 0)
- for i_ans in range(self.max_elements):
- if (not (first) and i_ans == self.max_elements - 1 - i):
- temp_ans.append(curr_prob)
- elif (first and i_ans == i):
- temp_ans.append(curr_prob)
- else:
- temp_ans.append(tf.zeros_like(curr_prob))
- temp_ans = tf.transpose(tf.concat(axis=0, values=temp_ans))
- answer += temp_ans
- return answer
-
- def make_hard_softmax(self, softmax):
- #converts soft selection to hard selection. used at test time
- cond = tf.equal(
- softmax, tf.reshape(tf.reduce_max(softmax, 1), [self.batch_size, 1]))
- softmax = tf.where(
- cond, tf.fill(tf.shape(softmax), 1.0), tf.fill(tf.shape(softmax), 0.0))
- softmax = tf.cast(softmax, self.data_type)
- return softmax
-
- def compute_max_or_min(self, select, maxi=True):
- #computes the argmax and argmin of a column with probabilistic row selection
- answer = tf.zeros([
- self.batch_size, self.num_cols + self.num_word_cols, self.max_elements
- ], self.data_type)
- sum_prob = tf.zeros([self.batch_size, self.num_cols + self.num_word_cols],
- self.data_type)
- for j in range(self.max_elements):
- if (maxi):
- curr_pos = j
- else:
- curr_pos = self.max_elements - 1 - j
- select_index = tf.slice(self.full_processed_sorted_index_column,
- [0, 0, curr_pos], [self.batch_size, -1, 1])
- select_mask = tf.equal(
- tf.tile(
- tf.expand_dims(
- tf.tile(
- tf.expand_dims(tf.range(self.max_elements), 0),
- [self.batch_size, 1]), 1),
- [1, self.num_cols + self.num_word_cols, 1]), select_index)
- curr_prob = tf.expand_dims(select, 1) * tf.cast(
- select_mask, self.data_type) * self.select_bad_number_mask
- curr_prob = curr_prob * tf.expand_dims((1 - sum_prob), 2)
- curr_prob = curr_prob * tf.expand_dims(
- tf.cast((1 - sum_prob) > 0.0, self.data_type), 2)
- answer = tf.where(select_mask, curr_prob, answer)
- sum_prob += tf.reduce_sum(curr_prob, 2)
- return answer
-
- def perform_operations(self, softmax, full_column_softmax, select,
- prev_select_1, curr_pass):
- #performs all the 15 operations. computes scalar output, lookup answer and row selector
- column_softmax = tf.slice(full_column_softmax, [0, 0],
- [self.batch_size, self.num_cols])
- word_column_softmax = tf.slice(full_column_softmax, [0, self.num_cols],
- [self.batch_size, self.num_word_cols])
- init_max = self.compute_max_or_min(select, maxi=True)
- init_min = self.compute_max_or_min(select, maxi=False)
- #operations that are column independent
- count = tf.reshape(tf.reduce_sum(select, 1), [self.batch_size, 1])
- select_full_column_softmax = tf.tile(
- tf.expand_dims(full_column_softmax, 2),
- [1, 1, self.max_elements
- ]) #BS * (max_cols + max_word_cols) * max_elements
- select_word_column_softmax = tf.tile(
- tf.expand_dims(word_column_softmax, 2),
- [1, 1, self.max_elements]) #BS * max_word_cols * max_elements
- select_greater = tf.reduce_sum(
- self.init_select_greater * select_full_column_softmax,
- 1) * self.batch_question_number_mask #BS * max_elements
- select_lesser = tf.reduce_sum(
- self.init_select_lesser * select_full_column_softmax,
- 1) * self.batch_question_number_mask #BS * max_elements
- select_geq = tf.reduce_sum(
- self.init_select_geq * select_full_column_softmax,
- 1) * self.batch_question_number_mask #BS * max_elements
- select_leq = tf.reduce_sum(
- self.init_select_leq * select_full_column_softmax,
- 1) * self.batch_question_number_mask #BS * max_elements
- select_max = tf.reduce_sum(init_max * select_full_column_softmax,
- 1) #BS * max_elements
- select_min = tf.reduce_sum(init_min * select_full_column_softmax,
- 1) #BS * max_elements
- select_prev = tf.concat(axis=1, values=[
- tf.slice(select, [0, 1], [self.batch_size, self.max_elements - 1]),
- tf.cast(tf.zeros([self.batch_size, 1]), self.data_type)
- ])
- select_next = tf.concat(axis=1, values=[
- tf.cast(tf.zeros([self.batch_size, 1]), self.data_type), tf.slice(
- select, [0, 0], [self.batch_size, self.max_elements - 1])
- ])
- select_last_rs = self.compute_first_or_last(select, False)
- select_first_rs = self.compute_first_or_last(select, True)
- select_word_match = tf.reduce_sum(self.batch_exact_match *
- select_full_column_softmax, 1)
- select_group_by_max = tf.reduce_sum(self.batch_group_by_max *
- select_full_column_softmax, 1)
- length_content = 1
- length_select = 13
- length_print = 1
- values = tf.concat(axis=1, values=[count])
- softmax_content = tf.slice(softmax, [0, 0],
- [self.batch_size, length_content])
- #compute scalar output
- output = tf.reduce_sum(tf.multiply(softmax_content, values), 1)
- #compute lookup answer
- softmax_print = tf.slice(softmax, [0, length_content + length_select],
- [self.batch_size, length_print])
- curr_print = select_full_column_softmax * tf.tile(
- tf.expand_dims(select, 1),
- [1, self.num_cols + self.num_word_cols, 1
- ]) #BS * max_cols * max_elements (conisders only column)
- self.batch_lookup_answer = curr_print * tf.tile(
- tf.expand_dims(softmax_print, 2),
- [1, self.num_cols + self.num_word_cols, self.max_elements
- ]) #BS * max_cols * max_elements
- self.batch_lookup_answer = self.batch_lookup_answer * self.select_full_mask
- #compute row select
- softmax_select = tf.slice(softmax, [0, length_content],
- [self.batch_size, length_select])
- select_lists = [
- tf.expand_dims(select_prev, 1), tf.expand_dims(select_next, 1),
- tf.expand_dims(select_first_rs, 1), tf.expand_dims(select_last_rs, 1),
- tf.expand_dims(select_group_by_max, 1),
- tf.expand_dims(select_greater, 1), tf.expand_dims(select_lesser, 1),
- tf.expand_dims(select_geq, 1), tf.expand_dims(select_leq, 1),
- tf.expand_dims(select_max, 1), tf.expand_dims(select_min, 1),
- tf.expand_dims(select_word_match, 1),
- tf.expand_dims(self.reset_select, 1)
- ]
- select = tf.reduce_sum(
- tf.tile(tf.expand_dims(softmax_select, 2), [1, 1, self.max_elements]) *
- tf.concat(axis=1, values=select_lists), 1)
- select = select * self.select_whole_mask
- return output, select
-
- def one_pass(self, select, question_embedding, hidden_vectors, hprev,
- prev_select_1, curr_pass):
- #Performs one timestep which involves selecting an operation and a column
- attention_vector = self.perform_attention(
- hprev, hidden_vectors, self.question_length,
- self.batch_question_attention_mask) #batch_size * embedding_dims
- controller_vector = tf.nn.relu(
- tf.matmul(hprev, self.params["controller_prev"]) + tf.matmul(
- tf.concat(axis=1, values=[question_embedding, attention_vector]), self.params[
- "controller"]))
- column_controller_vector = tf.nn.relu(
- tf.matmul(hprev, self.params["column_controller_prev"]) + tf.matmul(
- tf.concat(axis=1, values=[question_embedding, attention_vector]), self.params[
- "column_controller"]))
- controller_vector = nn_utils.apply_dropout(
- controller_vector, self.utility.FLAGS.dropout, self.mode)
- self.operation_logits = tf.matmul(controller_vector,
- tf.transpose(self.params_unit))
- softmax = tf.nn.softmax(self.operation_logits)
- soft_softmax = softmax
- #compute column softmax: bs * max_columns
- weighted_op_representation = tf.transpose(
- tf.matmul(tf.transpose(self.params_unit), tf.transpose(softmax)))
- column_controller_vector = tf.nn.relu(
- tf.matmul(
- tf.concat(axis=1, values=[
- column_controller_vector, weighted_op_representation
- ]), self.params["break_conditional"]))
- full_column_softmax = self.compute_column_softmax(column_controller_vector,
- curr_pass)
- soft_column_softmax = full_column_softmax
- if (self.mode == "test"):
- full_column_softmax = self.make_hard_softmax(full_column_softmax)
- softmax = self.make_hard_softmax(softmax)
- output, select = self.perform_operations(softmax, full_column_softmax,
- select, prev_select_1, curr_pass)
- return output, select, softmax, soft_softmax, full_column_softmax, soft_column_softmax
-
- def compute_lookup_error(self, val):
- #computes lookup error.
- cond = tf.equal(self.batch_print_answer, val)
- inter = tf.where(
- cond, self.init_print_error,
- tf.tile(
- tf.reshape(tf.constant(1e10, self.data_type), [1, 1, 1]), [
- self.batch_size, self.utility.FLAGS.max_word_cols +
- self.utility.FLAGS.max_number_cols,
- self.utility.FLAGS.max_elements
- ]))
- return tf.reduce_min(tf.reduce_min(inter, 1), 1) * tf.cast(
- tf.greater(
- tf.reduce_sum(tf.reduce_sum(tf.cast(cond, self.data_type), 1), 1),
- 0.0), self.data_type)
-
- def soft_min(self, x, y):
- return tf.maximum(-1.0 * (1 / (
- self.utility.FLAGS.soft_min_value + 0.0)) * tf.log(
- tf.exp(-self.utility.FLAGS.soft_min_value * x) + tf.exp(
- -self.utility.FLAGS.soft_min_value * y)), tf.zeros_like(x))
-
- def error_computation(self):
- #computes the error of each example in a batch
- math_error = 0.5 * tf.square(tf.subtract(self.scalar_output, self.batch_answer))
- #scale math error
- math_error = math_error / self.rows
- math_error = tf.minimum(math_error, self.utility.FLAGS.max_math_error *
- tf.ones(tf.shape(math_error), self.data_type))
- self.init_print_error = tf.where(
- self.batch_gold_select, -1 * tf.log(self.batch_lookup_answer + 1e-300 +
- self.invert_select_full_mask), -1 *
- tf.log(1 - self.batch_lookup_answer)) * self.select_full_mask
- print_error_1 = self.init_print_error * tf.cast(
- tf.equal(self.batch_print_answer, 0.0), self.data_type)
- print_error = tf.reduce_sum(tf.reduce_sum((print_error_1), 1), 1)
- for val in range(1, 58):
- print_error += self.compute_lookup_error(val + 0.0)
- print_error = print_error * self.utility.FLAGS.print_cost / self.num_entries
- if (self.mode == "train"):
- error = tf.where(
- tf.logical_and(
- tf.not_equal(self.batch_answer, 0.0),
- tf.not_equal(
- tf.reduce_sum(tf.reduce_sum(self.batch_print_answer, 1), 1),
- 0.0)),
- self.soft_min(math_error, print_error),
- tf.where(
- tf.not_equal(self.batch_answer, 0.0), math_error, print_error))
- else:
- error = tf.where(
- tf.logical_and(
- tf.equal(self.scalar_output, 0.0),
- tf.equal(
- tf.reduce_sum(tf.reduce_sum(self.batch_lookup_answer, 1), 1),
- 0.0)),
- tf.ones_like(math_error),
- tf.where(
- tf.equal(self.scalar_output, 0.0), print_error, math_error))
- return error
-
- def batch_process(self):
- #Computes loss and fraction of correct examples in a batch.
- self.params_unit = nn_utils.apply_dropout(
- self.params["unit"], self.utility.FLAGS.dropout, self.mode)
- batch_size = self.batch_size
- max_passes = self.max_passes
- num_timesteps = 1
- max_elements = self.max_elements
- select = tf.cast(
- tf.fill([self.batch_size, max_elements], 1.0), self.data_type)
- hprev = tf.cast(
- tf.fill([self.batch_size, self.embedding_dims], 0.0),
- self.data_type) #running sum of the hidden states of the model
- output = tf.cast(tf.fill([self.batch_size, 1], 0.0),
- self.data_type) #output of the model
- correct = tf.cast(
- tf.fill([1], 0.0), self.data_type
- ) #to compute accuracy, returns number of correct examples for this batch
- total_error = 0.0
- prev_select_1 = tf.zeros_like(select)
- self.create_summary_embeddings()
- self.get_column_hidden_vectors()
- #get question embedding
- question_embedding, hidden_vectors = self.LSTM_question_embedding(
- self.batch_question, self.question_length)
- #compute arguments for comparison operation
- greater_question_number, lesser_question_number, geq_question_number, leq_question_number = self.question_number_softmax(
- hidden_vectors)
- self.init_select_greater = tf.cast(
- tf.greater(self.full_processed_column,
- tf.expand_dims(greater_question_number, 2)), self.
- data_type) * self.select_bad_number_mask #bs * max_cols * max_elements
- self.init_select_lesser = tf.cast(
- tf.less(self.full_processed_column,
- tf.expand_dims(lesser_question_number, 2)), self.
- data_type) * self.select_bad_number_mask #bs * max_cols * max_elements
- self.init_select_geq = tf.cast(
- tf.greater_equal(self.full_processed_column,
- tf.expand_dims(geq_question_number, 2)), self.
- data_type) * self.select_bad_number_mask #bs * max_cols * max_elements
- self.init_select_leq = tf.cast(
- tf.less_equal(self.full_processed_column,
- tf.expand_dims(leq_question_number, 2)), self.
- data_type) * self.select_bad_number_mask #bs * max_cols * max_elements
- self.init_select_word_match = 0
- if (self.utility.FLAGS.rnn_dropout > 0.0):
- if (self.mode == "train"):
- history_rnn_dropout_mask = tf.cast(
- tf.random_uniform(
- tf.shape(hprev), minval=0.0, maxval=1.0) <
- self.utility.FLAGS.rnn_dropout,
- self.data_type) / self.utility.FLAGS.rnn_dropout
- else:
- history_rnn_dropout_mask = tf.ones_like(hprev)
- select = select * self.select_whole_mask
- self.batch_log_prob = tf.zeros([self.batch_size], dtype=self.data_type)
- #Perform max_passes and at each pass select operation and column
- for curr_pass in range(max_passes):
- print("step: ", curr_pass)
- output, select, softmax, soft_softmax, column_softmax, soft_column_softmax = self.one_pass(
- select, question_embedding, hidden_vectors, hprev, prev_select_1,
- curr_pass)
- prev_select_1 = select
- #compute input to history RNN
- input_op = tf.transpose(
- tf.matmul(
- tf.transpose(self.params_unit), tf.transpose(
- soft_softmax))) #weighted average of emebdding of operations
- input_col = tf.reduce_sum(
- tf.expand_dims(soft_column_softmax, 2) *
- self.full_column_hidden_vectors, 1)
- history_input = tf.concat(axis=1, values=[input_op, input_col])
- history_input = nn_utils.apply_dropout(
- history_input, self.utility.FLAGS.dropout, self.mode)
- hprev = self.history_recurrent_step(history_input, hprev)
- if (self.utility.FLAGS.rnn_dropout > 0.0):
- hprev = hprev * history_rnn_dropout_mask
- self.scalar_output = output
- error = self.error_computation()
- cond = tf.less(error, 0.0001, name="cond")
- correct_add = tf.where(
- cond, tf.fill(tf.shape(cond), 1.0), tf.fill(tf.shape(cond), 0.0))
- correct = tf.reduce_sum(correct_add)
- error = error / batch_size
- total_error = tf.reduce_sum(error)
- total_correct = correct / batch_size
- return total_error, total_correct
-
- def compute_error(self):
- #Sets mask variables and performs batch processing
- self.batch_gold_select = self.batch_print_answer > 0.0
- self.full_column_mask = tf.concat(
- axis=1, values=[self.batch_number_column_mask, self.batch_word_column_mask])
- self.full_processed_column = tf.concat(
- axis=1,
- values=[self.batch_processed_number_column, self.batch_processed_word_column])
- self.full_processed_sorted_index_column = tf.concat(axis=1, values=[
- self.batch_processed_sorted_index_number_column,
- self.batch_processed_sorted_index_word_column
- ])
- self.select_bad_number_mask = tf.cast(
- tf.logical_and(
- tf.not_equal(self.full_processed_column,
- self.utility.FLAGS.pad_int),
- tf.not_equal(self.full_processed_column,
- self.utility.FLAGS.bad_number_pre_process)),
- self.data_type)
- self.select_mask = tf.cast(
- tf.logical_not(
- tf.equal(self.batch_number_column, self.utility.FLAGS.pad_int)),
- self.data_type)
- self.select_word_mask = tf.cast(
- tf.logical_not(
- tf.equal(self.batch_word_column_entry_mask,
- self.utility.dummy_token_id)), self.data_type)
- self.select_full_mask = tf.concat(
- axis=1, values=[self.select_mask, self.select_word_mask])
- self.select_whole_mask = tf.maximum(
- tf.reshape(
- tf.slice(self.select_mask, [0, 0, 0],
- [self.batch_size, 1, self.max_elements]),
- [self.batch_size, self.max_elements]),
- tf.reshape(
- tf.slice(self.select_word_mask, [0, 0, 0],
- [self.batch_size, 1, self.max_elements]),
- [self.batch_size, self.max_elements]))
- self.invert_select_full_mask = tf.cast(
- tf.concat(axis=1, values=[
- tf.equal(self.batch_number_column, self.utility.FLAGS.pad_int),
- tf.equal(self.batch_word_column_entry_mask,
- self.utility.dummy_token_id)
- ]), self.data_type)
- self.batch_lookup_answer = tf.zeros(tf.shape(self.batch_gold_select))
- self.reset_select = self.select_whole_mask
- self.rows = tf.reduce_sum(self.select_whole_mask, 1)
- self.num_entries = tf.reshape(
- tf.reduce_sum(tf.reduce_sum(self.select_full_mask, 1), 1),
- [self.batch_size])
- self.final_error, self.final_correct = self.batch_process()
- return self.final_error
-
- def create_graph(self, params, global_step):
- #Creates the graph to compute error, gradient computation and updates parameters
- self.params = params
- batch_size = self.batch_size
- learning_rate = tf.cast(self.utility.FLAGS.learning_rate, self.data_type)
- self.total_cost = self.compute_error()
- optimize_params = self.params.values()
- optimize_names = self.params.keys()
- print("optimize params ", optimize_names)
- if (self.utility.FLAGS.l2_regularizer > 0.0):
- reg_cost = 0.0
- for ind_param in self.params.keys():
- reg_cost += tf.nn.l2_loss(self.params[ind_param])
- self.total_cost += self.utility.FLAGS.l2_regularizer * reg_cost
- grads = tf.gradients(self.total_cost, optimize_params, name="gradients")
- grad_norm = 0.0
- for p, name in zip(grads, optimize_names):
- print("grads: ", p, name)
- if isinstance(p, tf.IndexedSlices):
- grad_norm += tf.reduce_sum(p.values * p.values)
- elif not (p == None):
- grad_norm += tf.reduce_sum(p * p)
- grad_norm = tf.sqrt(grad_norm)
- max_grad_norm = np.float32(self.utility.FLAGS.clip_gradients).astype(
- self.utility.np_data_type[self.utility.FLAGS.data_type])
- grad_scale = tf.minimum(
- tf.cast(1.0, self.data_type), max_grad_norm / grad_norm)
- clipped_grads = list()
- for p in grads:
- if isinstance(p, tf.IndexedSlices):
- tmp = p.values * grad_scale
- clipped_grads.append(tf.IndexedSlices(tmp, p.indices))
- elif not (p == None):
- clipped_grads.append(p * grad_scale)
- else:
- clipped_grads.append(p)
- grads = clipped_grads
- self.global_step = global_step
- params_list = self.params.values()
- params_list.append(self.global_step)
- adam = tf.train.AdamOptimizer(
- learning_rate,
- epsilon=tf.cast(self.utility.FLAGS.eps, self.data_type),
- use_locking=True)
- self.step = adam.apply_gradients(zip(grads, optimize_params),
- global_step=self.global_step)
- self.init_op = tf.global_variables_initializer()
diff --git a/research/neural_programmer/neural_programmer.py b/research/neural_programmer/neural_programmer.py
deleted file mode 100644
index 145ca13d6ac8ce80d651f902440bfb3240f1c7a2..0000000000000000000000000000000000000000
--- a/research/neural_programmer/neural_programmer.py
+++ /dev/null
@@ -1,239 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Implementation of the Neural Programmer model described in https://openreview.net/pdf?id=ry2YOrcge
-
-This file calls functions to load & pre-process data, construct the TF graph
-and performs training or evaluation as specified by the flag evaluator_job
-Author: aneelakantan (Arvind Neelakantan)
-"""
-from __future__ import print_function
-
-import time
-from random import Random
-import numpy as np
-import tensorflow as tf
-import model
-import wiki_data
-import parameters
-import data_utils
-
-tf.flags.DEFINE_integer("train_steps", 100001, "Number of steps to train")
-tf.flags.DEFINE_integer("eval_cycle", 500,
- "Evaluate model at every eval_cycle steps")
-tf.flags.DEFINE_integer("max_elements", 100,
- "maximum rows that are considered for processing")
-tf.flags.DEFINE_integer(
- "max_number_cols", 15,
- "maximum number columns that are considered for processing")
-tf.flags.DEFINE_integer(
- "max_word_cols", 25,
- "maximum number columns that are considered for processing")
-tf.flags.DEFINE_integer("question_length", 62, "maximum question length")
-tf.flags.DEFINE_integer("max_entry_length", 1, "")
-tf.flags.DEFINE_integer("max_passes", 4, "number of operation passes")
-tf.flags.DEFINE_integer("embedding_dims", 256, "")
-tf.flags.DEFINE_integer("batch_size", 20, "")
-tf.flags.DEFINE_float("clip_gradients", 1.0, "")
-tf.flags.DEFINE_float("eps", 1e-6, "")
-tf.flags.DEFINE_float("param_init", 0.1, "")
-tf.flags.DEFINE_float("learning_rate", 0.001, "")
-tf.flags.DEFINE_float("l2_regularizer", 0.0001, "")
-tf.flags.DEFINE_float("print_cost", 50.0,
- "weighting factor in the objective function")
-tf.flags.DEFINE_string("job_id", "temp", """job id""")
-tf.flags.DEFINE_string("output_dir", "../model/",
- """output_dir""")
-tf.flags.DEFINE_string("data_dir", "../data/",
- """data_dir""")
-tf.flags.DEFINE_integer("write_every", 500, "wrtie every N")
-tf.flags.DEFINE_integer("param_seed", 150, "")
-tf.flags.DEFINE_integer("python_seed", 200, "")
-tf.flags.DEFINE_float("dropout", 0.8, "dropout keep probability")
-tf.flags.DEFINE_float("rnn_dropout", 0.9,
- "dropout keep probability for rnn connections")
-tf.flags.DEFINE_float("pad_int", -20000.0,
- "number columns are padded with pad_int")
-tf.flags.DEFINE_string("data_type", "double", "float or double")
-tf.flags.DEFINE_float("word_dropout_prob", 0.9, "word dropout keep prob")
-tf.flags.DEFINE_integer("word_cutoff", 10, "")
-tf.flags.DEFINE_integer("vocab_size", 10800, "")
-tf.flags.DEFINE_boolean("evaluator_job", False,
- "wehther to run as trainer/evaluator")
-tf.flags.DEFINE_float(
- "bad_number_pre_process", -200000.0,
- "number that is added to a corrupted table entry in a number column")
-tf.flags.DEFINE_float("max_math_error", 3.0,
- "max square loss error that is considered")
-tf.flags.DEFINE_float("soft_min_value", 5.0, "")
-FLAGS = tf.flags.FLAGS
-
-
-class Utility:
- #holds FLAGS and other variables that are used in different files
- def __init__(self):
- global FLAGS
- self.FLAGS = FLAGS
- self.unk_token = "UNK"
- self.entry_match_token = "entry_match"
- self.column_match_token = "column_match"
- self.dummy_token = "dummy_token"
- self.tf_data_type = {}
- self.tf_data_type["double"] = tf.float64
- self.tf_data_type["float"] = tf.float32
- self.np_data_type = {}
- self.np_data_type["double"] = np.float64
- self.np_data_type["float"] = np.float32
- self.operations_set = ["count"] + [
- "prev", "next", "first_rs", "last_rs", "group_by_max", "greater",
- "lesser", "geq", "leq", "max", "min", "word-match"
- ] + ["reset_select"] + ["print"]
- self.word_ids = {}
- self.reverse_word_ids = {}
- self.word_count = {}
- self.random = Random(FLAGS.python_seed)
-
-
-def evaluate(sess, data, batch_size, graph, i):
- #computes accuracy
- num_examples = 0.0
- gc = 0.0
- for j in range(0, len(data) - batch_size + 1, batch_size):
- [ct] = sess.run([graph.final_correct],
- feed_dict=data_utils.generate_feed_dict(data, j, batch_size,
- graph))
- gc += ct * batch_size
- num_examples += batch_size
- print("dev set accuracy after ", i, " : ", gc / num_examples)
- print(num_examples, len(data))
- print("--------")
-
-
-def Train(graph, utility, batch_size, train_data, sess, model_dir,
- saver):
- #performs training
- curr = 0
- train_set_loss = 0.0
- utility.random.shuffle(train_data)
- start = time.time()
- for i in range(utility.FLAGS.train_steps):
- curr_step = i
- if (i > 0 and i % FLAGS.write_every == 0):
- model_file = model_dir + "/model_" + str(i)
- saver.save(sess, model_file)
- if curr + batch_size >= len(train_data):
- curr = 0
- utility.random.shuffle(train_data)
- step, cost_value = sess.run(
- [graph.step, graph.total_cost],
- feed_dict=data_utils.generate_feed_dict(
- train_data, curr, batch_size, graph, train=True, utility=utility))
- curr = curr + batch_size
- train_set_loss += cost_value
- if (i > 0 and i % FLAGS.eval_cycle == 0):
- end = time.time()
- time_taken = end - start
- print("step ", i, " ", time_taken, " seconds ")
- start = end
- print(" printing train set loss: ", train_set_loss / utility.FLAGS.eval_cycle)
- train_set_loss = 0.0
-
-
-def master(train_data, dev_data, utility):
- #creates TF graph and calls trainer or evaluator
- batch_size = utility.FLAGS.batch_size
- model_dir = utility.FLAGS.output_dir + "/model" + utility.FLAGS.job_id + "/"
- #create all paramters of the model
- param_class = parameters.Parameters(utility)
- params, global_step, init = param_class.parameters(utility)
- key = "test" if (FLAGS.evaluator_job) else "train"
- graph = model.Graph(utility, batch_size, utility.FLAGS.max_passes, mode=key)
- graph.create_graph(params, global_step)
- prev_dev_error = 0.0
- final_loss = 0.0
- final_accuracy = 0.0
- #start session
- with tf.Session() as sess:
- sess.run(init.name)
- sess.run(graph.init_op.name)
- to_save = params.copy()
- saver = tf.train.Saver(to_save, max_to_keep=500)
- if (FLAGS.evaluator_job):
- while True:
- selected_models = {}
- file_list = tf.gfile.ListDirectory(model_dir)
- for model_file in file_list:
- if ("checkpoint" in model_file or "index" in model_file or
- "meta" in model_file):
- continue
- if ("data" in model_file):
- model_file = model_file.split(".")[0]
- model_step = int(
- model_file.split("_")[len(model_file.split("_")) - 1])
- selected_models[model_step] = model_file
- file_list = sorted(selected_models.items(), key=lambda x: x[0])
- if (len(file_list) > 0):
- file_list = file_list[0:len(file_list) - 1]
- print("list of models: ", file_list)
- for model_file in file_list:
- model_file = model_file[1]
- print("restoring: ", model_file)
- saver.restore(sess, model_dir + "/" + model_file)
- model_step = int(
- model_file.split("_")[len(model_file.split("_")) - 1])
- print("evaluating on dev ", model_file, model_step)
- evaluate(sess, dev_data, batch_size, graph, model_step)
- else:
- ckpt = tf.train.get_checkpoint_state(model_dir)
- print("model dir: ", model_dir)
- if (not (tf.gfile.IsDirectory(utility.FLAGS.output_dir))):
- print("create dir: ", utility.FLAGS.output_dir)
- tf.gfile.MkDir(utility.FLAGS.output_dir)
- if (not (tf.gfile.IsDirectory(model_dir))):
- print("create dir: ", model_dir)
- tf.gfile.MkDir(model_dir)
- Train(graph, utility, batch_size, train_data, sess, model_dir,
- saver)
-
-def main(args):
- utility = Utility()
- train_name = "random-split-1-train.examples"
- dev_name = "random-split-1-dev.examples"
- test_name = "pristine-unseen-tables.examples"
- #load data
- dat = wiki_data.WikiQuestionGenerator(train_name, dev_name, test_name, FLAGS.data_dir)
- train_data, dev_data, test_data = dat.load()
- utility.words = []
- utility.word_ids = {}
- utility.reverse_word_ids = {}
- #construct vocabulary
- data_utils.construct_vocab(train_data, utility)
- data_utils.construct_vocab(dev_data, utility, True)
- data_utils.construct_vocab(test_data, utility, True)
- data_utils.add_special_words(utility)
- data_utils.perform_word_cutoff(utility)
- #convert data to int format and pad the inputs
- train_data = data_utils.complete_wiki_processing(train_data, utility, True)
- dev_data = data_utils.complete_wiki_processing(dev_data, utility, False)
- test_data = data_utils.complete_wiki_processing(test_data, utility, False)
- print("# train examples ", len(train_data))
- print("# dev examples ", len(dev_data))
- print("# test examples ", len(test_data))
- print("running open source")
- #construct TF graph and train or evaluate
- master(train_data, dev_data, utility)
-
-
-if __name__ == "__main__":
- tf.app.run()
diff --git a/research/neural_programmer/nn_utils.py b/research/neural_programmer/nn_utils.py
deleted file mode 100644
index 2f3a1a98bf7f71631410fc88982b336d33a02f52..0000000000000000000000000000000000000000
--- a/research/neural_programmer/nn_utils.py
+++ /dev/null
@@ -1,68 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Author: aneelakantan (Arvind Neelakantan)
-"""
-
-import tensorflow as tf
-
-def get_embedding(word, utility, params):
- return tf.nn.embedding_lookup(params["word"], word)
-
-
-def apply_dropout(x, dropout_rate, mode):
- if (dropout_rate > 0.0):
- if (mode == "train"):
- x = tf.nn.dropout(x, dropout_rate)
- else:
- x = x
- return x
-
-
-def LSTMCell(x, mprev, cprev, key, params):
- """Create an LSTM cell.
-
- Implements the equations in pg.2 from
- "Long Short-Term Memory Based Recurrent Neural Network Architectures
- For Large Vocabulary Speech Recognition",
- Hasim Sak, Andrew Senior, Francoise Beaufays.
-
- Args:
- w: A dictionary of the weights and optional biases as returned
- by LSTMParametersSplit().
- x: Inputs to this cell.
- mprev: m_{t-1}, the recurrent activations (same as the output)
- from the previous cell.
- cprev: c_{t-1}, the cell activations from the previous cell.
- keep_prob: Keep probability on the input and the outputs of a cell.
-
- Returns:
- m: Outputs of this cell.
- c: Cell Activations.
- """
-
- i = tf.matmul(x, params[key + "_ix"]) + tf.matmul(mprev, params[key + "_im"])
- i = tf.nn.bias_add(i, params[key + "_i"])
- f = tf.matmul(x, params[key + "_fx"]) + tf.matmul(mprev, params[key + "_fm"])
- f = tf.nn.bias_add(f, params[key + "_f"])
- c = tf.matmul(x, params[key + "_cx"]) + tf.matmul(mprev, params[key + "_cm"])
- c = tf.nn.bias_add(c, params[key + "_c"])
- o = tf.matmul(x, params[key + "_ox"]) + tf.matmul(mprev, params[key + "_om"])
- o = tf.nn.bias_add(o, params[key + "_o"])
- i = tf.sigmoid(i, name="i_gate")
- f = tf.sigmoid(f, name="f_gate")
- o = tf.sigmoid(o, name="o_gate")
- c = f * cprev + i * tf.tanh(c)
- m = o * c
- return m, c
diff --git a/research/neural_programmer/parameters.py b/research/neural_programmer/parameters.py
deleted file mode 100644
index c576ae822b2d93c561381e27fe65afd2902b564e..0000000000000000000000000000000000000000
--- a/research/neural_programmer/parameters.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Author: aneelakantan (Arvind Neelakantan)
-"""
-
-import numpy as np
-import tensorflow as tf
-
-
-class Parameters:
-
- def __init__(self, u):
- self.utility = u
- self.init_seed_counter = 0
- self.word_init = {}
-
- def parameters(self, utility):
- params = {}
- inits = []
- embedding_dims = self.utility.FLAGS.embedding_dims
- params["unit"] = tf.Variable(
- self.RandomUniformInit([len(utility.operations_set), embedding_dims]))
- params["word"] = tf.Variable(
- self.RandomUniformInit([utility.FLAGS.vocab_size, embedding_dims]))
- params["word_match_feature_column_name"] = tf.Variable(
- self.RandomUniformInit([1]))
- params["controller"] = tf.Variable(
- self.RandomUniformInit([2 * embedding_dims, embedding_dims]))
- params["column_controller"] = tf.Variable(
- self.RandomUniformInit([2 * embedding_dims, embedding_dims]))
- params["column_controller_prev"] = tf.Variable(
- self.RandomUniformInit([embedding_dims, embedding_dims]))
- params["controller_prev"] = tf.Variable(
- self.RandomUniformInit([embedding_dims, embedding_dims]))
- global_step = tf.Variable(1, name="global_step")
- #weigths of question and history RNN (or LSTM)
- key_list = ["question_lstm"]
- for key in key_list:
- # Weights going from inputs to nodes.
- for wgts in ["ix", "fx", "cx", "ox"]:
- params[key + "_" + wgts] = tf.Variable(
- self.RandomUniformInit([embedding_dims, embedding_dims]))
- # Weights going from nodes to nodes.
- for wgts in ["im", "fm", "cm", "om"]:
- params[key + "_" + wgts] = tf.Variable(
- self.RandomUniformInit([embedding_dims, embedding_dims]))
- #Biases for the gates and cell
- for bias in ["i", "f", "c", "o"]:
- if (bias == "f"):
- print("forget gate bias")
- params[key + "_" + bias] = tf.Variable(
- tf.random_uniform([embedding_dims], 1.0, 1.1, self.utility.
- tf_data_type[self.utility.FLAGS.data_type]))
- else:
- params[key + "_" + bias] = tf.Variable(
- self.RandomUniformInit([embedding_dims]))
- params["history_recurrent"] = tf.Variable(
- self.RandomUniformInit([3 * embedding_dims, embedding_dims]))
- params["history_recurrent_bias"] = tf.Variable(
- self.RandomUniformInit([1, embedding_dims]))
- params["break_conditional"] = tf.Variable(
- self.RandomUniformInit([2 * embedding_dims, embedding_dims]))
- init = tf.global_variables_initializer()
- return params, global_step, init
-
- def RandomUniformInit(self, shape):
- """Returns a RandomUniform Tensor between -param_init and param_init."""
- param_seed = self.utility.FLAGS.param_seed
- self.init_seed_counter += 1
- return tf.random_uniform(
- shape, -1.0 *
- (np.float32(self.utility.FLAGS.param_init)
- ).astype(self.utility.np_data_type[self.utility.FLAGS.data_type]),
- (np.float32(self.utility.FLAGS.param_init)
- ).astype(self.utility.np_data_type[self.utility.FLAGS.data_type]),
- self.utility.tf_data_type[self.utility.FLAGS.data_type],
- param_seed + self.init_seed_counter)
diff --git a/research/neural_programmer/wiki_data.py b/research/neural_programmer/wiki_data.py
deleted file mode 100644
index c91637ca1ae537526ebddf4408b0fccd22d0f5e1..0000000000000000000000000000000000000000
--- a/research/neural_programmer/wiki_data.py
+++ /dev/null
@@ -1,532 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Loads the WikiQuestions dataset.
-
-An example consists of question, table. Additionally, we store the processed
-columns which store the entries after performing number, date and other
-preprocessing as done in the baseline.
-columns, column names and processed columns are split into word and number
-columns.
-lookup answer (or matrix) is also split into number and word lookup matrix
-Author: aneelakantan (Arvind Neelakantan)
-"""
-from __future__ import print_function
-
-import math
-import os
-import re
-import numpy as np
-import unicodedata as ud
-import tensorflow as tf
-
-bad_number = -200000.0 #number that is added to a corrupted table entry in a number column
-
-def is_nan_or_inf(number):
- return math.isnan(number) or math.isinf(number)
-
-def strip_accents(s):
- u = unicode(s, "utf-8")
- u_new = ''.join(c for c in ud.normalize('NFKD', u) if ud.category(c) != 'Mn')
- return u_new.encode("utf-8")
-
-
-def correct_unicode(string):
- string = strip_accents(string)
- string = re.sub("\xc2\xa0", " ", string).strip()
- string = re.sub("\xe2\x80\x93", "-", string).strip()
- #string = re.sub(ur'[\u0300-\u036F]', "", string)
- string = re.sub("‚", ",", string)
- string = re.sub("…", "...", string)
- #string = re.sub("[·・]", ".", string)
- string = re.sub("ˆ", "^", string)
- string = re.sub("˜", "~", string)
- string = re.sub("‹", "<", string)
- string = re.sub("›", ">", string)
- #string = re.sub("[‘’´`]", "'", string)
- #string = re.sub("[“â€Â«Â»]", "\"", string)
- #string = re.sub("[•†‡]", "", string)
- #string = re.sub("[â€â€‘–—]", "-", string)
- string = re.sub(r'[\u2E00-\uFFFF]', "", string)
- string = re.sub("\\s+", " ", string).strip()
- return string
-
-
-def simple_normalize(string):
- string = correct_unicode(string)
- # Citations
- string = re.sub("\[(nb ?)?\d+\]", "", string)
- string = re.sub("\*+$", "", string)
- # Year in parenthesis
- string = re.sub("\(\d* ?-? ?\d*\)", "", string)
- string = re.sub("^\"(.*)\"$", "", string)
- return string
-
-
-def full_normalize(string):
- #print "an: ", string
- string = simple_normalize(string)
- # Remove trailing info in brackets
- string = re.sub("\[[^\]]*\]", "", string)
- # Remove most unicode characters in other languages
- string = re.sub(r'[\u007F-\uFFFF]', "", string.strip())
- # Remove trailing info in parenthesis
- string = re.sub("\([^)]*\)$", "", string.strip())
- string = final_normalize(string)
- # Get rid of question marks
- string = re.sub("\?", "", string).strip()
- # Get rid of trailing colons (usually occur in column titles)
- string = re.sub("\:$", " ", string).strip()
- # Get rid of slashes
- string = re.sub(r"/", " ", string).strip()
- string = re.sub(r"\\", " ", string).strip()
- # Replace colon, slash, and dash with space
- # Note: need better replacement for this when parsing time
- string = re.sub(r"\:", " ", string).strip()
- string = re.sub("/", " ", string).strip()
- string = re.sub("-", " ", string).strip()
- # Convert empty strings to UNK
- # Important to do this last or near last
- if not string:
- string = "UNK"
- return string
-
-def final_normalize(string):
- # Remove leading and trailing whitespace
- string = re.sub("\\s+", " ", string).strip()
- # Convert entirely to lowercase
- string = string.lower()
- # Get rid of strangely escaped newline characters
- string = re.sub("\\\\n", " ", string).strip()
- # Get rid of quotation marks
- string = re.sub(r"\"", "", string).strip()
- string = re.sub(r"\'", "", string).strip()
- string = re.sub(r"`", "", string).strip()
- # Get rid of *
- string = re.sub("\*", "", string).strip()
- return string
-
-def is_number(x):
- try:
- f = float(x)
- return not is_nan_or_inf(f)
- except ValueError:
- return False
- except TypeError:
- return False
-
-
-class WikiExample(object):
-
- def __init__(self, id, question, answer, table_key):
- self.question_id = id
- self.question = question
- self.answer = answer
- self.table_key = table_key
- self.lookup_matrix = []
- self.is_bad_example = False
- self.is_word_lookup = False
- self.is_ambiguous_word_lookup = False
- self.is_number_lookup = False
- self.is_number_calc = False
- self.is_unknown_answer = False
-
-
-class TableInfo(object):
-
- def __init__(self, word_columns, word_column_names, word_column_indices,
- number_columns, number_column_names, number_column_indices,
- processed_word_columns, processed_number_columns, orig_columns):
- self.word_columns = word_columns
- self.word_column_names = word_column_names
- self.word_column_indices = word_column_indices
- self.number_columns = number_columns
- self.number_column_names = number_column_names
- self.number_column_indices = number_column_indices
- self.processed_word_columns = processed_word_columns
- self.processed_number_columns = processed_number_columns
- self.orig_columns = orig_columns
-
-
-class WikiQuestionLoader(object):
-
- def __init__(self, data_name, root_folder):
- self.root_folder = root_folder
- self.data_folder = os.path.join(self.root_folder, "data")
- self.examples = []
- self.data_name = data_name
-
- def num_questions(self):
- return len(self.examples)
-
- def load_qa(self):
- data_source = os.path.join(self.data_folder, self.data_name)
- f = tf.gfile.GFile(data_source, "r")
- id_regex = re.compile("\(id ([^\)]*)\)")
- for line in f:
- id_match = id_regex.search(line)
- id = id_match.group(1)
- self.examples.append(id)
-
- def load(self):
- self.load_qa()
-
-
-def is_date(word):
- if (not (bool(re.search("[a-z0-9]", word, re.IGNORECASE)))):
- return False
- if (len(word) != 10):
- return False
- if (word[4] != "-"):
- return False
- if (word[7] != "-"):
- return False
- for i in range(len(word)):
- if (not (word[i] == "X" or word[i] == "x" or word[i] == "-" or re.search(
- "[0-9]", word[i]))):
- return False
- return True
-
-
-class WikiQuestionGenerator(object):
-
- def __init__(self, train_name, dev_name, test_name, root_folder):
- self.train_name = train_name
- self.dev_name = dev_name
- self.test_name = test_name
- self.train_loader = WikiQuestionLoader(train_name, root_folder)
- self.dev_loader = WikiQuestionLoader(dev_name, root_folder)
- self.test_loader = WikiQuestionLoader(test_name, root_folder)
- self.bad_examples = 0
- self.root_folder = root_folder
- self.data_folder = os.path.join(self.root_folder, "annotated/data")
- self.annotated_examples = {}
- self.annotated_tables = {}
- self.annotated_word_reject = {}
- self.annotated_word_reject["-lrb-"] = 1
- self.annotated_word_reject["-rrb-"] = 1
- self.annotated_word_reject["UNK"] = 1
-
- def is_money(self, word):
- if (not (bool(re.search("[a-z0-9]", word, re.IGNORECASE)))):
- return False
- for i in range(len(word)):
- if (not (word[i] == "E" or word[i] == "." or re.search("[0-9]",
- word[i]))):
- return False
- return True
-
- def remove_consecutive(self, ner_tags, ner_values):
- for i in range(len(ner_tags)):
- if ((ner_tags[i] == "NUMBER" or ner_tags[i] == "MONEY" or
- ner_tags[i] == "PERCENT" or ner_tags[i] == "DATE") and
- i + 1 < len(ner_tags) and ner_tags[i] == ner_tags[i + 1] and
- ner_values[i] == ner_values[i + 1] and ner_values[i] != ""):
- word = ner_values[i]
- word = word.replace(">", "").replace("<", "").replace("=", "").replace(
- "%", "").replace("~", "").replace("$", "").replace("£", "").replace(
- "€", "")
- if (re.search("[A-Z]", word) and not (is_date(word)) and not (
- self.is_money(word))):
- ner_values[i] = "A"
- else:
- ner_values[i] = ","
- return ner_tags, ner_values
-
- def pre_process_sentence(self, tokens, ner_tags, ner_values):
- sentence = []
- tokens = tokens.split("|")
- ner_tags = ner_tags.split("|")
- ner_values = ner_values.split("|")
- ner_tags, ner_values = self.remove_consecutive(ner_tags, ner_values)
- #print "old: ", tokens
- for i in range(len(tokens)):
- word = tokens[i]
- if (ner_values[i] != "" and
- (ner_tags[i] == "NUMBER" or ner_tags[i] == "MONEY" or
- ner_tags[i] == "PERCENT" or ner_tags[i] == "DATE")):
- word = ner_values[i]
- word = word.replace(">", "").replace("<", "").replace("=", "").replace(
- "%", "").replace("~", "").replace("$", "").replace("£", "").replace(
- "€", "")
- if (re.search("[A-Z]", word) and not (is_date(word)) and not (
- self.is_money(word))):
- word = tokens[i]
- if (is_number(ner_values[i])):
- word = float(ner_values[i])
- elif (is_number(word)):
- word = float(word)
- if (tokens[i] == "score"):
- word = "score"
- if (is_number(word)):
- word = float(word)
- if (not (self.annotated_word_reject.has_key(word))):
- if (is_number(word) or is_date(word) or self.is_money(word)):
- sentence.append(word)
- else:
- word = full_normalize(word)
- if (not (self.annotated_word_reject.has_key(word)) and
- bool(re.search("[a-z0-9]", word, re.IGNORECASE))):
- m = re.search(",", word)
- sentence.append(word.replace(",", ""))
- if (len(sentence) == 0):
- sentence.append("UNK")
- return sentence
-
- def load_annotated_data(self, in_file):
- self.annotated_examples = {}
- self.annotated_tables = {}
- f = tf.gfile.GFile(in_file, "r")
- counter = 0
- for line in f:
- if (counter > 0):
- line = line.strip()
- (question_id, utterance, context, target_value, tokens, lemma_tokens,
- pos_tags, ner_tags, ner_values, target_canon) = line.split("\t")
- question = self.pre_process_sentence(tokens, ner_tags, ner_values)
- target_canon = target_canon.split("|")
- self.annotated_examples[question_id] = WikiExample(
- question_id, question, target_canon, context)
- self.annotated_tables[context] = []
- counter += 1
- print("Annotated examples loaded ", len(self.annotated_examples))
- f.close()
-
- def is_number_column(self, a):
- for w in a:
- if (len(w) != 1):
- return False
- if (not (is_number(w[0]))):
- return False
- return True
-
- def convert_table(self, table):
- answer = []
- for i in range(len(table)):
- temp = []
- for j in range(len(table[i])):
- temp.append(" ".join([str(w) for w in table[i][j]]))
- answer.append(temp)
- return answer
-
- def load_annotated_tables(self):
- for table in self.annotated_tables.keys():
- annotated_table = table.replace("csv", "annotated")
- orig_columns = []
- processed_columns = []
- f = tf.gfile.GFile(os.path.join(self.root_folder, annotated_table), "r")
- counter = 0
- for line in f:
- if (counter > 0):
- line = line.strip()
- line = line + "\t" * (13 - len(line.split("\t")))
- (row, col, read_id, content, tokens, lemma_tokens, pos_tags, ner_tags,
- ner_values, number, date, num2, read_list) = line.split("\t")
- counter += 1
- f.close()
- max_row = int(row)
- max_col = int(col)
- for i in range(max_col + 1):
- orig_columns.append([])
- processed_columns.append([])
- for j in range(max_row + 1):
- orig_columns[i].append(bad_number)
- processed_columns[i].append(bad_number)
- #print orig_columns
- f = tf.gfile.GFile(os.path.join(self.root_folder, annotated_table), "r")
- counter = 0
- column_names = []
- for line in f:
- if (counter > 0):
- line = line.strip()
- line = line + "\t" * (13 - len(line.split("\t")))
- (row, col, read_id, content, tokens, lemma_tokens, pos_tags, ner_tags,
- ner_values, number, date, num2, read_list) = line.split("\t")
- entry = self.pre_process_sentence(tokens, ner_tags, ner_values)
- if (row == "-1"):
- column_names.append(entry)
- else:
- orig_columns[int(col)][int(row)] = entry
- if (len(entry) == 1 and is_number(entry[0])):
- processed_columns[int(col)][int(row)] = float(entry[0])
- else:
- for single_entry in entry:
- if (is_number(single_entry)):
- processed_columns[int(col)][int(row)] = float(single_entry)
- break
- nt = ner_tags.split("|")
- nv = ner_values.split("|")
- for i_entry in range(len(tokens.split("|"))):
- if (nt[i_entry] == "DATE" and
- is_number(nv[i_entry].replace("-", "").replace("X", ""))):
- processed_columns[int(col)][int(row)] = float(nv[
- i_entry].replace("-", "").replace("X", ""))
- #processed_columns[int(col)][int(row)] = float(nv[i_entry])
- if (len(entry) == 1 and (is_number(entry[0]) or is_date(entry[0]) or
- self.is_money(entry[0]))):
- if (len(entry) == 1 and not (is_number(entry[0])) and
- is_date(entry[0])):
- entry[0] = entry[0].replace("X", "x")
- counter += 1
- word_columns = []
- processed_word_columns = []
- word_column_names = []
- word_column_indices = []
- number_columns = []
- processed_number_columns = []
- number_column_names = []
- number_column_indices = []
- for i in range(max_col + 1):
- if (self.is_number_column(orig_columns[i])):
- number_column_indices.append(i)
- number_column_names.append(column_names[i])
- temp = []
- for w in orig_columns[i]:
- if (is_number(w[0])):
- temp.append(w[0])
- number_columns.append(temp)
- processed_number_columns.append(processed_columns[i])
- else:
- word_column_indices.append(i)
- word_column_names.append(column_names[i])
- word_columns.append(orig_columns[i])
- processed_word_columns.append(processed_columns[i])
- table_info = TableInfo(
- word_columns, word_column_names, word_column_indices, number_columns,
- number_column_names, number_column_indices, processed_word_columns,
- processed_number_columns, orig_columns)
- self.annotated_tables[table] = table_info
- f.close()
-
- def answer_classification(self):
- lookup_questions = 0
- number_lookup_questions = 0
- word_lookup_questions = 0
- ambiguous_lookup_questions = 0
- number_questions = 0
- bad_questions = 0
- ice_bad_questions = 0
- tot = 0
- got = 0
- ice = {}
- with tf.gfile.GFile(
- self.root_folder + "/arvind-with-norms-2.tsv", mode="r") as f:
- lines = f.readlines()
- for line in lines:
- line = line.strip()
- if (not (self.annotated_examples.has_key(line.split("\t")[0]))):
- continue
- if (len(line.split("\t")) == 4):
- line = line + "\t" * (5 - len(line.split("\t")))
- if (not (is_number(line.split("\t")[2]))):
- ice_bad_questions += 1
- (example_id, ans_index, ans_raw, process_answer,
- matched_cells) = line.split("\t")
- if (ice.has_key(example_id)):
- ice[example_id].append(line.split("\t"))
- else:
- ice[example_id] = [line.split("\t")]
- for q_id in self.annotated_examples.keys():
- tot += 1
- example = self.annotated_examples[q_id]
- table_info = self.annotated_tables[example.table_key]
- # Figure out if the answer is numerical or lookup
- n_cols = len(table_info.orig_columns)
- n_rows = len(table_info.orig_columns[0])
- example.lookup_matrix = np.zeros((n_rows, n_cols))
- exact_matches = {}
- for (example_id, ans_index, ans_raw, process_answer,
- matched_cells) in ice[q_id]:
- for match_cell in matched_cells.split("|"):
- if (len(match_cell.split(",")) == 2):
- (row, col) = match_cell.split(",")
- row = int(row)
- col = int(col)
- if (row >= 0):
- exact_matches[ans_index] = 1
- answer_is_in_table = len(exact_matches) == len(example.answer)
- if (answer_is_in_table):
- for (example_id, ans_index, ans_raw, process_answer,
- matched_cells) in ice[q_id]:
- for match_cell in matched_cells.split("|"):
- if (len(match_cell.split(",")) == 2):
- (row, col) = match_cell.split(",")
- row = int(row)
- col = int(col)
- example.lookup_matrix[row, col] = float(ans_index) + 1.0
- example.lookup_number_answer = 0.0
- if (answer_is_in_table):
- lookup_questions += 1
- if len(example.answer) == 1 and is_number(example.answer[0]):
- example.number_answer = float(example.answer[0])
- number_lookup_questions += 1
- example.is_number_lookup = True
- else:
- #print "word lookup"
- example.calc_answer = example.number_answer = 0.0
- word_lookup_questions += 1
- example.is_word_lookup = True
- else:
- if (len(example.answer) == 1 and is_number(example.answer[0])):
- example.number_answer = example.answer[0]
- example.is_number_calc = True
- else:
- bad_questions += 1
- example.is_bad_example = True
- example.is_unknown_answer = True
- example.is_lookup = example.is_word_lookup or example.is_number_lookup
- if not example.is_word_lookup and not example.is_bad_example:
- number_questions += 1
- example.calc_answer = example.answer[0]
- example.lookup_number_answer = example.calc_answer
- # Split up the lookup matrix into word part and number part
- number_column_indices = table_info.number_column_indices
- word_column_indices = table_info.word_column_indices
- example.word_columns = table_info.word_columns
- example.number_columns = table_info.number_columns
- example.word_column_names = table_info.word_column_names
- example.processed_number_columns = table_info.processed_number_columns
- example.processed_word_columns = table_info.processed_word_columns
- example.number_column_names = table_info.number_column_names
- example.number_lookup_matrix = example.lookup_matrix[:,
- number_column_indices]
- example.word_lookup_matrix = example.lookup_matrix[:, word_column_indices]
-
- def load(self):
- train_data = []
- dev_data = []
- test_data = []
- self.load_annotated_data(
- os.path.join(self.data_folder, "training.annotated"))
- self.load_annotated_tables()
- self.answer_classification()
- self.train_loader.load()
- self.dev_loader.load()
- for i in range(self.train_loader.num_questions()):
- example = self.train_loader.examples[i]
- example = self.annotated_examples[example]
- train_data.append(example)
- for i in range(self.dev_loader.num_questions()):
- example = self.dev_loader.examples[i]
- dev_data.append(self.annotated_examples[example])
-
- self.load_annotated_data(
- os.path.join(self.data_folder, "pristine-unseen-tables.annotated"))
- self.load_annotated_tables()
- self.answer_classification()
- self.test_loader.load()
- for i in range(self.test_loader.num_questions()):
- example = self.test_loader.examples[i]
- test_data.append(self.annotated_examples[example])
- return train_data, dev_data, test_data
diff --git a/research/next_frame_prediction/README.md b/research/next_frame_prediction/README.md
deleted file mode 100644
index 9aa9b6fc5a3146a5e24ce53422d985570891d42b..0000000000000000000000000000000000000000
--- a/research/next_frame_prediction/README.md
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-
-
-Visual Dynamics: Probabilistic Future Frame Synthesis via Cross Convolutional Networks.
-
-Introduction
-
-https://arxiv.org/pdf/1607.02586v1.pdf
-
-This is an implementation based on my understanding, with small
-variations. It doesn't necessarily represents the paper published
-by the original authors.
-
-Authors: Xin Pan, Anelia Angelova
-
-Results:
-
-
-
-
-
-
-
-Prerequisite:
-
-1. Install TensorFlow (r0.12), Bazel.
-
-2. Download the Sprites dataset or generate moving object dataset.
-
-Sprites data is located here:
-
-http://www.scottreed.info/files/nips2015-analogy-data.tar.gz
-
-Convert .mat files into images and use sprites_gen.py to convert them
-to tf.SequenceExample.
-
-How to run:
-
-```shell
-$ ls -R
-.:
-data next_frame_prediction WORKSPACE
-
-./data:
-tfrecords tfrecords_test
-
-./next_frame_prediction:
-cross_conv g3doc README.md
-
-./next_frame_prediction/cross_conv:
-BUILD eval.py objects_gen.py model.py reader.py sprites_gen.py train.py
-
-./next_frame_prediction/g3doc:
-cross_conv2.png cross_conv3.png cross_conv.png
-
-
-# Build everything.
-$ bazel build -c opt next_frame_prediction/...
-
-# The following example runs the generated 2d objects.
-# For Sprites dataset, image_size should be 60, norm_scale should be 255.0.
-# Batch size is normally 16~64, depending on your memory size.
-
-# Run training.
-$ bazel-bin/next_frame_prediction/cross_conv/train \
- --batch_size=1 \
- --data_filepattern=data/tfrecords \
- --image_size=64 \
- --log_root=/tmp/predict
-
-step: 1, loss: 24.428671
-step: 2, loss: 19.211605
-step: 3, loss: 5.543143
-step: 4, loss: 3.035339
-step: 5, loss: 1.771392
-step: 6, loss: 2.099824
-step: 7, loss: 1.747665
-step: 8, loss: 1.572436
-step: 9, loss: 1.586816
-step: 10, loss: 1.434191
-
-# Run eval.
-$ bazel-bin/next_frame_prediction/cross_conv/eval \
- --batch_size=1 \
- --data_filepattern=data/tfrecords_test \
- --image_size=64 \
- --log_root=/tmp/predict
-```
diff --git a/research/next_frame_prediction/cross_conv/BUILD b/research/next_frame_prediction/cross_conv/BUILD
deleted file mode 100644
index b435087f34f6ffbeba016119c60724d8ac3eb180..0000000000000000000000000000000000000000
--- a/research/next_frame_prediction/cross_conv/BUILD
+++ /dev/null
@@ -1,48 +0,0 @@
-licenses(["notice"]) # Apache 2.0
-
-package_group(
- name = "internal",
- packages = [
- "//next_frame_prediction/...",
- ],
-)
-
-package(default_visibility = [":internal"])
-
-py_library(
- name = "model",
- srcs = ["model.py"],
-)
-
-py_library(
- name = "reader",
- srcs = ["reader.py"],
-)
-
-py_binary(
- name = "train",
- srcs = ["train.py"],
- deps = [
- ":model",
- ":reader",
- ],
-)
-
-py_binary(
- name = "eval",
- srcs = ["eval.py"],
- deps = [
- ":model",
- ":reader",
- ],
-)
-
-py_binary(
- name = "example_gen",
- srcs = ["example_gen.py"],
-)
-
-py_binary(
- name = "sprites_gen",
- srcs = ["sprites_gen.py"],
-)
diff --git a/research/next_frame_prediction/cross_conv/eval.py b/research/next_frame_prediction/cross_conv/eval.py
deleted file mode 100644
index 17ebc0e0edd2911f828cbb145ee40a06db8795b5..0000000000000000000000000000000000000000
--- a/research/next_frame_prediction/cross_conv/eval.py
+++ /dev/null
@@ -1,119 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Eval Cross Convolutional Model."""
-import io
-import os
-import sys
-import time
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-import model as cross_conv_model
-import reader
-
-FLAGS = tf.flags.FLAGS
-tf.flags.DEFINE_string('log_root', '/tmp/moving_obj', 'The root dir of output.')
-tf.flags.DEFINE_string('data_filepattern',
- 'est',
- 'training data file pattern.')
-tf.flags.DEFINE_integer('batch_size', 1, 'Batch size.')
-tf.flags.DEFINE_integer('image_size', 64, 'Image height and width.')
-tf.flags.DEFINE_float('norm_scale', 1.0, 'Normalize the original image')
-tf.flags.DEFINE_float('scale', 10.0,
- 'Scale the image after norm_scale and move the diff '
- 'to the positive realm.')
-tf.flags.DEFINE_integer('sequence_length', 2, 'tf.SequenceExample length.')
-tf.flags.DEFINE_integer('eval_batch_count', 100,
- 'Average the result this number of examples.')
-tf.flags.DEFINE_bool('l2_loss', True, 'If true, include l2_loss.')
-tf.flags.DEFINE_bool('reconstr_loss', False, 'If true, include reconstr_loss.')
-tf.flags.DEFINE_bool('kl_loss', True, 'If true, include KL loss.')
-
-slim = tf.contrib.slim
-
-
-def _Eval():
- params = dict()
- params['batch_size'] = FLAGS.batch_size
- params['seq_len'] = FLAGS.sequence_length
- params['image_size'] = FLAGS.image_size
- params['is_training'] = False
- params['norm_scale'] = FLAGS.norm_scale
- params['scale'] = FLAGS.scale
- params['l2_loss'] = FLAGS.l2_loss
- params['reconstr_loss'] = FLAGS.reconstr_loss
- params['kl_loss'] = FLAGS.kl_loss
-
- eval_dir = os.path.join(FLAGS.log_root, 'eval')
-
- images = reader.ReadInput(
- FLAGS.data_filepattern, shuffle=False, params=params)
- images *= params['scale']
- # Increase the value makes training much faster.
- image_diff_list = reader.SequenceToImageAndDiff(images)
- model = cross_conv_model.CrossConvModel(image_diff_list, params)
- model.Build()
-
- summary_writer = tf.summary.FileWriter(eval_dir)
- saver = tf.train.Saver()
- sess = tf.Session('', config=tf.ConfigProto(allow_soft_placement=True))
- tf.train.start_queue_runners(sess)
-
- while True:
- time.sleep(60)
- try:
- ckpt_state = tf.train.get_checkpoint_state(FLAGS.log_root)
- except tf.errors.OutOfRangeError as e:
- sys.stderr.write('Cannot restore checkpoint: %s\n' % e)
- continue
- if not (ckpt_state and ckpt_state.model_checkpoint_path):
- sys.stderr.write('No model to eval yet at %s\n' % FLAGS.log_root)
- continue
- sys.stderr.write('Loading checkpoint %s\n' %
- ckpt_state.model_checkpoint_path)
- saver.restore(sess, ckpt_state.model_checkpoint_path)
- # Use the empirical distribution of z from training set.
- if not tf.gfile.Exists(os.path.join(FLAGS.log_root, 'z_mean.npy')):
- sys.stderr.write('No z at %s\n' % FLAGS.log_root)
- continue
-
- with tf.gfile.Open(os.path.join(FLAGS.log_root, 'z_mean.npy')) as f:
- sample_z_mean = np.load(io.BytesIO(f.read()))
- with tf.gfile.Open(
- os.path.join(FLAGS.log_root, 'z_stddev_log.npy')) as f:
- sample_z_stddev_log = np.load(io.BytesIO(f.read()))
-
- total_loss = 0.0
- for _ in xrange(FLAGS.eval_batch_count):
- loss_val, total_steps, summaries = sess.run(
- [model.loss, model.global_step, model.summary_op],
- feed_dict={model.z_mean: sample_z_mean,
- model.z_stddev_log: sample_z_stddev_log})
- total_loss += loss_val
-
- summary_writer.add_summary(summaries, total_steps)
- sys.stderr.write('steps: %d, loss: %f\n' %
- (total_steps, total_loss / FLAGS.eval_batch_count))
-
-
-def main(_):
- _Eval()
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/next_frame_prediction/cross_conv/example_gen.py b/research/next_frame_prediction/cross_conv/example_gen.py
deleted file mode 100644
index bcda0bc405a60c3116e8c488cae92f502720fec4..0000000000000000000000000000000000000000
--- a/research/next_frame_prediction/cross_conv/example_gen.py
+++ /dev/null
@@ -1,93 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Generate examples of two objects moving in different directions."""
-import random
-import sys
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-
-tf.flags.DEFINE_string('out_file', '',
- 'Output file for the tfrecords.')
-
-
-def _add_object(obj_type, image, image2, xpos, ypos):
- """Add a moving obj to two consecutive images."""
- obj_size = random.randint(8, 10)
- channel = random.randint(0, 2)
- move = random.randint(6, 10)
-
- obj = np.zeros([obj_size, obj_size, 3])
- if obj_type == 'rectangle':
- xpos2 = xpos + move
- ypos2 = ypos
- for i in xrange(obj_size):
- obj[i, 0:i+1, channel] = [1.0 for _ in xrange(i+1)]
- elif obj_type == 'square':
- xpos2 = xpos
- ypos2 = ypos + move
- obj[:, :, channel] = 1.0
-
- for x in xrange(obj_size):
- for y in xrange(obj_size):
- if obj[x, y, channel] == 1.0:
- image[xpos+x, ypos+y, channel] = 1.0
- image2[xpos2+x, ypos2+y, channel] = 1.0
-
-
-def _images_to_example(image, image2):
- """Convert two consecutive images to SequenceExample."""
- example = tf.SequenceExample()
- feature_list = example.feature_lists.feature_list['moving_objs']
- feature = feature_list.feature.add()
- feature.float_list.value.extend(np.reshape(image, [-1]).tolist())
- feature = feature_list.feature.add()
- feature.float_list.value.extend(np.reshape(image2, [-1]).tolist())
- return example
-
-
-def generate_input():
- """Generate tfrecords."""
- writer = tf.python_io.TFRecordWriter(tf.flags.FLAGS.out_file)
- writer2 = tf.python_io.TFRecordWriter(tf.flags.FLAGS.out_file + '_test')
-
- examples = []
- for xpos in xrange(0, 40, 3):
- for ypos in xrange(0, 40, 3):
- for xpos2 in xrange(0, 40, 3):
- for ypos2 in xrange(0, 40, 3):
- image = np.zeros([64, 64, 3])
- image2 = np.zeros([64, 64, 3])
- _add_object('rectangle', image, image2, xpos, ypos)
- _add_object('square', image, image2, xpos2, ypos2)
- examples.append(_images_to_example(image, image2))
-
- sys.stderr.write('Finish generating examples.\n')
- random.shuffle(examples)
- for count, ex in enumerate(examples):
- if count % 10 == 0:
- writer2.write(ex.SerializeToString())
- else:
- writer.write(ex.SerializeToString())
-
-def main(_):
- generate_input()
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/next_frame_prediction/cross_conv/model.py b/research/next_frame_prediction/cross_conv/model.py
deleted file mode 100644
index 7b48e446e18b70fec87142f6834f33332287d02e..0000000000000000000000000000000000000000
--- a/research/next_frame_prediction/cross_conv/model.py
+++ /dev/null
@@ -1,233 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Cross Convolutional Model.
-
-https://arxiv.org/pdf/1607.02586v1.pdf
-"""
-import math
-import sys
-
-from six.moves import xrange
-import tensorflow as tf
-
-slim = tf.contrib.slim
-
-
-class CrossConvModel(object):
-
- def __init__(self, image_diff_list, params):
- """Constructor.
-
- Args:
- image_diff_list: A list of (image, diff) tuples, with shape
- [batch_size, image_size, image_size, 3] and image_sizes as
- [32, 64, 128, 256].
- params: Dict of parameters.
- """
- self.images = [i for (i, _) in image_diff_list]
- # Move the diff to the positive realm.
- self.diffs = [(d + params['scale']) / 2 for (i, d) in image_diff_list]
- self.params = params
-
- def Build(self):
- with tf.device('/gpu:0'):
- with slim.arg_scope([slim.conv2d],
- activation_fn=tf.nn.relu,
- normalizer_fn=slim.batch_norm,
- normalizer_params={'is_training':
- self.params['is_training']}):
- self._BuildMotionKernel()
- encoded_images = self._BuildImageEncoder()
- cross_conved_images = self._CrossConv(encoded_images)
- self._BuildImageDecoder(cross_conved_images)
- self._BuildLoss()
-
- image = self.images[1]
- diff = self.diffs[1]
-
- self.global_step = tf.Variable(0, name='global_step', trainable=False)
-
- if self.params['is_training']:
- self._BuildTrainOp()
-
- diff = diff * 2.0 - self.params['scale']
- diff_output = self.diff_output * 2.0 - self.params['scale']
- concat_image = tf.concat(
- axis=1, values=[image, image + diff_output, image + diff, diff_output])
- tf.summary.image('origin_predict_expect_predictdiff', concat_image)
- self.summary_op = tf.summary.merge_all()
- return self.loss
-
- def _BuildTrainOp(self):
- lrn_rate = tf.maximum(
- 0.01, # min_lr_rate.
- tf.train.exponential_decay(
- self.params['learning_rate'], self.global_step, 10000, 0.5))
- tf.summary.scalar('learning rate', lrn_rate)
- optimizer = tf.train.GradientDescentOptimizer(lrn_rate)
- self.train_op = slim.learning.create_train_op(
- self.loss, optimizer, global_step=self.global_step)
-
- def _BuildLoss(self):
- # 1. reconstr_loss seems doesn't do better than l2 loss.
- # 2. Only works when using reduce_mean. reduce_sum doesn't work.
- # 3. It seems kl loss doesn't play an important role.
- self.loss = 0
- with tf.variable_scope('loss'):
- if self.params['l2_loss']:
- l2_loss = tf.reduce_mean(tf.square(self.diff_output - self.diffs[1]))
- tf.summary.scalar('l2_loss', l2_loss)
- self.loss += l2_loss
- if self.params['reconstr_loss']:
- reconstr_loss = (-tf.reduce_mean(
- self.diffs[1] * (1e-10 + self.diff_output) +
- (1-self.diffs[1]) * tf.log(1e-10 + 1 - self.diff_output)))
- reconstr_loss = tf.check_numerics(reconstr_loss, 'reconstr_loss')
- tf.summary.scalar('reconstr_loss', reconstr_loss)
- self.loss += reconstr_loss
- if self.params['kl_loss']:
- kl_loss = (0.5 * tf.reduce_mean(
- tf.square(self.z_mean) + tf.square(self.z_stddev) -
- 2 * self.z_stddev_log - 1))
- tf.summary.scalar('kl_loss', kl_loss)
- self.loss += kl_loss
-
- tf.summary.scalar('loss', self.loss)
-
- def _BuildMotionKernel(self):
- image = self.images[-2]
- diff = self.diffs[-2]
- shape = image.get_shape().as_list()
- assert shape[1] == shape[2] and shape[1] == 128
- batch_size = shape[0]
-
- net = tf.concat(axis=3, values=[image, diff])
- with tf.variable_scope('motion_encoder'):
- with slim.arg_scope([slim.conv2d], padding='VALID'):
- net = slim.conv2d(net, 96, [5, 5], stride=1)
- net = slim.max_pool2d(net, [2, 2])
- net = slim.conv2d(net, 96, [5, 5], stride=1)
- net = slim.max_pool2d(net, [2, 2])
- net = slim.conv2d(net, 128, [5, 5], stride=1)
- net = slim.conv2d(net, 128, [5, 5], stride=1)
- net = slim.max_pool2d(net, [2, 2])
- net = slim.conv2d(net, 256, [4, 4], stride=1)
- net = slim.conv2d(net, 256, [3, 3], stride=1)
-
- z = tf.reshape(net, shape=[batch_size, -1])
- self.z_mean, self.z_stddev_log = tf.split(
- axis=1, num_or_size_splits=2, value=z)
- self.z_stddev = tf.exp(self.z_stddev_log)
-
- epsilon = tf.random_normal(
- self.z_mean.get_shape().as_list(), 0, 1, dtype=tf.float32)
- kernel = self.z_mean + tf.multiply(self.z_stddev, epsilon)
-
- width = int(math.sqrt(kernel.get_shape().as_list()[1] // 128))
- kernel = tf.reshape(kernel, [batch_size, width, width, 128])
- with tf.variable_scope('kernel_decoder'):
- with slim.arg_scope([slim.conv2d], padding='SAME'):
- kernel = slim.conv2d(kernel, 128, [5, 5], stride=1)
- self.kernel = slim.conv2d(kernel, 128, [5, 5], stride=1)
-
- sys.stderr.write('kernel shape: %s\n' % kernel.get_shape())
-
- def _BuildImageEncoder(self):
- feature_maps = []
- for (i, image) in enumerate(self.images):
- with tf.variable_scope('image_encoder_%d' % i):
- with slim.arg_scope([slim.conv2d, slim.max_pool2d], padding='SAME'):
- net = slim.conv2d(image, 64, [5, 5], stride=1)
- net = slim.conv2d(net, 64, [5, 5], stride=1)
- net = slim.max_pool2d(net, [5, 5])
- net = slim.conv2d(net, 64, [5, 5], stride=1)
- net = slim.conv2d(net, 32, [5, 5], stride=1)
- net = slim.max_pool2d(net, [2, 2])
- sys.stderr.write('image_conv shape: %s\n' % net.get_shape())
- feature_maps.append(net)
- return feature_maps
-
- def _CrossConvHelper(self, encoded_image, kernel):
- """Cross Convolution.
-
- The encoded image and kernel are of the same shape. Namely
- [batch_size, image_size, image_size, channels]. They are split
- into [image_size, image_size] image squares [kernel_size, kernel_size]
- kernel squares. kernel squares are used to convolute image squares.
- """
- images = tf.expand_dims(encoded_image, 0)
- kernels = tf.expand_dims(kernel, 3)
- return tf.nn.depthwise_conv2d(images, kernels, [1, 1, 1, 1], 'SAME')
-
- def _CrossConv(self, encoded_images):
- """Apply the motion kernel on the encoded_images."""
- cross_conved_images = []
- kernels = tf.split(axis=3, num_or_size_splits=4, value=self.kernel)
- for (i, encoded_image) in enumerate(encoded_images):
- with tf.variable_scope('cross_conv_%d' % i):
- kernel = kernels[i]
-
- encoded_image = tf.unstack(encoded_image, axis=0)
- kernel = tf.unstack(kernel, axis=0)
- assert len(encoded_image) == len(kernel)
- assert len(encoded_image) == self.params['batch_size']
- conved_image = []
- for j in xrange(len(encoded_image)):
- conved_image.append(self._CrossConvHelper(
- encoded_image[j], kernel[j]))
- cross_conved_images.append(tf.concat(axis=0, values=conved_image))
- sys.stderr.write('cross_conved shape: %s\n' %
- cross_conved_images[-1].get_shape())
- return cross_conved_images
-
- def _Deconv(self, net, out_filters, kernel_size, stride):
- shape = net.get_shape().as_list()
- in_filters = shape[3]
- kernel_shape = [kernel_size, kernel_size, out_filters, in_filters]
-
- weights = tf.get_variable(
- name='weights',
- shape=kernel_shape,
- dtype=tf.float32,
- initializer=tf.truncated_normal_initializer(stddev=0.01))
-
-
- out_height = shape[1] * stride
- out_width = shape[2] * stride
- batch_size = shape[0]
-
- output_shape = [batch_size, out_height, out_width, out_filters]
- net = tf.nn.conv2d_transpose(net, weights, output_shape,
- [1, stride, stride, 1], padding='SAME')
- slim.batch_norm(net)
- return net
-
- def _BuildImageDecoder(self, cross_conved_images):
- """Decode the cross_conved feature maps into the predicted images."""
- nets = []
- for i, cross_conved_image in enumerate(cross_conved_images):
- with tf.variable_scope('image_decoder_%d' % i):
- stride = 64 / cross_conved_image.get_shape().as_list()[1]
- # TODO(xpan): Alternative solution for upsampling?
- nets.append(self._Deconv(
- cross_conved_image, 64, kernel_size=3, stride=stride))
-
- net = tf.concat(axis=3, values=nets)
- net = slim.conv2d(net, 128, [9, 9], padding='SAME', stride=1)
- net = slim.conv2d(net, 128, [1, 1], padding='SAME', stride=1)
- net = slim.conv2d(net, 3, [1, 1], padding='SAME', stride=1)
- self.diff_output = net
- sys.stderr.write('diff_output shape: %s\n' % self.diff_output.get_shape())
diff --git a/research/next_frame_prediction/cross_conv/reader.py b/research/next_frame_prediction/cross_conv/reader.py
deleted file mode 100644
index ab4ab698dda938f182be0019168aa132c1e3c5af..0000000000000000000000000000000000000000
--- a/research/next_frame_prediction/cross_conv/reader.py
+++ /dev/null
@@ -1,86 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Read image sequence."""
-
-from six.moves import xrange
-import tensorflow as tf
-
-
-def SequenceToImageAndDiff(images):
- """Convert image sequence batch into image and diff batch.
-
- Each image pair is converted to the first image and their diff.
- Batch size will increase if sequence length is larger than 2.
-
- Args:
- images: Image sequence with shape
- [batch_size, seq_len, image_size, image_size, channel]
-
- Returns:
- the list of (image, diff) tuples with shape
- [batch_size2, image_size, image_size, channel]. image_sizes are
- [32, 64, 128, 256].
- """
- image_diff_list = []
- image_seq = tf.unstack(images, axis=1)
- for size in [32, 64, 128, 256]:
- resized_images = [
- tf.image.resize_images(i, [size, size]) for i in image_seq]
- diffs = []
- for i in xrange(0, len(resized_images)-1):
- diffs.append(resized_images[i+1] - resized_images[i])
- image_diff_list.append(
- (tf.concat(axis=0, values=resized_images[:-1]), tf.concat(axis=0, values=diffs)))
- return image_diff_list
-
-
-def ReadInput(data_filepattern, shuffle, params):
- """Read the tf.SequenceExample tfrecord files.
-
- Args:
- data_filepattern: tf.SequenceExample tfrecord filepattern.
- shuffle: Whether to shuffle the examples.
- params: parameter dict.
-
- Returns:
- image sequence batch [batch_size, seq_len, image_size, image_size, channel].
- """
- image_size = params['image_size']
- filenames = tf.gfile.Glob(data_filepattern)
- filename_queue = tf.train.string_input_producer(filenames, shuffle=shuffle)
- reader = tf.TFRecordReader()
- _, example = reader.read(filename_queue)
- feature_sepc = {
- 'moving_objs': tf.FixedLenSequenceFeature(
- shape=[image_size * image_size * 3], dtype=tf.float32)}
- _, features = tf.parse_single_sequence_example(
- example, sequence_features=feature_sepc)
- moving_objs = tf.reshape(
- features['moving_objs'], [params['seq_len'], image_size, image_size, 3])
- if shuffle:
- examples = tf.train.shuffle_batch(
- [moving_objs],
- batch_size=params['batch_size'],
- num_threads=64,
- capacity=params['batch_size'] * 100,
- min_after_dequeue=params['batch_size'] * 4)
- else:
- examples = tf.train.batch([moving_objs],
- batch_size=params['batch_size'],
- num_threads=16,
- capacity=params['batch_size'])
- examples /= params['norm_scale']
- return examples
diff --git a/research/next_frame_prediction/cross_conv/sprites_gen.py b/research/next_frame_prediction/cross_conv/sprites_gen.py
deleted file mode 100644
index 0d36c255cd93a90797272d7a80389f16fc6f3702..0000000000000000000000000000000000000000
--- a/research/next_frame_prediction/cross_conv/sprites_gen.py
+++ /dev/null
@@ -1,98 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Generate the sprites tfrecords from raw_images."""
-import os
-import random
-import re
-import sys
-
-import numpy as np
-import scipy.misc
-from six.moves import xrange
-import tensorflow as tf
-
-
-tf.flags.DEFINE_string('data_filepattern', '', 'The raw images.')
-tf.flags.DEFINE_string('out_file', '',
- 'File name for the tfrecord output.')
-
-
-def _read_images():
- """Read images from image files into data structure."""
- sprites = dict()
- files = tf.gfile.Glob(tf.flags.FLAGS.data_filepattern)
- for f in files:
- image = scipy.misc.imread(f)
- m = re.search('image_([0-9]+)_([0-9]+)_([0-9]+).jpg', os.path.basename(f))
- if m.group(1) not in sprites:
- sprites[m.group(1)] = dict()
- character = sprites[m.group(1)]
- if m.group(2) not in character:
- character[m.group(2)] = dict()
- pose = character[m.group(2)]
- pose[int(m.group(3))] = image
- return sprites
-
-
-def _images_to_example(image, image2):
- """Convert 2 consecutive image to a SequenceExample."""
- example = tf.SequenceExample()
- feature_list = example.feature_lists.feature_list['moving_objs']
- feature = feature_list.feature.add()
- feature.float_list.value.extend(np.reshape(image, [-1]).tolist())
- feature = feature_list.feature.add()
- feature.float_list.value.extend(np.reshape(image2, [-1]).tolist())
- return example
-
-
-def generate_input():
- """Generate tfrecords."""
- sprites = _read_images()
- sys.stderr.write('Finish reading images.\n')
- train_writer = tf.python_io.TFRecordWriter(
- tf.flags.FLAGS.out_file.replace('sprites', 'sprites_train'))
- test_writer = tf.python_io.TFRecordWriter(
- tf.flags.FLAGS.out_file.replace('sprites', 'sprites_test'))
-
- train_examples = []
- test_examples = []
- for i in sprites:
- if int(i) < 24:
- examples = test_examples
- else:
- examples = train_examples
-
- character = sprites[i]
- for j in character.keys():
- pose = character[j]
- for k in xrange(1, len(pose), 1):
- image = pose[k]
- image2 = pose[k+1]
- examples.append(_images_to_example(image, image2))
-
- sys.stderr.write('Finish generating examples: %d, %d.\n' %
- (len(train_examples), len(test_examples)))
- random.shuffle(train_examples)
- _ = [train_writer.write(ex.SerializeToString()) for ex in train_examples]
- _ = [test_writer.write(ex.SerializeToString()) for ex in test_examples]
-
-
-def main(_):
- generate_input()
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/next_frame_prediction/cross_conv/train.py b/research/next_frame_prediction/cross_conv/train.py
deleted file mode 100644
index 5b9973f52cc3946b3396c1e0b87fda19901735f6..0000000000000000000000000000000000000000
--- a/research/next_frame_prediction/cross_conv/train.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# Copyright 2016 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Train the cross convolutional model."""
-import os
-import sys
-
-import numpy as np
-import tensorflow as tf
-
-import model as cross_conv_model
-import reader
-
-FLAGS = tf.flags.FLAGS
-tf.flags.DEFINE_string('master', '', 'Session address.')
-tf.flags.DEFINE_string('log_root', '/tmp/moving_obj', 'The root dir of output.')
-tf.flags.DEFINE_string('data_filepattern', '',
- 'training data file pattern.')
-tf.flags.DEFINE_integer('image_size', 64, 'Image height and width.')
-tf.flags.DEFINE_integer('batch_size', 1, 'Batch size.')
-tf.flags.DEFINE_float('norm_scale', 1.0, 'Normalize the original image')
-tf.flags.DEFINE_float('scale', 10.0,
- 'Scale the image after norm_scale and move the diff '
- 'to the positive realm.')
-tf.flags.DEFINE_integer('sequence_length', 2, 'tf.SequenceExample length.')
-tf.flags.DEFINE_float('learning_rate', 0.8, 'Learning rate.')
-tf.flags.DEFINE_bool('l2_loss', True, 'If true, include l2_loss.')
-tf.flags.DEFINE_bool('reconstr_loss', False, 'If true, include reconstr_loss.')
-tf.flags.DEFINE_bool('kl_loss', True, 'If true, include KL loss.')
-
-slim = tf.contrib.slim
-
-
-def _Train():
- params = dict()
- params['batch_size'] = FLAGS.batch_size
- params['seq_len'] = FLAGS.sequence_length
- params['image_size'] = FLAGS.image_size
- params['is_training'] = True
- params['norm_scale'] = FLAGS.norm_scale
- params['scale'] = FLAGS.scale
- params['learning_rate'] = FLAGS.learning_rate
- params['l2_loss'] = FLAGS.l2_loss
- params['reconstr_loss'] = FLAGS.reconstr_loss
- params['kl_loss'] = FLAGS.kl_loss
-
- train_dir = os.path.join(FLAGS.log_root, 'train')
-
- images = reader.ReadInput(FLAGS.data_filepattern, shuffle=True, params=params)
- images *= params['scale']
- # Increase the value makes training much faster.
- image_diff_list = reader.SequenceToImageAndDiff(images)
- model = cross_conv_model.CrossConvModel(image_diff_list, params)
- model.Build()
- tf.contrib.tfprof.model_analyzer.print_model_analysis(tf.get_default_graph())
-
- summary_writer = tf.summary.FileWriter(train_dir)
- sv = tf.train.Supervisor(logdir=FLAGS.log_root,
- summary_op=None,
- is_chief=True,
- save_model_secs=60,
- global_step=model.global_step)
- sess = sv.prepare_or_wait_for_session(
- FLAGS.master, config=tf.ConfigProto(allow_soft_placement=True))
-
- total_loss = 0.0
- step = 0
- sample_z_mean = np.zeros(model.z_mean.get_shape().as_list())
- sample_z_stddev_log = np.zeros(model.z_stddev_log.get_shape().as_list())
- sample_step = 0
-
- while True:
- _, loss_val, total_steps, summaries, z_mean, z_stddev_log = sess.run(
- [model.train_op, model.loss, model.global_step,
- model.summary_op,
- model.z_mean, model.z_stddev_log])
-
- sample_z_mean += z_mean
- sample_z_stddev_log += z_stddev_log
- total_loss += loss_val
- step += 1
- sample_step += 1
-
- if step % 100 == 0:
- summary_writer.add_summary(summaries, total_steps)
- sys.stderr.write('step: %d, loss: %f\n' %
- (total_steps, total_loss / step))
- total_loss = 0.0
- step = 0
-
- # Sampled z is used for eval.
- # It seems 10k is better than 1k. Maybe try 100k next?
- if sample_step % 10000 == 0:
- with tf.gfile.Open(os.path.join(FLAGS.log_root, 'z_mean.npy'), 'w') as f:
- np.save(f, sample_z_mean / sample_step)
- with tf.gfile.Open(
- os.path.join(FLAGS.log_root, 'z_stddev_log.npy'), 'w') as f:
- np.save(f, sample_z_stddev_log / sample_step)
- sample_z_mean = np.zeros(model.z_mean.get_shape().as_list())
- sample_z_stddev_log = np.zeros(
- model.z_stddev_log.get_shape().as_list())
- sample_step = 0
-
-
-def main(_):
- _Train()
-
-
-if __name__ == '__main__':
- tf.app.run()
diff --git a/research/next_frame_prediction/g3doc/cross_conv.png b/research/next_frame_prediction/g3doc/cross_conv.png
deleted file mode 100644
index 13915f944188adf0b0a3dc85219fce7bcb5e7de9..0000000000000000000000000000000000000000
Binary files a/research/next_frame_prediction/g3doc/cross_conv.png and /dev/null differ
diff --git a/research/next_frame_prediction/g3doc/cross_conv2.png b/research/next_frame_prediction/g3doc/cross_conv2.png
deleted file mode 100644
index c4b5e8e9d6169a1a908858a91fdc6467ae03ea2a..0000000000000000000000000000000000000000
Binary files a/research/next_frame_prediction/g3doc/cross_conv2.png and /dev/null differ
diff --git a/research/next_frame_prediction/g3doc/cross_conv3.png b/research/next_frame_prediction/g3doc/cross_conv3.png
deleted file mode 100644
index 054d7d1edf2043c50a3ea8d332cc83a8dcb32c9b..0000000000000000000000000000000000000000
Binary files a/research/next_frame_prediction/g3doc/cross_conv3.png and /dev/null differ
diff --git a/research/ptn/.gitignore b/research/ptn/.gitignore
deleted file mode 100644
index 8479374e96149a2e772046da042820dae34ba305..0000000000000000000000000000000000000000
--- a/research/ptn/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-bazel
-.idea
-bazel-bin
-bazel-out
-bazel-genfiles
-bazel-ptn
-bazel-testlogs
-*.pyc
diff --git a/research/ptn/BUILD b/research/ptn/BUILD
deleted file mode 100644
index f08c6172c4e899de77d3c10dc8e9d61519e750a8..0000000000000000000000000000000000000000
--- a/research/ptn/BUILD
+++ /dev/null
@@ -1,94 +0,0 @@
-py_library(
- name = "input_generator",
- srcs = ["input_generator.py"],
- deps = [
- ],
-)
-
-py_library(
- name = "losses",
- srcs = ["losses.py"],
- deps = [
- ],
-)
-
-py_library(
- name = "metrics",
- srcs = ["metrics.py"],
- deps = [
- ],
-)
-
-py_library(
- name = "utils",
- srcs = ["utils.py"],
- deps = [
- ],
-)
-
-# Defines the Rotator model here
-py_library(
- name = "model_rotator",
- srcs = ["model_rotator.py"],
- deps = [
- ":input_generator",
- ":losses",
- ":metrics",
- ":utils",
- "//nets:deeprotator_factory",
- ],
-)
-
-# Defines the Im2vox model here
-py_library(
- name = "model_voxel_generation",
- srcs = ["model_voxel_generation.py"],
- deps = [
- ":input_generator",
- "//nets:im2vox_factory",
- ],
-)
-
-py_library(
- name = "model_ptn",
- srcs = ["model_ptn.py"],
- deps = [
- ":losses",
- ":metrics",
- ":model_voxel_generation",
- ":utils",
- "//nets:im2vox_factory",
- ],
-)
-
-py_binary(
- name = "train_ptn",
- srcs = ["train_ptn.py"],
- deps = [
- ":model_ptn",
- ],
-)
-
-py_binary(
- name = "eval_ptn",
- srcs = ["eval_ptn.py"],
- deps = [
- ":model_ptn",
- ],
-)
-
-py_binary(
- name = "pretrain_rotator",
- srcs = ["pretrain_rotator.py"],
- deps = [
- ":model_rotator",
- ],
-)
-
-py_binary(
- name = "eval_rotator",
- srcs = ["eval_rotator.py"],
- deps = [
- ":model_rotator",
- ],
-)
diff --git a/research/ptn/README.md b/research/ptn/README.md
deleted file mode 100644
index e9558cd097f7c5f8dd30321222d777172cf5276d..0000000000000000000000000000000000000000
--- a/research/ptn/README.md
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-
-
-# Perspective Transformer Nets
-
-## Introduction
-This is the TensorFlow implementation for the NIPS 2016 work ["Perspective Transformer Nets: Learning Single-View 3D Object Reconstrution without 3D Supervision"](https://papers.nips.cc/paper/6206-perspective-transformer-nets-learning-single-view-3d-object-reconstruction-without-3d-supervision.pdf)
-
-Re-implemented by Xinchen Yan, Arkanath Pathak, Jasmine Hsu, Honglak Lee
-
-Reference: [Orginal implementation in Torch](https://github.com/xcyan/nips16_PTN)
-
-## How to run this code
-
-This implementation is ready to be run locally or ["distributed across multiple machines/tasks"](https://www.tensorflow.org/deploy/distributed).
-You will need to set the task number flag for each task when running in a distributed fashion.
-Please refer to the original paper for parameter explanations and training details.
-
-### Installation
-* TensorFlow
- * This code requires the latest open-source TensorFlow that you will need to build manually.
- The [documentation](https://www.tensorflow.org/install/install_sources) provides the steps required for that.
-* Bazel
- * Follow the instructions [here](http://bazel.build/docs/install.html).
- * Alternately, Download bazel from
- [https://github.com/bazelbuild/bazel/releases](https://github.com/bazelbuild/bazel/releases)
- for your system configuration.
- * Check for the bazel version using this command: bazel version
-* matplotlib
- * Follow the instructions [here](https://matplotlib.org/users/installing.html).
- * You can use a package repository like pip.
-* scikit-image
- * Follow the instructions [here](http://scikit-image.org/docs/dev/install.html).
- * You can use a package repository like pip.
-* PIL
- * Install from [here](https://pypi.python.org/pypi/Pillow/2.2.1).
-
-### Dataset
-
-This code requires the dataset to be in *tfrecords* format with the following features:
-* image
- * Flattened list of image (float representations) for each view point.
-* mask
- * Flattened list of image masks (float representations) for each view point.
-* vox
- * Flattened list of voxels (float representations) for the object.
- * This is needed for using vox loss and for prediction comparison.
-
-You can download the ShapeNet Dataset in tfrecords format from [here](https://drive.google.com/file/d/0B12XukcbU7T7OHQ4MGh6d25qQlk)*.
-
-* Disclaimer: This data is hosted personally by Arkanath Pathak for non-commercial research purposes. Please cite the [ShapeNet paper](https://arxiv.org/pdf/1512.03012.pdf) in your works when using ShapeNet for non-commercial research purposes.
-
-### Pretraining: pretrain_rotator.py for each RNN step
-$ bazel run -c opt :pretrain_rotator -- --step_size={} --init_model={}
-
-Pass the init_model as the checkpoint path for the last step trained model.
-You'll also need to set the inp_dir flag to where your data resides.
-
-### Training: train_ptn.py with last pretrained model.
-$ bazel run -c opt :train_ptn -- --init_model={}
-
-### Example TensorBoard Visualizations
-
-To compare the visualizations make sure to set the model_name flag different for each parametric setting:
-
-This code adds summaries for each loss. For instance, these are the losses we encountered in the distributed pretraining for ShapeNet Chair Dataset with 10 workers and 16 parameter servers:
-
-
-You can expect such images after fine tuning the training as "grid_vis" under **Image** summaries in TensorBoard:
-
-Here the third and fifth columns are the predicted masks and voxels respectively, alongside their ground truth values.
-
-A similar image for when trained on all ShapeNet Categories (Voxel visualizations might be skewed):
-
diff --git a/research/ptn/WORKSPACE b/research/ptn/WORKSPACE
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/ptn/eval_ptn.py b/research/ptn/eval_ptn.py
deleted file mode 100644
index 2f8dd96b1938452083253832a586eaf525d5e072..0000000000000000000000000000000000000000
--- a/research/ptn/eval_ptn.py
+++ /dev/null
@@ -1,132 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Contains evaluation plan for the Im2vox model."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-
-import tensorflow as tf
-from tensorflow import app
-
-import model_ptn
-
-flags = tf.app.flags
-slim = tf.contrib.slim
-
-flags.DEFINE_string('inp_dir',
- '',
- 'Directory path containing the input data (tfrecords).')
-flags.DEFINE_string(
- 'dataset_name', 'shapenet_chair',
- 'Dataset name that is to be used for training and evaluation.')
-flags.DEFINE_integer('z_dim', 512, '')
-flags.DEFINE_integer('f_dim', 64, '')
-flags.DEFINE_integer('fc_dim', 1024, '')
-flags.DEFINE_integer('num_views', 24, 'Num of viewpoints in the input data.')
-flags.DEFINE_integer('image_size', 64,
- 'Input images dimension (pixels) - width & height.')
-flags.DEFINE_integer('vox_size', 32, 'Voxel prediction dimension.')
-flags.DEFINE_integer('step_size', 24, '')
-flags.DEFINE_integer('batch_size', 1, 'Batch size while training.')
-flags.DEFINE_float('focal_length', 0.866, '')
-flags.DEFINE_float('focal_range', 1.732, '')
-flags.DEFINE_string('encoder_name', 'ptn_encoder',
- 'Name of the encoder network being used.')
-flags.DEFINE_string('decoder_name', 'ptn_vox_decoder',
- 'Name of the decoder network being used.')
-flags.DEFINE_string('projector_name', 'ptn_projector',
- 'Name of the projector network being used.')
-# Save options
-flags.DEFINE_string('checkpoint_dir', '/tmp/ptn/eval/',
- 'Directory path for saving trained models and other data.')
-flags.DEFINE_string('model_name', 'ptn_proj',
- 'Name of the model used in naming the TF job. Must be different for each run.')
-flags.DEFINE_string('eval_set', 'val', 'Data partition to form evaluation on.')
-# Optimization
-flags.DEFINE_float('proj_weight', 10, 'Weighting factor for projection loss.')
-flags.DEFINE_float('volume_weight', 0, 'Weighting factor for volume loss.')
-flags.DEFINE_float('viewpoint_weight', 1,
- 'Weighting factor for viewpoint loss.')
-flags.DEFINE_float('learning_rate', 0.0001, 'Learning rate.')
-flags.DEFINE_float('weight_decay', 0.001, '')
-flags.DEFINE_float('clip_gradient_norm', 0, '')
-# Summary
-flags.DEFINE_integer('save_summaries_secs', 15, '')
-flags.DEFINE_integer('eval_interval_secs', 60 * 5, '')
-# Distribution
-flags.DEFINE_string('master', '', '')
-
-FLAGS = flags.FLAGS
-
-
-def main(argv=()):
- del argv # Unused.
- eval_dir = os.path.join(FLAGS.checkpoint_dir, FLAGS.model_name, 'train')
- log_dir = os.path.join(FLAGS.checkpoint_dir, FLAGS.model_name,
- 'eval_%s' % FLAGS.eval_set)
- if not os.path.exists(eval_dir):
- os.makedirs(eval_dir)
- if not os.path.exists(log_dir):
- os.makedirs(log_dir)
- g = tf.Graph()
-
- with g.as_default():
- eval_params = FLAGS
- eval_params.batch_size = 1
- eval_params.step_size = FLAGS.num_views
- ###########
- ## model ##
- ###########
- model = model_ptn.model_PTN(eval_params)
- ##########
- ## data ##
- ##########
- eval_data = model.get_inputs(
- FLAGS.inp_dir,
- FLAGS.dataset_name,
- eval_params.eval_set,
- eval_params.batch_size,
- eval_params.image_size,
- eval_params.vox_size,
- is_training=False)
- inputs = model.preprocess_with_all_views(eval_data)
- ##############
- ## model_fn ##
- ##############
- model_fn = model.get_model_fn(is_training=False, run_projection=False)
- outputs = model_fn(inputs)
- #############
- ## metrics ##
- #############
- names_to_values, names_to_updates = model.get_metrics(inputs, outputs)
- del names_to_values
- ################
- ## evaluation ##
- ################
- num_batches = eval_data['num_samples']
- slim.evaluation.evaluation_loop(
- master=FLAGS.master,
- checkpoint_dir=eval_dir,
- logdir=log_dir,
- num_evals=num_batches,
- eval_op=names_to_updates.values(),
- eval_interval_secs=FLAGS.eval_interval_secs)
-
-
-if __name__ == '__main__':
- app.run()
diff --git a/research/ptn/eval_rotator.py b/research/ptn/eval_rotator.py
deleted file mode 100644
index b7fcf0fe4ab2b98754ffbc0d75efa64828db6e25..0000000000000000000000000000000000000000
--- a/research/ptn/eval_rotator.py
+++ /dev/null
@@ -1,126 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Contains evaluation plan for the Rotator model."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-
-import tensorflow as tf
-from tensorflow import app
-
-import model_rotator as model
-
-flags = tf.app.flags
-slim = tf.contrib.slim
-
-flags.DEFINE_string('inp_dir',
- '',
- 'Directory path containing the input data (tfrecords).')
-flags.DEFINE_string(
- 'dataset_name', 'shapenet_chair',
- 'Dataset name that is to be used for training and evaluation.')
-flags.DEFINE_integer('z_dim', 512, '')
-flags.DEFINE_integer('a_dim', 3, '')
-flags.DEFINE_integer('f_dim', 64, '')
-flags.DEFINE_integer('fc_dim', 1024, '')
-flags.DEFINE_integer('num_views', 24, 'Num of viewpoints in the input data.')
-flags.DEFINE_integer('image_size', 64,
- 'Input images dimension (pixels) - width & height.')
-flags.DEFINE_integer('step_size', 24, '')
-flags.DEFINE_integer('batch_size', 2, '')
-flags.DEFINE_string('encoder_name', 'ptn_encoder',
- 'Name of the encoder network being used.')
-flags.DEFINE_string('decoder_name', 'ptn_im_decoder',
- 'Name of the decoder network being used.')
-flags.DEFINE_string('rotator_name', 'ptn_rotator',
- 'Name of the rotator network being used.')
-# Save options
-flags.DEFINE_string('checkpoint_dir', '/tmp/ptn_train/',
- 'Directory path for saving trained models and other data.')
-flags.DEFINE_string('model_name', 'ptn_proj',
- 'Name of the model used in naming the TF job. Must be different for each run.')
-# Optimization
-flags.DEFINE_float('image_weight', 10, '')
-flags.DEFINE_float('mask_weight', 1, '')
-flags.DEFINE_float('learning_rate', 0.0001, 'Learning rate.')
-flags.DEFINE_float('weight_decay', 0.001, '')
-flags.DEFINE_float('clip_gradient_norm', 0, '')
-# Summary
-flags.DEFINE_integer('save_summaries_secs', 15, '')
-flags.DEFINE_integer('eval_interval_secs', 60 * 5, '')
-# Scheduling
-flags.DEFINE_string('master', '', '')
-
-FLAGS = flags.FLAGS
-
-
-def main(argv=()):
- del argv # Unused.
- eval_dir = os.path.join(FLAGS.checkpoint_dir,
- FLAGS.model_name, 'train')
- log_dir = os.path.join(FLAGS.checkpoint_dir,
- FLAGS.model_name, 'eval')
-
- if not os.path.exists(eval_dir):
- os.makedirs(eval_dir)
- if not os.path.exists(log_dir):
- os.makedirs(log_dir)
- g = tf.Graph()
-
- if FLAGS.step_size < FLAGS.num_views:
- raise ValueError('Impossible step_size, must not be less than num_views.')
-
- g = tf.Graph()
- with g.as_default():
- ##########
- ## data ##
- ##########
- val_data = model.get_inputs(
- FLAGS.inp_dir,
- FLAGS.dataset_name,
- 'val',
- FLAGS.batch_size,
- FLAGS.image_size,
- is_training=False)
- inputs = model.preprocess(val_data, FLAGS.step_size)
- ###########
- ## model ##
- ###########
- model_fn = model.get_model_fn(FLAGS, is_training=False)
- outputs = model_fn(inputs)
- #############
- ## metrics ##
- #############
- names_to_values, names_to_updates = model.get_metrics(
- inputs, outputs, FLAGS)
- del names_to_values
- ################
- ## evaluation ##
- ################
- num_batches = int(val_data['num_samples'] / FLAGS.batch_size)
- slim.evaluation.evaluation_loop(
- master=FLAGS.master,
- checkpoint_dir=eval_dir,
- logdir=log_dir,
- num_evals=num_batches,
- eval_op=names_to_updates.values(),
- eval_interval_secs=FLAGS.eval_interval_secs)
-
-
-if __name__ == '__main__':
- app.run()
diff --git a/research/ptn/input_generator.py b/research/ptn/input_generator.py
deleted file mode 100644
index 7047d6483030b8b6ad0e68897121822030f84769..0000000000000000000000000000000000000000
--- a/research/ptn/input_generator.py
+++ /dev/null
@@ -1,130 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Provides dataset dictionaries as used in our network models."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-
-import tensorflow as tf
-import tensorflow.contrib.slim as slim
-
-from tensorflow.contrib.slim.python.slim.data import dataset
-from tensorflow.contrib.slim.python.slim.data import dataset_data_provider
-from tensorflow.contrib.slim.python.slim.data import tfexample_decoder
-
-_ITEMS_TO_DESCRIPTIONS = {
- 'image': 'Images',
- 'mask': 'Masks',
- 'vox': 'Voxels'
-}
-
-
-def _get_split(file_pattern, num_samples, num_views, image_size, vox_size):
- """Get dataset.Dataset for the given dataset file pattern and properties."""
-
- # A dictionary from TF-Example keys to tf.FixedLenFeature instance.
- keys_to_features = {
- 'image': tf.FixedLenFeature(
- shape=[num_views, image_size, image_size, 3],
- dtype=tf.float32, default_value=None),
- 'mask': tf.FixedLenFeature(
- shape=[num_views, image_size, image_size, 1],
- dtype=tf.float32, default_value=None),
- 'vox': tf.FixedLenFeature(
- shape=[vox_size, vox_size, vox_size, 1],
- dtype=tf.float32, default_value=None),
- }
-
- items_to_handler = {
- 'image': tfexample_decoder.Tensor(
- 'image', shape=[num_views, image_size, image_size, 3]),
- 'mask': tfexample_decoder.Tensor(
- 'mask', shape=[num_views, image_size, image_size, 1]),
- 'vox': tfexample_decoder.Tensor(
- 'vox', shape=[vox_size, vox_size, vox_size, 1])
- }
-
- decoder = tfexample_decoder.TFExampleDecoder(
- keys_to_features, items_to_handler)
-
- return dataset.Dataset(
- data_sources=file_pattern,
- reader=tf.TFRecordReader,
- decoder=decoder,
- num_samples=num_samples,
- items_to_descriptions=_ITEMS_TO_DESCRIPTIONS)
-
-
-def get(dataset_dir,
- dataset_name,
- split_name,
- shuffle=True,
- num_readers=1,
- common_queue_capacity=64,
- common_queue_min=50):
- """Provides input data for a specified dataset and split."""
-
- dataset_to_kwargs = {
- 'shapenet_chair': {
- 'file_pattern': '03001627_%s.tfrecords' % split_name,
- 'num_views': 24,
- 'image_size': 64,
- 'vox_size': 32,
- }, 'shapenet_all': {
- 'file_pattern': '*_%s.tfrecords' % split_name,
- 'num_views': 24,
- 'image_size': 64,
- 'vox_size': 32,
- },
- }
-
- split_sizes = {
- 'shapenet_chair': {
- 'train': 4744,
- 'val': 678,
- 'test': 1356,
- },
- 'shapenet_all': {
- 'train': 30643,
- 'val': 4378,
- 'test': 8762,
- }
- }
-
- kwargs = dataset_to_kwargs[dataset_name]
- kwargs['file_pattern'] = os.path.join(dataset_dir, kwargs['file_pattern'])
- kwargs['num_samples'] = split_sizes[dataset_name][split_name]
-
- dataset_split = _get_split(**kwargs)
- data_provider = dataset_data_provider.DatasetDataProvider(
- dataset_split,
- num_readers=num_readers,
- common_queue_capacity=common_queue_capacity,
- common_queue_min=common_queue_min,
- shuffle=shuffle)
-
- inputs = {
- 'num_samples': dataset_split.num_samples,
- }
-
- [image, mask, vox] = data_provider.get(['image', 'mask', 'vox'])
- inputs['image'] = image
- inputs['mask'] = mask
- inputs['voxel'] = vox
-
- return inputs
diff --git a/research/ptn/losses.py b/research/ptn/losses.py
deleted file mode 100644
index 53cc28847a32af88b718fbb9e53ca287b48a8b65..0000000000000000000000000000000000000000
--- a/research/ptn/losses.py
+++ /dev/null
@@ -1,178 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Defines the various loss functions in use by the PTN model."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-slim = tf.contrib.slim
-
-
-def add_rotator_image_loss(inputs, outputs, step_size, weight_scale):
- """Computes the image loss of deep rotator model.
-
- Args:
- inputs: Input dictionary to the model containing keys
- such as `images_k'.
- outputs: Output dictionary returned by the model containing keys
- such as `images_k'.
- step_size: A scalar representing the number of recurrent
- steps (number of repeated out-of-plane rotations)
- in the deep rotator network (int).
- weight_scale: A reweighting factor applied over the image loss (float).
-
- Returns:
- A `Tensor' scalar that returns averaged L2 loss
- (divided by batch_size and step_size) between the
- ground-truth images (RGB) and predicted images (tf.float32).
-
- """
- batch_size = tf.shape(inputs['images_0'])[0]
- image_loss = 0
- for k in range(1, step_size + 1):
- image_loss += tf.nn.l2_loss(
- inputs['images_%d' % k] - outputs['images_%d' % k])
-
- image_loss /= tf.to_float(step_size * batch_size)
- slim.summaries.add_scalar_summary(
- image_loss, 'image_loss', prefix='losses')
- image_loss *= weight_scale
- return image_loss
-
-
-def add_rotator_mask_loss(inputs, outputs, step_size, weight_scale):
- """Computes the mask loss of deep rotator model.
-
- Args:
- inputs: Input dictionary to the model containing keys
- such as `masks_k'.
- outputs: Output dictionary returned by the model containing
- keys such as `masks_k'.
- step_size: A scalar representing the number of recurrent
- steps (number of repeated out-of-plane rotations)
- in the deep rotator network (int).
- weight_scale: A reweighting factor applied over the mask loss (float).
-
- Returns:
- A `Tensor' that returns averaged L2 loss
- (divided by batch_size and step_size) between the ground-truth masks
- (object silhouettes) and predicted masks (tf.float32).
-
- """
- batch_size = tf.shape(inputs['images_0'])[0]
- mask_loss = 0
- for k in range(1, step_size + 1):
- mask_loss += tf.nn.l2_loss(
- inputs['masks_%d' % k] - outputs['masks_%d' % k])
-
- mask_loss /= tf.to_float(step_size * batch_size)
- slim.summaries.add_scalar_summary(
- mask_loss, 'mask_loss', prefix='losses')
- mask_loss *= weight_scale
- return mask_loss
-
-
-def add_volume_proj_loss(inputs, outputs, num_views, weight_scale):
- """Computes the projection loss of voxel generation model.
-
- Args:
- inputs: Input dictionary to the model containing keys such as
- `images_1'.
- outputs: Output dictionary returned by the model containing keys
- such as `masks_k' and ``projs_k'.
- num_views: A integer scalar represents the total number of
- viewpoints for each of the object (int).
- weight_scale: A reweighting factor applied over the projection loss (float).
-
- Returns:
- A `Tensor' that returns the averaged L2 loss
- (divided by batch_size and num_views) between the ground-truth
- masks (object silhouettes) and predicted masks (tf.float32).
-
- """
- batch_size = tf.shape(inputs['images_1'])[0]
- proj_loss = 0
- for k in range(num_views):
- proj_loss += tf.nn.l2_loss(
- outputs['masks_%d' % (k + 1)] - outputs['projs_%d' % (k + 1)])
- proj_loss /= tf.to_float(num_views * batch_size)
- slim.summaries.add_scalar_summary(
- proj_loss, 'proj_loss', prefix='losses')
- proj_loss *= weight_scale
- return proj_loss
-
-
-def add_volume_loss(inputs, outputs, num_views, weight_scale):
- """Computes the volume loss of voxel generation model.
-
- Args:
- inputs: Input dictionary to the model containing keys such as
- `images_1' and `voxels'.
- outputs: Output dictionary returned by the model containing keys
- such as `voxels_k'.
- num_views: A scalar representing the total number of
- viewpoints for each object (int).
- weight_scale: A reweighting factor applied over the volume
- loss (tf.float32).
-
- Returns:
- A `Tensor' that returns the averaged L2 loss
- (divided by batch_size and num_views) between the ground-truth
- volumes and predicted volumes (tf.float32).
-
- """
- batch_size = tf.shape(inputs['images_1'])[0]
- vol_loss = 0
- for k in range(num_views):
- vol_loss += tf.nn.l2_loss(
- inputs['voxels'] - outputs['voxels_%d' % (k + 1)])
- vol_loss /= tf.to_float(num_views * batch_size)
- slim.summaries.add_scalar_summary(
- vol_loss, 'vol_loss', prefix='losses')
- vol_loss *= weight_scale
- return vol_loss
-
-
-def regularization_loss(scopes, params):
- """Computes the weight decay as regularization during training.
-
- Args:
- scopes: A list of different components of the model such as
- ``encoder'', ``decoder'' and ``projector''.
- params: Parameters of the model.
-
- Returns:
- Regularization loss (tf.float32).
- """
-
- reg_loss = tf.zeros(dtype=tf.float32, shape=[])
- if params.weight_decay > 0:
- is_trainable = lambda x: x in tf.trainable_variables()
- is_weights = lambda x: 'weights' in x.name
- for scope in scopes:
- scope_vars = filter(is_trainable,
- tf.contrib.framework.get_model_variables(scope))
- scope_vars = filter(is_weights, scope_vars)
- if scope_vars:
- reg_loss += tf.add_n([tf.nn.l2_loss(var) for var in scope_vars])
-
- slim.summaries.add_scalar_summary(
- reg_loss, 'reg_loss', prefix='losses')
- reg_loss *= params.weight_decay
- return reg_loss
diff --git a/research/ptn/metrics.py b/research/ptn/metrics.py
deleted file mode 100644
index 5f31dd5fd5a67af3f5cc94de88493c25750e413c..0000000000000000000000000000000000000000
--- a/research/ptn/metrics.py
+++ /dev/null
@@ -1,111 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Provides metrics used by PTN."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from six.moves import xrange
-import tensorflow as tf
-
-slim = tf.contrib.slim
-
-
-def add_image_pred_metrics(
- inputs, outputs, num_views, upscale_factor):
- """Computes the image prediction metrics.
-
- Args:
- inputs: Input dictionary of the deep rotator model (model_rotator.py).
- outputs: Output dictionary of the deep rotator model (model_rotator.py).
- num_views: An integer scalar representing the total number
- of different viewpoints for each object in the dataset.
- upscale_factor: A float scalar representing the number of pixels
- per image (num_channels x image_height x image_width).
-
- Returns:
- names_to_values: A dictionary representing the current value
- of the metric.
- names_to_updates: A dictionary representing the operation
- that accumulates the error from a batch of data.
- """
- names_to_values = dict()
- names_to_updates = dict()
- for k in xrange(num_views):
- tmp_value, tmp_update = tf.contrib.metrics.streaming_mean_squared_error(
- outputs['images_%d' % (k + 1)], inputs['images_%d' % (k + 1)])
- name = 'image_pred/rnn_%d' % (k + 1)
- names_to_values.update({name: tmp_value * upscale_factor})
- names_to_updates.update({name: tmp_update})
- return names_to_values, names_to_updates
-
-
-def add_mask_pred_metrics(
- inputs, outputs, num_views, upscale_factor):
- """Computes the mask prediction metrics.
-
- Args:
- inputs: Input dictionary of the deep rotator model (model_rotator.py).
- outputs: Output dictionary of the deep rotator model (model_rotator.py).
- num_views: An integer scalar representing the total number
- of different viewpoints for each object in the dataset.
- upscale_factor: A float scalar representing the number of pixels
- per image (num_channels x image_height x image_width).
-
- Returns:
- names_to_values: A dictionary representing the current value
- of the metric.
- names_to_updates: A dictionary representing the operation
- that accumulates the error from a batch of data.
-
- """
- names_to_values = dict()
- names_to_updates = dict()
- for k in xrange(num_views):
- tmp_value, tmp_update = tf.contrib.metrics.streaming_mean_squared_error(
- outputs['masks_%d' % (k + 1)], inputs['masks_%d' % (k + 1)])
- name = 'mask_pred/rnn_%d' % (k + 1)
- names_to_values.update({name: tmp_value * upscale_factor})
- names_to_updates.update({name: tmp_update})
- return names_to_values, names_to_updates
-
-
-def add_volume_iou_metrics(inputs, outputs):
- """Computes the per-instance volume IOU.
-
- Args:
- inputs: Input dictionary of the voxel generation model.
- outputs: Output dictionary returned by the voxel generation model.
-
- Returns:
- names_to_values: metrics->values (dict).
- names_to_updates: metrics->ops (dict).
-
- """
- names_to_values = dict()
- names_to_updates = dict()
- labels = tf.greater_equal(inputs['voxels'], 0.5)
- predictions = tf.greater_equal(outputs['voxels_1'], 0.5)
- labels = (2 - tf.to_int32(labels)) - 1
- predictions = (3 - tf.to_int32(predictions) * 2) - 1
- tmp_values, tmp_updates = tf.metrics.mean_iou(
- labels=labels,
- predictions=predictions,
- num_classes=3)
- names_to_values['volume_iou'] = tmp_values * 3.0
- names_to_updates['volume_iou'] = tmp_updates
- return names_to_values, names_to_updates
diff --git a/research/ptn/model_ptn.py b/research/ptn/model_ptn.py
deleted file mode 100644
index cc0fc4fa38e5479d78307e764ae490e124e34ab7..0000000000000000000000000000000000000000
--- a/research/ptn/model_ptn.py
+++ /dev/null
@@ -1,232 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Implementations for Im2Vox PTN (NIPS16) model."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-import losses
-import metrics
-import model_voxel_generation
-import utils
-from nets import im2vox_factory
-
-slim = tf.contrib.slim
-
-
-class model_PTN(model_voxel_generation.Im2Vox): # pylint:disable=invalid-name
- """Inherits the generic Im2Vox model class and implements the functions."""
-
- def __init__(self, params):
- super(model_PTN, self).__init__(params)
-
- # For testing, this selects all views in input
- def preprocess_with_all_views(self, raw_inputs):
- (quantity, num_views) = raw_inputs['images'].get_shape().as_list()[:2]
-
- inputs = dict()
- inputs['voxels'] = []
- inputs['images_1'] = []
- for k in xrange(num_views):
- inputs['matrix_%d' % (k + 1)] = []
- inputs['matrix_1'] = []
- for n in xrange(quantity):
- for k in xrange(num_views):
- inputs['images_1'].append(raw_inputs['images'][n, k, :, :, :])
- inputs['voxels'].append(raw_inputs['voxels'][n, :, :, :, :])
- tf_matrix = self.get_transform_matrix(k)
- inputs['matrix_%d' % (k + 1)].append(tf_matrix)
-
- inputs['images_1'] = tf.stack(inputs['images_1'])
- inputs['voxels'] = tf.stack(inputs['voxels'])
- for k in xrange(num_views):
- inputs['matrix_%d' % (k + 1)] = tf.stack(inputs['matrix_%d' % (k + 1)])
-
- return inputs
-
- def get_model_fn(self, is_training=True, reuse=False, run_projection=True):
- return im2vox_factory.get(self._params, is_training, reuse, run_projection)
-
- def get_regularization_loss(self, scopes):
- return losses.regularization_loss(scopes, self._params)
-
- def get_loss(self, inputs, outputs):
- """Computes the loss used for PTN paper (projection + volume loss)."""
- g_loss = tf.zeros(dtype=tf.float32, shape=[])
-
- if self._params.proj_weight:
- g_loss += losses.add_volume_proj_loss(
- inputs, outputs, self._params.step_size, self._params.proj_weight)
-
- if self._params.volume_weight:
- g_loss += losses.add_volume_loss(inputs, outputs, 1,
- self._params.volume_weight)
-
- slim.summaries.add_scalar_summary(g_loss, 'im2vox_loss', prefix='losses')
-
- return g_loss
-
- def get_metrics(self, inputs, outputs):
- """Aggregate the metrics for voxel generation model.
-
- Args:
- inputs: Input dictionary of the voxel generation model.
- outputs: Output dictionary returned by the voxel generation model.
-
- Returns:
- names_to_values: metrics->values (dict).
- names_to_updates: metrics->ops (dict).
- """
- names_to_values = dict()
- names_to_updates = dict()
-
- tmp_values, tmp_updates = metrics.add_volume_iou_metrics(inputs, outputs)
-
- names_to_values.update(tmp_values)
- names_to_updates.update(tmp_updates)
-
- for name, value in names_to_values.iteritems():
- slim.summaries.add_scalar_summary(
- value, name, prefix='eval', print_summary=True)
-
- return names_to_values, names_to_updates
-
- def write_disk_grid(self,
- global_step,
- log_dir,
- input_images,
- gt_projs,
- pred_projs,
- input_voxels=None,
- output_voxels=None):
- """Function called by TF to save the prediction periodically."""
- summary_freq = self._params.save_every
-
- def write_grid(input_images, gt_projs, pred_projs, global_step,
- input_voxels, output_voxels):
- """Native python function to call for writing images to files."""
- grid = _build_image_grid(
- input_images,
- gt_projs,
- pred_projs,
- input_voxels=input_voxels,
- output_voxels=output_voxels)
-
- if global_step % summary_freq == 0:
- img_path = os.path.join(log_dir, '%s.jpg' % str(global_step))
- utils.save_image(grid, img_path)
- return grid
-
- save_op = tf.py_func(write_grid, [
- input_images, gt_projs, pred_projs, global_step, input_voxels,
- output_voxels
- ], [tf.uint8], 'write_grid')[0]
- slim.summaries.add_image_summary(
- tf.expand_dims(save_op, axis=0), name='grid_vis')
- return save_op
-
- def get_transform_matrix(self, view_out):
- """Get the 4x4 Perspective Transfromation matrix used for PTN."""
- num_views = self._params.num_views
- focal_length = self._params.focal_length
- focal_range = self._params.focal_range
- phi = 30
- theta_interval = 360.0 / num_views
- theta = theta_interval * view_out
-
- # pylint: disable=invalid-name
- camera_matrix = np.zeros((4, 4), dtype=np.float32)
- intrinsic_matrix = np.eye(4, dtype=np.float32)
- extrinsic_matrix = np.eye(4, dtype=np.float32)
-
- sin_phi = np.sin(float(phi) / 180.0 * np.pi)
- cos_phi = np.cos(float(phi) / 180.0 * np.pi)
- sin_theta = np.sin(float(-theta) / 180.0 * np.pi)
- cos_theta = np.cos(float(-theta) / 180.0 * np.pi)
-
- rotation_azimuth = np.zeros((3, 3), dtype=np.float32)
- rotation_azimuth[0, 0] = cos_theta
- rotation_azimuth[2, 2] = cos_theta
- rotation_azimuth[0, 2] = -sin_theta
- rotation_azimuth[2, 0] = sin_theta
- rotation_azimuth[1, 1] = 1.0
-
- ## rotation axis -- x
- rotation_elevation = np.zeros((3, 3), dtype=np.float32)
- rotation_elevation[0, 0] = cos_phi
- rotation_elevation[0, 1] = sin_phi
- rotation_elevation[1, 0] = -sin_phi
- rotation_elevation[1, 1] = cos_phi
- rotation_elevation[2, 2] = 1.0
-
- rotation_matrix = np.matmul(rotation_azimuth, rotation_elevation)
- displacement = np.zeros((3, 1), dtype=np.float32)
- displacement[0, 0] = float(focal_length) + float(focal_range) / 2.0
- displacement = np.matmul(rotation_matrix, displacement)
-
- extrinsic_matrix[0:3, 0:3] = rotation_matrix
- extrinsic_matrix[0:3, 3:4] = -displacement
-
- intrinsic_matrix[2, 2] = 1.0 / float(focal_length)
- intrinsic_matrix[1, 1] = 1.0 / float(focal_length)
-
- camera_matrix = np.matmul(extrinsic_matrix, intrinsic_matrix)
- return camera_matrix
-
-
-def _build_image_grid(input_images,
- gt_projs,
- pred_projs,
- input_voxels,
- output_voxels,
- vis_size=128):
- """Builds a grid image by concatenating the input images."""
- quantity = input_images.shape[0]
-
- for row in xrange(int(quantity / 3)):
- for col in xrange(3):
- index = row * 3 + col
- input_img_ = utils.resize_image(input_images[index, :, :, :], vis_size,
- vis_size)
- gt_proj_ = utils.resize_image(gt_projs[index, :, :, :], vis_size,
- vis_size)
- pred_proj_ = utils.resize_image(pred_projs[index, :, :, :], vis_size,
- vis_size)
- gt_voxel_vis = utils.resize_image(
- utils.display_voxel(input_voxels[index, :, :, :, 0]), vis_size,
- vis_size)
- pred_voxel_vis = utils.resize_image(
- utils.display_voxel(output_voxels[index, :, :, :, 0]), vis_size,
- vis_size)
- if col == 0:
- tmp_ = np.concatenate(
- [input_img_, gt_proj_, pred_proj_, gt_voxel_vis, pred_voxel_vis], 1)
- else:
- tmp_ = np.concatenate([
- tmp_, input_img_, gt_proj_, pred_proj_, gt_voxel_vis, pred_voxel_vis
- ], 1)
- if row == 0:
- out_grid = tmp_
- else:
- out_grid = np.concatenate([out_grid, tmp_], 0)
-
- return out_grid
diff --git a/research/ptn/model_rotator.py b/research/ptn/model_rotator.py
deleted file mode 100644
index 28860bc1025f78b5413b84d0c2bbf632874e0853..0000000000000000000000000000000000000000
--- a/research/ptn/model_rotator.py
+++ /dev/null
@@ -1,266 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Helper functions for pretraining (rotator) as described in PTN paper."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-import input_generator
-import losses
-import metrics
-import utils
-from nets import deeprotator_factory
-
-slim = tf.contrib.slim
-
-
-def _get_data_from_provider(inputs, batch_size, split_name):
- """Returns dictionary of batch input data processed by tf.train.batch."""
- images, masks = tf.train.batch(
- [inputs['image'], inputs['mask']],
- batch_size=batch_size,
- num_threads=8,
- capacity=8 * batch_size,
- name='batching_queues/%s' % (split_name))
-
- outputs = dict()
- outputs['images'] = images
- outputs['masks'] = masks
- outputs['num_samples'] = inputs['num_samples']
-
- return outputs
-
-
-def get_inputs(dataset_dir, dataset_name, split_name, batch_size, image_size,
- is_training):
- """Loads the given dataset and split."""
- del image_size # Unused
- with tf.variable_scope('data_loading_%s/%s' % (dataset_name, split_name)):
- common_queue_min = 50
- common_queue_capacity = 256
- num_readers = 4
-
- inputs = input_generator.get(
- dataset_dir,
- dataset_name,
- split_name,
- shuffle=is_training,
- num_readers=num_readers,
- common_queue_min=common_queue_min,
- common_queue_capacity=common_queue_capacity)
-
- return _get_data_from_provider(inputs, batch_size, split_name)
-
-
-def preprocess(raw_inputs, step_size):
- """Selects the subset of viewpoints to train on."""
- shp = raw_inputs['images'].get_shape().as_list()
- quantity = shp[0]
- num_views = shp[1]
- image_size = shp[2]
- del image_size # Unused
-
- batch_rot = np.zeros((quantity, 3), dtype=np.float32)
- inputs = dict()
- for n in xrange(step_size + 1):
- inputs['images_%d' % n] = []
- inputs['masks_%d' % n] = []
-
- for n in xrange(quantity):
- view_in = np.random.randint(0, num_views)
- rng_rot = np.random.randint(0, 2)
- if step_size == 1:
- rng_rot = np.random.randint(0, 3)
-
- delta = 0
- if rng_rot == 0:
- delta = -1
- batch_rot[n, 2] = 1
- elif rng_rot == 1:
- delta = 1
- batch_rot[n, 0] = 1
- else:
- delta = 0
- batch_rot[n, 1] = 1
-
- inputs['images_0'].append(raw_inputs['images'][n, view_in, :, :, :])
- inputs['masks_0'].append(raw_inputs['masks'][n, view_in, :, :, :])
-
- view_out = view_in
- for k in xrange(1, step_size + 1):
- view_out += delta
- if view_out >= num_views:
- view_out = 0
- if view_out < 0:
- view_out = num_views - 1
-
- inputs['images_%d' % k].append(raw_inputs['images'][n, view_out, :, :, :])
- inputs['masks_%d' % k].append(raw_inputs['masks'][n, view_out, :, :, :])
-
- for n in xrange(step_size + 1):
- inputs['images_%d' % n] = tf.stack(inputs['images_%d' % n])
- inputs['masks_%d' % n] = tf.stack(inputs['masks_%d' % n])
-
- inputs['actions'] = tf.constant(batch_rot, dtype=tf.float32)
- return inputs
-
-
-def get_init_fn(scopes, params):
- """Initialization assignment operator function used while training."""
- if not params.init_model:
- return None
-
- is_trainable = lambda x: x in tf.trainable_variables()
- var_list = []
- for scope in scopes:
- var_list.extend(
- filter(is_trainable, tf.contrib.framework.get_model_variables(scope)))
-
- init_assign_op, init_feed_dict = slim.assign_from_checkpoint(
- params.init_model, var_list)
-
- def init_assign_function(sess):
- sess.run(init_assign_op, init_feed_dict)
-
- return init_assign_function
-
-
-def get_model_fn(params, is_training, reuse=False):
- return deeprotator_factory.get(params, is_training, reuse)
-
-
-def get_regularization_loss(scopes, params):
- return losses.regularization_loss(scopes, params)
-
-
-def get_loss(inputs, outputs, params):
- """Computes the rotator loss."""
- g_loss = tf.zeros(dtype=tf.float32, shape=[])
-
- if hasattr(params, 'image_weight'):
- g_loss += losses.add_rotator_image_loss(inputs, outputs, params.step_size,
- params.image_weight)
-
- if hasattr(params, 'mask_weight'):
- g_loss += losses.add_rotator_mask_loss(inputs, outputs, params.step_size,
- params.mask_weight)
-
- slim.summaries.add_scalar_summary(
- g_loss, 'rotator_loss', prefix='losses')
-
- return g_loss
-
-
-def get_train_op_for_scope(loss, optimizer, scopes, params):
- """Train operation function for the given scope used file training."""
- is_trainable = lambda x: x in tf.trainable_variables()
-
- var_list = []
- update_ops = []
-
- for scope in scopes:
- var_list.extend(
- filter(is_trainable, tf.contrib.framework.get_model_variables(scope)))
- update_ops.extend(tf.get_collection(tf.GraphKeys.UPDATE_OPS, scope))
-
- return slim.learning.create_train_op(
- loss,
- optimizer,
- update_ops=update_ops,
- variables_to_train=var_list,
- clip_gradient_norm=params.clip_gradient_norm)
-
-
-def get_metrics(inputs, outputs, params):
- """Aggregate the metrics for rotator model.
-
- Args:
- inputs: Input dictionary of the rotator model.
- outputs: Output dictionary returned by the rotator model.
- params: Hyperparameters of the rotator model.
-
- Returns:
- names_to_values: metrics->values (dict).
- names_to_updates: metrics->ops (dict).
- """
- names_to_values = dict()
- names_to_updates = dict()
-
- tmp_values, tmp_updates = metrics.add_image_pred_metrics(
- inputs, outputs, params.num_views, 3*params.image_size**2)
- names_to_values.update(tmp_values)
- names_to_updates.update(tmp_updates)
-
- tmp_values, tmp_updates = metrics.add_mask_pred_metrics(
- inputs, outputs, params.num_views, params.image_size**2)
- names_to_values.update(tmp_values)
- names_to_updates.update(tmp_updates)
-
- for name, value in names_to_values.iteritems():
- slim.summaries.add_scalar_summary(
- value, name, prefix='eval', print_summary=True)
-
- return names_to_values, names_to_updates
-
-
-def write_disk_grid(global_step, summary_freq, log_dir, input_images,
- output_images, pred_images, pred_masks):
- """Function called by TF to save the prediction periodically."""
-
- def write_grid(grid, global_step):
- """Native python function to call for writing images to files."""
- if global_step % summary_freq == 0:
- img_path = os.path.join(log_dir, '%s.jpg' % str(global_step))
- utils.save_image(grid, img_path)
- return 0
-
- grid = _build_image_grid(input_images, output_images, pred_images, pred_masks)
- slim.summaries.add_image_summary(
- tf.expand_dims(grid, axis=0), name='grid_vis')
- save_op = tf.py_func(write_grid, [grid, global_step], [tf.int64],
- 'write_grid')[0]
- return save_op
-
-
-def _build_image_grid(input_images, output_images, pred_images, pred_masks):
- """Builds a grid image by concatenating the input images."""
- quantity = input_images.get_shape().as_list()[0]
-
- for row in xrange(int(quantity / 4)):
- for col in xrange(4):
- index = row * 4 + col
- input_img_ = input_images[index, :, :, :]
- output_img_ = output_images[index, :, :, :]
- pred_img_ = pred_images[index, :, :, :]
- pred_mask_ = tf.tile(pred_masks[index, :, :, :], [1, 1, 3])
- if col == 0:
- tmp_ = tf.concat([input_img_, output_img_, pred_img_, pred_mask_],
- 1) ## to the right
- else:
- tmp_ = tf.concat([tmp_, input_img_, output_img_, pred_img_, pred_mask_],
- 1)
- if row == 0:
- out_grid = tmp_
- else:
- out_grid = tf.concat([out_grid, tmp_], 0)
-
- return out_grid
diff --git a/research/ptn/model_voxel_generation.py b/research/ptn/model_voxel_generation.py
deleted file mode 100644
index 0c8fc84669a7fccc0f3a33ecb4c847162d99521e..0000000000000000000000000000000000000000
--- a/research/ptn/model_voxel_generation.py
+++ /dev/null
@@ -1,222 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Base class for voxel generation model."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import abc
-import os
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-import input_generator
-import utils
-
-slim = tf.contrib.slim
-
-
-class Im2Vox(object):
- """Defines the voxel generation model."""
-
- __metaclass__ = abc.ABCMeta
-
- def __init__(self, params):
- self._params = params
-
- @abc.abstractmethod
- def get_metrics(self, inputs, outputs):
- """Gets dictionaries from metrics to value `Tensors` & update `Tensors`."""
- pass
-
- @abc.abstractmethod
- def get_loss(self, inputs, outputs):
- pass
-
- @abc.abstractmethod
- def get_regularization_loss(self, scopes):
- pass
-
- def set_params(self, params):
- self._params = params
-
- def get_inputs(self,
- dataset_dir,
- dataset_name,
- split_name,
- batch_size,
- image_size,
- vox_size,
- is_training=True):
- """Loads data for a specified dataset and split."""
- del image_size, vox_size
- with tf.variable_scope('data_loading_%s/%s' % (dataset_name, split_name)):
- common_queue_min = 64
- common_queue_capacity = 256
- num_readers = 4
-
- inputs = input_generator.get(
- dataset_dir,
- dataset_name,
- split_name,
- shuffle=is_training,
- num_readers=num_readers,
- common_queue_min=common_queue_min,
- common_queue_capacity=common_queue_capacity)
-
- images, voxels = tf.train.batch(
- [inputs['image'], inputs['voxel']],
- batch_size=batch_size,
- num_threads=8,
- capacity=8 * batch_size,
- name='batching_queues/%s/%s' % (dataset_name, split_name))
-
- outputs = dict()
- outputs['images'] = images
- outputs['voxels'] = voxels
- outputs['num_samples'] = inputs['num_samples']
-
- return outputs
-
- def preprocess(self, raw_inputs, step_size):
- """Selects the subset of viewpoints to train on."""
- (quantity, num_views) = raw_inputs['images'].get_shape().as_list()[:2]
-
- inputs = dict()
- inputs['voxels'] = raw_inputs['voxels']
-
- for k in xrange(step_size):
- inputs['images_%d' % (k + 1)] = []
- inputs['matrix_%d' % (k + 1)] = []
-
- for n in xrange(quantity):
- selected_views = np.random.choice(num_views, step_size, replace=False)
- for k in xrange(step_size):
- view_selected = selected_views[k]
- inputs['images_%d' %
- (k + 1)].append(raw_inputs['images'][n, view_selected, :, :, :])
- tf_matrix = self.get_transform_matrix(view_selected)
- inputs['matrix_%d' % (k + 1)].append(tf_matrix)
-
- for k in xrange(step_size):
- inputs['images_%d' % (k + 1)] = tf.stack(inputs['images_%d' % (k + 1)])
- inputs['matrix_%d' % (k + 1)] = tf.stack(inputs['matrix_%d' % (k + 1)])
-
- return inputs
-
- def get_init_fn(self, scopes):
- """Initialization assignment operator function used while training."""
- if not self._params.init_model:
- return None
-
- is_trainable = lambda x: x in tf.trainable_variables()
- var_list = []
- for scope in scopes:
- var_list.extend(
- filter(is_trainable, tf.contrib.framework.get_model_variables(scope)))
-
- init_assign_op, init_feed_dict = slim.assign_from_checkpoint(
- self._params.init_model, var_list)
-
- def init_assign_function(sess):
- sess.run(init_assign_op, init_feed_dict)
-
- return init_assign_function
-
- def get_train_op_for_scope(self, loss, optimizer, scopes):
- """Train operation function for the given scope used file training."""
- is_trainable = lambda x: x in tf.trainable_variables()
-
- var_list = []
- update_ops = []
-
- for scope in scopes:
- var_list.extend(
- filter(is_trainable, tf.contrib.framework.get_model_variables(scope)))
- update_ops.extend(tf.get_collection(tf.GraphKeys.UPDATE_OPS, scope))
-
- return slim.learning.create_train_op(
- loss,
- optimizer,
- update_ops=update_ops,
- variables_to_train=var_list,
- clip_gradient_norm=self._params.clip_gradient_norm)
-
- def write_disk_grid(self,
- global_step,
- log_dir,
- input_images,
- gt_projs,
- pred_projs,
- pred_voxels=None):
- """Function called by TF to save the prediction periodically."""
- summary_freq = self._params.save_every
-
- def write_grid(input_images, gt_projs, pred_projs, pred_voxels,
- global_step):
- """Native python function to call for writing images to files."""
- grid = _build_image_grid(input_images, gt_projs, pred_projs, pred_voxels)
-
- if global_step % summary_freq == 0:
- img_path = os.path.join(log_dir, '%s.jpg' % str(global_step))
- utils.save_image(grid, img_path)
- with open(
- os.path.join(log_dir, 'pred_voxels_%s' % str(global_step)),
- 'w') as fout:
- np.save(fout, pred_voxels)
- with open(
- os.path.join(log_dir, 'input_images_%s' % str(global_step)),
- 'w') as fout:
- np.save(fout, input_images)
-
- return grid
-
- py_func_args = [
- input_images, gt_projs, pred_projs, pred_voxels, global_step
- ]
- save_grid_op = tf.py_func(write_grid, py_func_args, [tf.uint8],
- 'wrtie_grid')[0]
- slim.summaries.add_image_summary(
- tf.expand_dims(save_grid_op, axis=0), name='grid_vis')
- return save_grid_op
-
-
-def _build_image_grid(input_images, gt_projs, pred_projs, pred_voxels):
- """Build the visualization grid with py_func."""
- quantity, img_height, img_width = input_images.shape[:3]
- for row in xrange(int(quantity / 3)):
- for col in xrange(3):
- index = row * 3 + col
- input_img_ = input_images[index, :, :, :]
- gt_proj_ = gt_projs[index, :, :, :]
- pred_proj_ = pred_projs[index, :, :, :]
- pred_voxel_ = utils.display_voxel(pred_voxels[index, :, :, :, 0])
- pred_voxel_ = utils.resize_image(pred_voxel_, img_height, img_width)
- if col == 0:
- tmp_ = np.concatenate([input_img_, gt_proj_, pred_proj_, pred_voxel_],
- 1)
- else:
- tmp_ = np.concatenate(
- [tmp_, input_img_, gt_proj_, pred_proj_, pred_voxel_], 1)
- if row == 0:
- out_grid = tmp_
- else:
- out_grid = np.concatenate([out_grid, tmp_], 0)
-
- out_grid = out_grid.astype(np.uint8)
- return out_grid
diff --git a/research/ptn/nets/BUILD b/research/ptn/nets/BUILD
deleted file mode 100644
index 987499341ef25c8e19d532fdb14d3a9e842d0909..0000000000000000000000000000000000000000
--- a/research/ptn/nets/BUILD
+++ /dev/null
@@ -1,64 +0,0 @@
-package(default_visibility = ["//visibility:public"])
-
-py_library(
- name = "deeprotator_factory",
- srcs = ["deeprotator_factory.py"],
- deps = [
- ":ptn_encoder",
- ":ptn_im_decoder",
- ":ptn_rotator",
- ],
-)
-
-py_library(
- name = "im2vox_factory",
- srcs = ["im2vox_factory.py"],
- deps = [
- ":perspective_projector",
- ":ptn_encoder",
- ":ptn_vox_decoder",
- ],
-)
-
-py_library(
- name = "perspective_projector",
- srcs = ["perspective_projector.py"],
- deps = [
- ":perspective_transform",
- ],
-)
-
-py_library(
- name = "perspective_transform",
- srcs = ["perspective_transform.py"],
- deps = [
- ],
-)
-
-py_library(
- name = "ptn_encoder",
- srcs = ["ptn_encoder.py"],
- deps = [
- ],
-)
-
-py_library(
- name = "ptn_im_decoder",
- srcs = ["ptn_im_decoder.py"],
- deps = [
- ],
-)
-
-py_library(
- name = "ptn_rotator",
- srcs = ["ptn_rotator.py"],
- deps = [
- ],
-)
-
-py_library(
- name = "ptn_vox_decoder",
- srcs = ["ptn_vox_decoder.py"],
- deps = [
- ],
-)
diff --git a/research/ptn/nets/deeprotator_factory.py b/research/ptn/nets/deeprotator_factory.py
deleted file mode 100644
index e16170c41b7daae4a00068183cd0a4056ff279c3..0000000000000000000000000000000000000000
--- a/research/ptn/nets/deeprotator_factory.py
+++ /dev/null
@@ -1,91 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Factory module for different encoder/decoder network models."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-from nets import ptn_encoder
-from nets import ptn_im_decoder
-from nets import ptn_rotator
-
-_NAME_TO_NETS = {
- 'ptn_encoder': ptn_encoder,
- 'ptn_rotator': ptn_rotator,
- 'ptn_im_decoder': ptn_im_decoder,
-}
-
-
-def _get_network(name):
- """Gets a single network component."""
-
- if name not in _NAME_TO_NETS:
- raise ValueError('Network name [%s] not recognized.' % name)
- return _NAME_TO_NETS[name].model
-
-
-def get(params, is_training=False, reuse=False):
- """Factory function to retrieve a network model.
-
- Args:
- params: Different parameters used througout ptn, typically FLAGS (dict)
- is_training: Set to True if while training (boolean)
- reuse: Set as True if either using a pre-trained model or
- in the training loop while the graph has already been built (boolean)
- Returns:
- Model function for network (inputs to outputs)
- """
-
- def model(inputs):
- """Model function corresponding to a specific network architecture."""
- outputs = {}
-
- # First, build the encoder.
- encoder_fn = _get_network(params.encoder_name)
- with tf.variable_scope('encoder', reuse=reuse):
- # Produces id/pose units
- features = encoder_fn(inputs['images_0'], params, is_training)
- outputs['ids'] = features['ids']
- outputs['poses_0'] = features['poses']
-
- # Second, build the rotator and decoder.
- rotator_fn = _get_network(params.rotator_name)
- with tf.variable_scope('rotator', reuse=reuse):
- outputs['poses_1'] = rotator_fn(outputs['poses_0'], inputs['actions'],
- params, is_training)
- decoder_fn = _get_network(params.decoder_name)
- with tf.variable_scope('decoder', reuse=reuse):
- dec_output = decoder_fn(outputs['ids'], outputs['poses_1'], params,
- is_training)
- outputs['images_1'] = dec_output['images']
- outputs['masks_1'] = dec_output['masks']
-
- # Third, build the recurrent connection
- for k in range(1, params.step_size):
- with tf.variable_scope('rotator', reuse=True):
- outputs['poses_%d' % (k + 1)] = rotator_fn(
- outputs['poses_%d' % k], inputs['actions'], params, is_training)
- with tf.variable_scope('decoder', reuse=True):
- dec_output = decoder_fn(outputs['ids'], outputs['poses_%d' % (k + 1)],
- params, is_training)
- outputs['images_%d' % (k + 1)] = dec_output['images']
- outputs['masks_%d' % (k + 1)] = dec_output['masks']
-
- return outputs
-
- return model
diff --git a/research/ptn/nets/im2vox_factory.py b/research/ptn/nets/im2vox_factory.py
deleted file mode 100644
index c54b96c24a56a8fa796cbc4f881a78cfbf41b86d..0000000000000000000000000000000000000000
--- a/research/ptn/nets/im2vox_factory.py
+++ /dev/null
@@ -1,92 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Factory module for getting the complete image to voxel generation network."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-from nets import perspective_projector
-from nets import ptn_encoder
-from nets import ptn_vox_decoder
-
-_NAME_TO_NETS = {
- 'ptn_encoder': ptn_encoder,
- 'ptn_vox_decoder': ptn_vox_decoder,
- 'perspective_projector': perspective_projector,
-}
-
-
-def _get_network(name):
- """Gets a single encoder/decoder network model."""
-
- if name not in _NAME_TO_NETS:
- raise ValueError('Network name [%s] not recognized.' % name)
- return _NAME_TO_NETS[name].model
-
-
-def get(params, is_training=False, reuse=False, run_projection=True):
- """Factory function to get the training/pretraining im->vox model (NIPS16).
-
- Args:
- params: Different parameters used througout ptn, typically FLAGS (dict).
- is_training: Set to True if while training (boolean).
- reuse: Set as True if sharing variables with a model that has already
- been built (boolean).
- run_projection: Set as False if not interested in mask and projection
- images. Useful in evaluation routine (boolean).
- Returns:
- Model function for network (inputs to outputs).
- """
- def model(inputs):
- """Model function corresponding to a specific network architecture."""
- outputs = {}
-
- # First, build the encoder
- encoder_fn = _get_network(params.encoder_name)
- with tf.variable_scope('encoder', reuse=reuse):
- # Produces id/pose units
- enc_outputs = encoder_fn(inputs['images_1'], params, is_training)
- outputs['ids_1'] = enc_outputs['ids']
-
- # Second, build the decoder and projector
- decoder_fn = _get_network(params.decoder_name)
- with tf.variable_scope('decoder', reuse=reuse):
- outputs['voxels_1'] = decoder_fn(outputs['ids_1'], params, is_training)
- if run_projection:
- projector_fn = _get_network(params.projector_name)
- with tf.variable_scope('projector', reuse=reuse):
- outputs['projs_1'] = projector_fn(
- outputs['voxels_1'], inputs['matrix_1'], params, is_training)
- # Infer the ground-truth mask
- with tf.variable_scope('oracle', reuse=reuse):
- outputs['masks_1'] = projector_fn(inputs['voxels'], inputs['matrix_1'],
- params, False)
-
- # Third, build the entire graph (bundled strategy described in PTN paper)
- for k in range(1, params.step_size):
- with tf.variable_scope('projector', reuse=True):
- outputs['projs_%d' % (k + 1)] = projector_fn(
- outputs['voxels_1'], inputs['matrix_%d' %
- (k + 1)], params, is_training)
- with tf.variable_scope('oracle', reuse=True):
- outputs['masks_%d' % (k + 1)] = projector_fn(
- inputs['voxels'], inputs['matrix_%d' % (k + 1)], params, False)
-
- return outputs
-
- return model
diff --git a/research/ptn/nets/perspective_projector.py b/research/ptn/nets/perspective_projector.py
deleted file mode 100644
index 38c7df86b203884327d4c4eda5f02b7fc1b16323..0000000000000000000000000000000000000000
--- a/research/ptn/nets/perspective_projector.py
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""3D->2D projector model as used in PTN (NIPS16)."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-from nets import perspective_transform
-
-
-def model(voxels, transform_matrix, params, is_training):
- """Model transforming the 3D voxels into 2D projections.
-
- Args:
- voxels: A tensor of size [batch, depth, height, width, channel]
- representing the input of projection layer (tf.float32).
- transform_matrix: A tensor of size [batch, 16] representing
- the flattened 4-by-4 matrix for transformation (tf.float32).
- params: Model parameters (dict).
- is_training: Set to True if while training (boolean).
-
- Returns:
- A transformed tensor (tf.float32)
-
- """
- del is_training # Doesn't make a difference for projector
- # Rearrangement (batch, z, y, x, channel) --> (batch, y, z, x, channel).
- # By the standard, projection happens along z-axis but the voxels
- # are stored in a different way. So we need to switch the y and z
- # axis for transformation operation.
- voxels = tf.transpose(voxels, [0, 2, 1, 3, 4])
- z_near = params.focal_length
- z_far = params.focal_length + params.focal_range
- transformed_voxels = perspective_transform.transformer(
- voxels, transform_matrix, [params.vox_size] * 3, z_near, z_far)
- views = tf.reduce_max(transformed_voxels, [1])
- views = tf.reverse(views, [1])
- return views
diff --git a/research/ptn/nets/perspective_transform.py b/research/ptn/nets/perspective_transform.py
deleted file mode 100644
index 1c01f15f21d4f6f36c4638d0b8ad916e895aa0b2..0000000000000000000000000000000000000000
--- a/research/ptn/nets/perspective_transform.py
+++ /dev/null
@@ -1,278 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Perspective Transformer Layer Implementation.
-
-Transform the volume based on 4 x 4 perspective projection matrix.
-
-Reference:
-(1) "Perspective Transformer Nets: Perspective Transformer Nets:
-Learning Single-View 3D Object Reconstruction without 3D Supervision."
-Xinchen Yan, Jimei Yang, Ersin Yumer, Yijie Guo, Honglak Lee. In NIPS 2016
-https://papers.nips.cc/paper/6206-perspective-transformer-nets-learning-single-view-3d-object-reconstruction-without-3d-supervision.pdf
-
-(2) Official implementation in Torch: https://github.com/xcyan/ptnbhwd
-
-(3) 2D Transformer implementation in TF:
-github.com/tensorflow/models/tree/master/research/transformer
-
-"""
-
-import tensorflow as tf
-
-
-def transformer(voxels,
- theta,
- out_size,
- z_near,
- z_far,
- name='PerspectiveTransformer'):
- """Perspective Transformer Layer.
-
- Args:
- voxels: A tensor of size [num_batch, depth, height, width, num_channels].
- It is the output of a deconv/upsampling conv network (tf.float32).
- theta: A tensor of size [num_batch, 16].
- It is the inverse camera transformation matrix (tf.float32).
- out_size: A tuple representing the size of output of
- transformer layer (float).
- z_near: A number representing the near clipping plane (float).
- z_far: A number representing the far clipping plane (float).
-
- Returns:
- A transformed tensor (tf.float32).
-
- """
- def _repeat(x, n_repeats):
- with tf.variable_scope('_repeat'):
- rep = tf.transpose(
- tf.expand_dims(tf.ones(shape=tf.stack([
- n_repeats,
- ])), 1), [1, 0])
- rep = tf.to_int32(rep)
- x = tf.matmul(tf.reshape(x, (-1, 1)), rep)
- return tf.reshape(x, [-1])
-
- def _interpolate(im, x, y, z, out_size):
- """Bilinear interploation layer.
-
- Args:
- im: A 5D tensor of size [num_batch, depth, height, width, num_channels].
- It is the input volume for the transformation layer (tf.float32).
- x: A tensor of size [num_batch, out_depth, out_height, out_width]
- representing the inverse coordinate mapping for x (tf.float32).
- y: A tensor of size [num_batch, out_depth, out_height, out_width]
- representing the inverse coordinate mapping for y (tf.float32).
- z: A tensor of size [num_batch, out_depth, out_height, out_width]
- representing the inverse coordinate mapping for z (tf.float32).
- out_size: A tuple representing the output size of transformation layer
- (float).
-
- Returns:
- A transformed tensor (tf.float32).
-
- """
- with tf.variable_scope('_interpolate'):
- num_batch = im.get_shape().as_list()[0]
- depth = im.get_shape().as_list()[1]
- height = im.get_shape().as_list()[2]
- width = im.get_shape().as_list()[3]
- channels = im.get_shape().as_list()[4]
-
- x = tf.to_float(x)
- y = tf.to_float(y)
- z = tf.to_float(z)
- depth_f = tf.to_float(depth)
- height_f = tf.to_float(height)
- width_f = tf.to_float(width)
- # Number of disparity interpolated.
- out_depth = out_size[0]
- out_height = out_size[1]
- out_width = out_size[2]
- zero = tf.zeros([], dtype='int32')
- # 0 <= z < depth, 0 <= y < height & 0 <= x < width.
- max_z = tf.to_int32(tf.shape(im)[1] - 1)
- max_y = tf.to_int32(tf.shape(im)[2] - 1)
- max_x = tf.to_int32(tf.shape(im)[3] - 1)
-
- # Converts scale indices from [-1, 1] to [0, width/height/depth].
- x = (x + 1.0) * (width_f) / 2.0
- y = (y + 1.0) * (height_f) / 2.0
- z = (z + 1.0) * (depth_f) / 2.0
-
- x0 = tf.to_int32(tf.floor(x))
- x1 = x0 + 1
- y0 = tf.to_int32(tf.floor(y))
- y1 = y0 + 1
- z0 = tf.to_int32(tf.floor(z))
- z1 = z0 + 1
-
- x0_clip = tf.clip_by_value(x0, zero, max_x)
- x1_clip = tf.clip_by_value(x1, zero, max_x)
- y0_clip = tf.clip_by_value(y0, zero, max_y)
- y1_clip = tf.clip_by_value(y1, zero, max_y)
- z0_clip = tf.clip_by_value(z0, zero, max_z)
- z1_clip = tf.clip_by_value(z1, zero, max_z)
- dim3 = width
- dim2 = width * height
- dim1 = width * height * depth
- base = _repeat(
- tf.range(num_batch) * dim1, out_depth * out_height * out_width)
- base_z0_y0 = base + z0_clip * dim2 + y0_clip * dim3
- base_z0_y1 = base + z0_clip * dim2 + y1_clip * dim3
- base_z1_y0 = base + z1_clip * dim2 + y0_clip * dim3
- base_z1_y1 = base + z1_clip * dim2 + y1_clip * dim3
-
- idx_z0_y0_x0 = base_z0_y0 + x0_clip
- idx_z0_y0_x1 = base_z0_y0 + x1_clip
- idx_z0_y1_x0 = base_z0_y1 + x0_clip
- idx_z0_y1_x1 = base_z0_y1 + x1_clip
- idx_z1_y0_x0 = base_z1_y0 + x0_clip
- idx_z1_y0_x1 = base_z1_y0 + x1_clip
- idx_z1_y1_x0 = base_z1_y1 + x0_clip
- idx_z1_y1_x1 = base_z1_y1 + x1_clip
-
- # Use indices to lookup pixels in the flat image and restore
- # channels dim
- im_flat = tf.reshape(im, tf.stack([-1, channels]))
- im_flat = tf.to_float(im_flat)
- i_z0_y0_x0 = tf.gather(im_flat, idx_z0_y0_x0)
- i_z0_y0_x1 = tf.gather(im_flat, idx_z0_y0_x1)
- i_z0_y1_x0 = tf.gather(im_flat, idx_z0_y1_x0)
- i_z0_y1_x1 = tf.gather(im_flat, idx_z0_y1_x1)
- i_z1_y0_x0 = tf.gather(im_flat, idx_z1_y0_x0)
- i_z1_y0_x1 = tf.gather(im_flat, idx_z1_y0_x1)
- i_z1_y1_x0 = tf.gather(im_flat, idx_z1_y1_x0)
- i_z1_y1_x1 = tf.gather(im_flat, idx_z1_y1_x1)
-
- # Finally calculate interpolated values.
- x0_f = tf.to_float(x0)
- x1_f = tf.to_float(x1)
- y0_f = tf.to_float(y0)
- y1_f = tf.to_float(y1)
- z0_f = tf.to_float(z0)
- z1_f = tf.to_float(z1)
- # Check the out-of-boundary case.
- x0_valid = tf.to_float(
- tf.less_equal(x0, max_x) & tf.greater_equal(x0, 0))
- x1_valid = tf.to_float(
- tf.less_equal(x1, max_x) & tf.greater_equal(x1, 0))
- y0_valid = tf.to_float(
- tf.less_equal(y0, max_y) & tf.greater_equal(y0, 0))
- y1_valid = tf.to_float(
- tf.less_equal(y1, max_y) & tf.greater_equal(y1, 0))
- z0_valid = tf.to_float(
- tf.less_equal(z0, max_z) & tf.greater_equal(z0, 0))
- z1_valid = tf.to_float(
- tf.less_equal(z1, max_z) & tf.greater_equal(z1, 0))
-
- w_z0_y0_x0 = tf.expand_dims(((x1_f - x) * (y1_f - y) *
- (z1_f - z) * x1_valid * y1_valid * z1_valid),
- 1)
- w_z0_y0_x1 = tf.expand_dims(((x - x0_f) * (y1_f - y) *
- (z1_f - z) * x0_valid * y1_valid * z1_valid),
- 1)
- w_z0_y1_x0 = tf.expand_dims(((x1_f - x) * (y - y0_f) *
- (z1_f - z) * x1_valid * y0_valid * z1_valid),
- 1)
- w_z0_y1_x1 = tf.expand_dims(((x - x0_f) * (y - y0_f) *
- (z1_f - z) * x0_valid * y0_valid * z1_valid),
- 1)
- w_z1_y0_x0 = tf.expand_dims(((x1_f - x) * (y1_f - y) *
- (z - z0_f) * x1_valid * y1_valid * z0_valid),
- 1)
- w_z1_y0_x1 = tf.expand_dims(((x - x0_f) * (y1_f - y) *
- (z - z0_f) * x0_valid * y1_valid * z0_valid),
- 1)
- w_z1_y1_x0 = tf.expand_dims(((x1_f - x) * (y - y0_f) *
- (z - z0_f) * x1_valid * y0_valid * z0_valid),
- 1)
- w_z1_y1_x1 = tf.expand_dims(((x - x0_f) * (y - y0_f) *
- (z - z0_f) * x0_valid * y0_valid * z0_valid),
- 1)
-
- output = tf.add_n([
- w_z0_y0_x0 * i_z0_y0_x0, w_z0_y0_x1 * i_z0_y0_x1,
- w_z0_y1_x0 * i_z0_y1_x0, w_z0_y1_x1 * i_z0_y1_x1,
- w_z1_y0_x0 * i_z1_y0_x0, w_z1_y0_x1 * i_z1_y0_x1,
- w_z1_y1_x0 * i_z1_y1_x0, w_z1_y1_x1 * i_z1_y1_x1
- ])
- return output
-
- def _meshgrid(depth, height, width, z_near, z_far):
- with tf.variable_scope('_meshgrid'):
- x_t = tf.reshape(
- tf.tile(tf.linspace(-1.0, 1.0, width), [height * depth]),
- [depth, height, width])
- y_t = tf.reshape(
- tf.tile(tf.linspace(-1.0, 1.0, height), [width * depth]),
- [depth, width, height])
- y_t = tf.transpose(y_t, [0, 2, 1])
- sample_grid = tf.tile(
- tf.linspace(float(z_near), float(z_far), depth), [width * height])
- z_t = tf.reshape(sample_grid, [height, width, depth])
- z_t = tf.transpose(z_t, [2, 0, 1])
-
- z_t = 1 / z_t
- d_t = 1 / z_t
- x_t /= z_t
- y_t /= z_t
-
- x_t_flat = tf.reshape(x_t, (1, -1))
- y_t_flat = tf.reshape(y_t, (1, -1))
- d_t_flat = tf.reshape(d_t, (1, -1))
-
- ones = tf.ones_like(x_t_flat)
- grid = tf.concat([d_t_flat, y_t_flat, x_t_flat, ones], 0)
- return grid
-
- def _transform(theta, input_dim, out_size, z_near, z_far):
- with tf.variable_scope('_transform'):
- num_batch = input_dim.get_shape().as_list()[0]
- num_channels = input_dim.get_shape().as_list()[4]
- theta = tf.reshape(theta, (-1, 4, 4))
- theta = tf.cast(theta, 'float32')
-
- out_depth = out_size[0]
- out_height = out_size[1]
- out_width = out_size[2]
- grid = _meshgrid(out_depth, out_height, out_width, z_near, z_far)
- grid = tf.expand_dims(grid, 0)
- grid = tf.reshape(grid, [-1])
- grid = tf.tile(grid, tf.stack([num_batch]))
- grid = tf.reshape(grid, tf.stack([num_batch, 4, -1]))
-
- # Transform A x (x_t', y_t', 1, d_t)^T -> (x_s, y_s, z_s, 1).
- t_g = tf.matmul(theta, grid)
- z_s = tf.slice(t_g, [0, 0, 0], [-1, 1, -1])
- y_s = tf.slice(t_g, [0, 1, 0], [-1, 1, -1])
- x_s = tf.slice(t_g, [0, 2, 0], [-1, 1, -1])
-
- z_s_flat = tf.reshape(z_s, [-1])
- y_s_flat = tf.reshape(y_s, [-1])
- x_s_flat = tf.reshape(x_s, [-1])
-
- input_transformed = _interpolate(input_dim, x_s_flat, y_s_flat, z_s_flat,
- out_size)
-
- output = tf.reshape(
- input_transformed,
- tf.stack([num_batch, out_depth, out_height, out_width, num_channels]))
-
- return output
-
- with tf.variable_scope(name):
- output = _transform(theta, voxels, out_size, z_near, z_far)
- return output
diff --git a/research/ptn/nets/ptn_encoder.py b/research/ptn/nets/ptn_encoder.py
deleted file mode 100644
index ede556834e6ea42e9e0a266bc0d525a679924077..0000000000000000000000000000000000000000
--- a/research/ptn/nets/ptn_encoder.py
+++ /dev/null
@@ -1,54 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Training/Pretraining encoder as used in PTN (NIPS16)."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-slim = tf.contrib.slim
-
-
-def _preprocess(images):
- return images * 2 - 1
-
-
-def model(images, params, is_training):
- """Model encoding the images into view-invariant embedding."""
- del is_training # Unused
- image_size = images.get_shape().as_list()[1]
- f_dim = params.f_dim
- fc_dim = params.fc_dim
- z_dim = params.z_dim
- outputs = dict()
-
- images = _preprocess(images)
- with slim.arg_scope(
- [slim.conv2d, slim.fully_connected],
- weights_initializer=tf.truncated_normal_initializer(stddev=0.02, seed=1)):
- h0 = slim.conv2d(images, f_dim, [5, 5], stride=2, activation_fn=tf.nn.relu)
- h1 = slim.conv2d(h0, f_dim * 2, [5, 5], stride=2, activation_fn=tf.nn.relu)
- h2 = slim.conv2d(h1, f_dim * 4, [5, 5], stride=2, activation_fn=tf.nn.relu)
- # Reshape layer
- s8 = image_size // 8
- h2 = tf.reshape(h2, [-1, s8 * s8 * f_dim * 4])
- h3 = slim.fully_connected(h2, fc_dim, activation_fn=tf.nn.relu)
- h4 = slim.fully_connected(h3, fc_dim, activation_fn=tf.nn.relu)
-
- outputs['ids'] = slim.fully_connected(h4, z_dim, activation_fn=tf.nn.relu)
- outputs['poses'] = slim.fully_connected(h4, z_dim, activation_fn=tf.nn.relu)
- return outputs
diff --git a/research/ptn/nets/ptn_im_decoder.py b/research/ptn/nets/ptn_im_decoder.py
deleted file mode 100644
index 8ee512e878d549c2d16f13f58dee8786e129e751..0000000000000000000000000000000000000000
--- a/research/ptn/nets/ptn_im_decoder.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Image/Mask decoder used while pretraining the network."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-slim = tf.contrib.slim
-
-_FEATURE_MAP_SIZE = 8
-
-
-def _postprocess_im(images):
- """Performs post-processing for the images returned from conv net.
-
- Transforms the value from [-1, 1] to [0, 1].
- """
- return (images + 1) * 0.5
-
-
-def model(identities, poses, params, is_training):
- """Decoder model to get image and mask from latent embedding."""
- del is_training
- f_dim = params.f_dim
- fc_dim = params.fc_dim
-
- outputs = dict()
-
- with slim.arg_scope(
- [slim.fully_connected, slim.conv2d_transpose],
- weights_initializer=tf.truncated_normal_initializer(stddev=0.02, seed=1)):
- # Concatenate the identity and pose units
- h0 = tf.concat([identities, poses], 1)
- h0 = slim.fully_connected(h0, fc_dim, activation_fn=tf.nn.relu)
- h1 = slim.fully_connected(h0, fc_dim, activation_fn=tf.nn.relu)
-
- # Mask decoder
- dec_m0 = slim.fully_connected(
- h1, (_FEATURE_MAP_SIZE**2) * f_dim * 2, activation_fn=tf.nn.relu)
- dec_m0 = tf.reshape(
- dec_m0, [-1, _FEATURE_MAP_SIZE, _FEATURE_MAP_SIZE, f_dim * 2])
-
- dec_m1 = slim.conv2d_transpose(
- dec_m0, f_dim, [5, 5], stride=2, activation_fn=tf.nn.relu)
- dec_m2 = slim.conv2d_transpose(
- dec_m1, int(f_dim / 2), [5, 5], stride=2, activation_fn=tf.nn.relu)
- dec_m3 = slim.conv2d_transpose(
- dec_m2, 1, [5, 5], stride=2, activation_fn=tf.nn.sigmoid)
-
- # Image decoder
- dec_i0 = slim.fully_connected(
- h1, (_FEATURE_MAP_SIZE**2) * f_dim * 4, activation_fn=tf.nn.relu)
- dec_i0 = tf.reshape(
- dec_i0, [-1, _FEATURE_MAP_SIZE, _FEATURE_MAP_SIZE, f_dim * 4])
-
- dec_i1 = slim.conv2d_transpose(
- dec_i0, f_dim * 2, [5, 5], stride=2, activation_fn=tf.nn.relu)
- dec_i2 = slim.conv2d_transpose(
- dec_i1, f_dim * 2, [5, 5], stride=2, activation_fn=tf.nn.relu)
- dec_i3 = slim.conv2d_transpose(
- dec_i2, 3, [5, 5], stride=2, activation_fn=tf.nn.tanh)
-
- outputs = dict()
- outputs['images'] = _postprocess_im(dec_i3)
- outputs['masks'] = dec_m3
- return outputs
diff --git a/research/ptn/nets/ptn_rotator.py b/research/ptn/nets/ptn_rotator.py
deleted file mode 100644
index 2cc73bb8dfe2edb624d9fa56ecd95347fbf0cf3f..0000000000000000000000000000000000000000
--- a/research/ptn/nets/ptn_rotator.py
+++ /dev/null
@@ -1,58 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Creates rotator network model.
-
-This model performs the out-of-plane rotations given input image and action.
-The action is either no-op, rotate clockwise or rotate counter-clockwise.
-
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-
-def bilinear(input_x, input_y, output_size):
- """Define the bilinear transformation layer."""
- shape_x = input_x.get_shape().as_list()
- shape_y = input_y.get_shape().as_list()
-
- weights_initializer = tf.truncated_normal_initializer(stddev=0.02,
- seed=1)
- biases_initializer = tf.constant_initializer(0.0)
-
- matrix = tf.get_variable("Matrix", [shape_x[1], shape_y[1], output_size],
- tf.float32, initializer=weights_initializer)
- bias = tf.get_variable("Bias", [output_size],
- initializer=biases_initializer)
- # Add to GraphKeys.MODEL_VARIABLES
- tf.contrib.framework.add_model_variable(matrix)
- tf.contrib.framework.add_model_variable(bias)
- # Define the transformation
- h0 = tf.matmul(input_x, tf.reshape(matrix,
- [shape_x[1], shape_y[1]*output_size]))
- h0 = tf.reshape(h0, [-1, shape_y[1], output_size])
- h1 = tf.tile(tf.reshape(input_y, [-1, shape_y[1], 1]),
- [1, 1, output_size])
- h1 = tf.multiply(h0, h1)
- return tf.reduce_sum(h1, 1) + bias
-
-
-def model(poses, actions, params, is_training):
- """Model for performing rotation."""
- del is_training # Unused
- return bilinear(poses, actions, params.z_dim)
diff --git a/research/ptn/nets/ptn_vox_decoder.py b/research/ptn/nets/ptn_vox_decoder.py
deleted file mode 100644
index 87ea27fa2bfcffc6fd9b9292686096e06f36e6a6..0000000000000000000000000000000000000000
--- a/research/ptn/nets/ptn_vox_decoder.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Training decoder as used in PTN (NIPS16)."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-slim = tf.contrib.slim
-
-
-@tf.contrib.framework.add_arg_scope
-def conv3d_transpose(inputs,
- num_outputs,
- kernel_size,
- stride=1,
- padding='SAME',
- activation_fn=tf.nn.relu,
- weights_initializer=tf.contrib.layers.xavier_initializer(),
- biases_initializer=tf.zeros_initializer(),
- reuse=None,
- trainable=True,
- scope=None):
- """Wrapper for conv3d_transpose layer.
-
- This function wraps the tf.conv3d_transpose with basic non-linearity.
- Tt creates a variable called `weights`, representing the kernel,
- that is convoled with the input. A second varibale called `biases'
- is added to the result of operation.
- """
- with tf.variable_scope(
- scope, 'Conv3d_transpose', [inputs], reuse=reuse):
- dtype = inputs.dtype.base_dtype
- kernel_d, kernel_h, kernel_w = kernel_size[0:3]
- num_filters_in = inputs.get_shape()[4]
-
- weights_shape = [kernel_d, kernel_h, kernel_w, num_outputs, num_filters_in]
- weights = tf.get_variable('weights',
- shape=weights_shape,
- dtype=dtype,
- initializer=weights_initializer,
- trainable=trainable)
- tf.contrib.framework.add_model_variable(weights)
-
- input_shape = inputs.get_shape().as_list()
- batch_size = input_shape[0]
- depth = input_shape[1]
- height = input_shape[2]
- width = input_shape[3]
-
- def get_deconv_dim(dim_size, stride_size):
- # Only support padding='SAME'.
- if isinstance(dim_size, tf.Tensor):
- dim_size = tf.multiply(dim_size, stride_size)
- elif dim_size is not None:
- dim_size *= stride_size
- return dim_size
-
- out_depth = get_deconv_dim(depth, stride)
- out_height = get_deconv_dim(height, stride)
- out_width = get_deconv_dim(width, stride)
-
- out_shape = [batch_size, out_depth, out_height, out_width, num_outputs]
- outputs = tf.nn.conv3d_transpose(inputs, weights, out_shape,
- [1, stride, stride, stride, 1],
- padding=padding)
-
- outputs.set_shape(out_shape)
-
- if biases_initializer is not None:
- biases = tf.get_variable('biases',
- shape=[num_outputs,],
- dtype=dtype,
- initializer=biases_initializer,
- trainable=trainable)
- tf.contrib.framework.add_model_variable(biases)
- outputs = tf.nn.bias_add(outputs, biases)
-
- if activation_fn:
- outputs = activation_fn(outputs)
- return outputs
-
-
-def model(identities, params, is_training):
- """Model transforming embedding to voxels."""
- del is_training # Unused
- f_dim = params.f_dim
-
- # Please refer to the original implementation: github.com/xcyan/nips16_PTN
- # In TF replication, we use a slightly different architecture.
- with slim.arg_scope(
- [slim.fully_connected, conv3d_transpose],
- weights_initializer=tf.truncated_normal_initializer(stddev=0.02, seed=1)):
- h0 = slim.fully_connected(
- identities, 4 * 4 * 4 * f_dim * 8, activation_fn=tf.nn.relu)
- h1 = tf.reshape(h0, [-1, 4, 4, 4, f_dim * 8])
- h1 = conv3d_transpose(
- h1, f_dim * 4, [4, 4, 4], stride=2, activation_fn=tf.nn.relu)
- h2 = conv3d_transpose(
- h1, int(f_dim * 3 / 2), [5, 5, 5], stride=2, activation_fn=tf.nn.relu)
- h3 = conv3d_transpose(
- h2, 1, [6, 6, 6], stride=2, activation_fn=tf.nn.sigmoid)
- return h3
diff --git a/research/ptn/pretrain_rotator.py b/research/ptn/pretrain_rotator.py
deleted file mode 100644
index 6307f2d4f6ad4341105de7e265411d10e55f61c9..0000000000000000000000000000000000000000
--- a/research/ptn/pretrain_rotator.py
+++ /dev/null
@@ -1,236 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Contains training plan for the Rotator model (Pretraining in NIPS16)."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-
-import numpy as np
-from six.moves import xrange
-import tensorflow as tf
-
-from tensorflow import app
-
-import model_rotator as model
-
-flags = tf.app.flags
-slim = tf.contrib.slim
-
-flags.DEFINE_string('inp_dir', '',
- 'Directory path containing the input data (tfrecords).')
-flags.DEFINE_string(
- 'dataset_name', 'shapenet_chair',
- 'Dataset name that is to be used for training and evaluation.')
-flags.DEFINE_integer('z_dim', 512, '')
-flags.DEFINE_integer('a_dim', 3, '')
-flags.DEFINE_integer('f_dim', 64, '')
-flags.DEFINE_integer('fc_dim', 1024, '')
-flags.DEFINE_integer('num_views', 24, 'Num of viewpoints in the input data.')
-flags.DEFINE_integer('image_size', 64,
- 'Input images dimension (pixels) - width & height.')
-flags.DEFINE_integer('step_size', 1, 'Steps to take for rotation in pretraining.')
-flags.DEFINE_integer('batch_size', 32, 'Batch size for training.')
-flags.DEFINE_string('encoder_name', 'ptn_encoder',
- 'Name of the encoder network being used.')
-flags.DEFINE_string('decoder_name', 'ptn_im_decoder',
- 'Name of the decoder network being used.')
-flags.DEFINE_string('rotator_name', 'ptn_rotator',
- 'Name of the rotator network being used.')
-# Save options
-flags.DEFINE_string('checkpoint_dir', '/tmp/ptn_train/',
- 'Directory path for saving trained models and other data.')
-flags.DEFINE_string('model_name', 'deeprotator_pretrain',
- 'Name of the model used in naming the TF job. Must be different for each run.')
-flags.DEFINE_string('init_model', None,
- 'Checkpoint path of the model to initialize with.')
-flags.DEFINE_integer('save_every', 1000,
- 'Average period of steps after which we save a model.')
-# Optimization
-flags.DEFINE_float('image_weight', 10, 'Weighting factor for image loss.')
-flags.DEFINE_float('mask_weight', 1, 'Weighting factor for mask loss.')
-flags.DEFINE_float('learning_rate', 0.0001, 'Learning rate.')
-flags.DEFINE_float('weight_decay', 0.001, 'Weight decay parameter while training.')
-flags.DEFINE_float('clip_gradient_norm', 0, 'Gradient clim norm, leave 0 if no gradient clipping.')
-flags.DEFINE_integer('max_number_of_steps', 320000, 'Maximum number of steps for training.')
-# Summary
-flags.DEFINE_integer('save_summaries_secs', 15, 'Seconds interval for dumping TF summaries.')
-flags.DEFINE_integer('save_interval_secs', 60 * 5, 'Seconds interval to save models.')
-# Distribution
-flags.DEFINE_string('master', '', 'The address of the tensorflow master if running distributed.')
-flags.DEFINE_bool('sync_replicas', False, 'Whether to sync gradients between replicas for optimizer.')
-flags.DEFINE_integer('worker_replicas', 1, 'Number of worker replicas (train tasks).')
-flags.DEFINE_integer('backup_workers', 0, 'Number of backup workers.')
-flags.DEFINE_integer('ps_tasks', 0, 'Number of ps tasks.')
-flags.DEFINE_integer('task', 0,
- 'Task identifier flag to be set for each task running in distributed manner. Task number 0 '
- 'will be chosen as the chief.')
-
-FLAGS = flags.FLAGS
-
-
-def main(_):
- train_dir = os.path.join(FLAGS.checkpoint_dir, FLAGS.model_name, 'train')
- save_image_dir = os.path.join(train_dir, 'images')
- if not os.path.exists(train_dir):
- os.makedirs(train_dir)
- if not os.path.exists(save_image_dir):
- os.makedirs(save_image_dir)
-
- g = tf.Graph()
- with g.as_default():
- with tf.device(tf.train.replica_device_setter(FLAGS.ps_tasks)):
- global_step = slim.get_or_create_global_step()
- ##########
- ## data ##
- ##########
- train_data = model.get_inputs(
- FLAGS.inp_dir,
- FLAGS.dataset_name,
- 'train',
- FLAGS.batch_size,
- FLAGS.image_size,
- is_training=True)
- inputs = model.preprocess(train_data, FLAGS.step_size)
- ###########
- ## model ##
- ###########
- model_fn = model.get_model_fn(FLAGS, is_training=True)
- outputs = model_fn(inputs)
- ##########
- ## loss ##
- ##########
- task_loss = model.get_loss(inputs, outputs, FLAGS)
- regularization_loss = model.get_regularization_loss(
- ['encoder', 'rotator', 'decoder'], FLAGS)
- loss = task_loss + regularization_loss
- ###############
- ## optimizer ##
- ###############
- optimizer = tf.train.AdamOptimizer(FLAGS.learning_rate)
- if FLAGS.sync_replicas:
- optimizer = tf.train.SyncReplicasOptimizer(
- optimizer,
- replicas_to_aggregate=FLAGS.workers_replicas - FLAGS.backup_workers,
- total_num_replicas=FLAGS.worker_replicas)
-
- ##############
- ## train_op ##
- ##############
- train_op = model.get_train_op_for_scope(
- loss, optimizer, ['encoder', 'rotator', 'decoder'], FLAGS)
- ###########
- ## saver ##
- ###########
- saver = tf.train.Saver(max_to_keep=np.minimum(5,
- FLAGS.worker_replicas + 1))
-
- if FLAGS.task == 0:
- val_data = model.get_inputs(
- FLAGS.inp_dir,
- FLAGS.dataset_name,
- 'val',
- FLAGS.batch_size,
- FLAGS.image_size,
- is_training=False)
- val_inputs = model.preprocess(val_data, FLAGS.step_size)
- # Note: don't compute loss here
- reused_model_fn = model.get_model_fn(
- FLAGS, is_training=False, reuse=True)
- val_outputs = reused_model_fn(val_inputs)
- with tf.device(tf.DeviceSpec(device_type='CPU')):
- if FLAGS.step_size == 1:
- vis_input_images = val_inputs['images_0'] * 255.0
- vis_output_images = val_inputs['images_1'] * 255.0
- vis_pred_images = val_outputs['images_1'] * 255.0
- vis_pred_masks = (val_outputs['masks_1'] * (-1) + 1) * 255.0
- else:
- rep_times = int(np.ceil(32.0 / float(FLAGS.step_size)))
- vis_list_1 = []
- vis_list_2 = []
- vis_list_3 = []
- vis_list_4 = []
- for j in xrange(rep_times):
- for k in xrange(FLAGS.step_size):
- vis_input_image = val_inputs['images_0'][j],
- vis_output_image = val_inputs['images_%d' % (k + 1)][j]
- vis_pred_image = val_outputs['images_%d' % (k + 1)][j]
- vis_pred_mask = val_outputs['masks_%d' % (k + 1)][j]
- vis_list_1.append(tf.expand_dims(vis_input_image, 0))
- vis_list_2.append(tf.expand_dims(vis_output_image, 0))
- vis_list_3.append(tf.expand_dims(vis_pred_image, 0))
- vis_list_4.append(tf.expand_dims(vis_pred_mask, 0))
-
- vis_list_1 = tf.reshape(
- tf.stack(vis_list_1), [
- rep_times * FLAGS.step_size, FLAGS.image_size,
- FLAGS.image_size, 3
- ])
- vis_list_2 = tf.reshape(
- tf.stack(vis_list_2), [
- rep_times * FLAGS.step_size, FLAGS.image_size,
- FLAGS.image_size, 3
- ])
- vis_list_3 = tf.reshape(
- tf.stack(vis_list_3), [
- rep_times * FLAGS.step_size, FLAGS.image_size,
- FLAGS.image_size, 3
- ])
- vis_list_4 = tf.reshape(
- tf.stack(vis_list_4), [
- rep_times * FLAGS.step_size, FLAGS.image_size,
- FLAGS.image_size, 1
- ])
-
- vis_input_images = vis_list_1 * 255.0
- vis_output_images = vis_list_2 * 255.0
- vis_pred_images = vis_list_3 * 255.0
- vis_pred_masks = (vis_list_4 * (-1) + 1) * 255.0
-
- write_disk_op = model.write_disk_grid(
- global_step=global_step,
- summary_freq=FLAGS.save_every,
- log_dir=save_image_dir,
- input_images=vis_input_images,
- output_images=vis_output_images,
- pred_images=vis_pred_images,
- pred_masks=vis_pred_masks)
- with tf.control_dependencies([write_disk_op]):
- train_op = tf.identity(train_op)
-
- #############
- ## init_fn ##
- #############
- init_fn = model.get_init_fn(['encoder, ' 'rotator', 'decoder'], FLAGS)
-
- ##############
- ## training ##
- ##############
- slim.learning.train(
- train_op=train_op,
- logdir=train_dir,
- init_fn=init_fn,
- master=FLAGS.master,
- is_chief=(FLAGS.task == 0),
- number_of_steps=FLAGS.max_number_of_steps,
- saver=saver,
- save_summaries_secs=FLAGS.save_summaries_secs,
- save_interval_secs=FLAGS.save_interval_secs)
-
-
-if __name__ == '__main__':
- app.run()
diff --git a/research/ptn/train_ptn.py b/research/ptn/train_ptn.py
deleted file mode 100644
index 1b42245d4c2d7fc445e275aa4e933e89e6108699..0000000000000000000000000000000000000000
--- a/research/ptn/train_ptn.py
+++ /dev/null
@@ -1,230 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Contains training plan for the Im2vox model."""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-
-import numpy as np
-import tensorflow as tf
-
-from tensorflow import app
-
-import model_ptn
-
-flags = tf.app.flags
-slim = tf.contrib.slim
-
-flags.DEFINE_string('inp_dir',
- '',
- 'Directory path containing the input data (tfrecords).')
-flags.DEFINE_string(
- 'dataset_name', 'shapenet_chair',
- 'Dataset name that is to be used for training and evaluation.')
-flags.DEFINE_integer('z_dim', 512, '')
-flags.DEFINE_integer('f_dim', 64, '')
-flags.DEFINE_integer('fc_dim', 1024, '')
-flags.DEFINE_integer('num_views', 24, 'Num of viewpoints in the input data.')
-flags.DEFINE_integer('image_size', 64,
- 'Input images dimension (pixels) - width & height.')
-flags.DEFINE_integer('vox_size', 32, 'Voxel prediction dimension.')
-flags.DEFINE_integer('step_size', 24, 'Steps to take in rotation to fetch viewpoints.')
-flags.DEFINE_integer('batch_size', 6, 'Batch size while training.')
-flags.DEFINE_float('focal_length', 0.866, 'Focal length parameter used in perspective projection.')
-flags.DEFINE_float('focal_range', 1.732, 'Focal length parameter used in perspective projection.')
-flags.DEFINE_string('encoder_name', 'ptn_encoder',
- 'Name of the encoder network being used.')
-flags.DEFINE_string('decoder_name', 'ptn_vox_decoder',
- 'Name of the decoder network being used.')
-flags.DEFINE_string('projector_name', 'perspective_projector',
- 'Name of the projector network being used.')
-# Save options
-flags.DEFINE_string('checkpoint_dir', '/tmp/ptn_train/',
- 'Directory path for saving trained models and other data.')
-flags.DEFINE_string('model_name', 'ptn_finetune',
- 'Name of the model used in naming the TF job. Must be different for each run.')
-flags.DEFINE_string('init_model', None,
- 'Checkpoint path of the model to initialize with.')
-flags.DEFINE_integer('save_every', 1000,
- 'Average period of steps after which we save a model.')
-# Optimization
-flags.DEFINE_float('proj_weight', 10, 'Weighting factor for projection loss.')
-flags.DEFINE_float('volume_weight', 0, 'Weighting factor for volume loss.')
-flags.DEFINE_float('viewpoint_weight', 1, 'Weighting factor for viewpoint loss.')
-flags.DEFINE_float('learning_rate', 0.0001, 'Learning rate.')
-flags.DEFINE_float('weight_decay', 0.001, 'Weight decay parameter while training.')
-flags.DEFINE_float('clip_gradient_norm', 0, 'Gradient clim norm, leave 0 if no gradient clipping.')
-flags.DEFINE_integer('max_number_of_steps', 10000, 'Maximum number of steps for training.')
-# Summary
-flags.DEFINE_integer('save_summaries_secs', 15, 'Seconds interval for dumping TF summaries.')
-flags.DEFINE_integer('save_interval_secs', 60 * 5, 'Seconds interval to save models.')
-
-# Scheduling
-flags.DEFINE_string('master', '', 'The address of the tensorflow master')
-flags.DEFINE_bool('sync_replicas', False, 'Whether to sync gradients between replicas for optimizer.')
-flags.DEFINE_integer('worker_replicas', 1, 'Number of worker replicas (train tasks).')
-flags.DEFINE_integer('backup_workers', 0, 'Number of backup workers.')
-flags.DEFINE_integer('ps_tasks', 0, 'Number of ps tasks.')
-flags.DEFINE_integer('task', 0,
- 'Task identifier flag to be set for each task running in distributed manner. Task number 0 '
- 'will be chosen as the chief.')
-
-FLAGS = flags.FLAGS
-
-
-def main(_):
- train_dir = os.path.join(FLAGS.checkpoint_dir, FLAGS.model_name, 'train')
- save_image_dir = os.path.join(train_dir, 'images')
- if not os.path.exists(train_dir):
- os.makedirs(train_dir)
- if not os.path.exists(save_image_dir):
- os.makedirs(save_image_dir)
-
- g = tf.Graph()
- with g.as_default():
- with tf.device(tf.train.replica_device_setter(FLAGS.ps_tasks)):
- global_step = slim.get_or_create_global_step()
- ###########
- ## model ##
- ###########
- model = model_ptn.model_PTN(FLAGS)
- ##########
- ## data ##
- ##########
- train_data = model.get_inputs(
- FLAGS.inp_dir,
- FLAGS.dataset_name,
- 'train',
- FLAGS.batch_size,
- FLAGS.image_size,
- FLAGS.vox_size,
- is_training=True)
- inputs = model.preprocess(train_data, FLAGS.step_size)
- ##############
- ## model_fn ##
- ##############
- model_fn = model.get_model_fn(
- is_training=True, reuse=False, run_projection=True)
- outputs = model_fn(inputs)
- ##################
- ## train_scopes ##
- ##################
- if FLAGS.init_model:
- train_scopes = ['decoder']
- init_scopes = ['encoder']
- else:
- train_scopes = ['encoder', 'decoder']
-
- ##########
- ## loss ##
- ##########
- task_loss = model.get_loss(inputs, outputs)
-
- regularization_loss = model.get_regularization_loss(train_scopes)
- loss = task_loss + regularization_loss
- ###############
- ## optimizer ##
- ###############
- optimizer = tf.train.AdamOptimizer(FLAGS.learning_rate)
- if FLAGS.sync_replicas:
- optimizer = tf.train.SyncReplicasOptimizer(
- optimizer,
- replicas_to_aggregate=FLAGS.workers_replicas - FLAGS.backup_workers,
- total_num_replicas=FLAGS.worker_replicas)
-
- ##############
- ## train_op ##
- ##############
- train_op = model.get_train_op_for_scope(loss, optimizer, train_scopes)
- ###########
- ## saver ##
- ###########
- saver = tf.train.Saver(max_to_keep=np.minimum(5,
- FLAGS.worker_replicas + 1))
-
- if FLAGS.task == 0:
- params = FLAGS
- params.batch_size = params.num_views
- params.step_size = 1
- model.set_params(params)
- val_data = model.get_inputs(
- params.inp_dir,
- params.dataset_name,
- 'val',
- params.batch_size,
- params.image_size,
- params.vox_size,
- is_training=False)
- val_inputs = model.preprocess(val_data, params.step_size)
- # Note: don't compute loss here
- reused_model_fn = model.get_model_fn(is_training=False, reuse=True)
- val_outputs = reused_model_fn(val_inputs)
-
- with tf.device(tf.DeviceSpec(device_type='CPU')):
- vis_input_images = val_inputs['images_1'] * 255.0
- vis_gt_projs = (val_outputs['masks_1'] * (-1) + 1) * 255.0
- vis_pred_projs = (val_outputs['projs_1'] * (-1) + 1) * 255.0
-
- vis_gt_projs = tf.concat([vis_gt_projs] * 3, axis=3)
- vis_pred_projs = tf.concat([vis_pred_projs] * 3, axis=3)
- # rescale
- new_size = [FLAGS.image_size] * 2
- vis_gt_projs = tf.image.resize_nearest_neighbor(
- vis_gt_projs, new_size)
- vis_pred_projs = tf.image.resize_nearest_neighbor(
- vis_pred_projs, new_size)
- # flip
- # vis_gt_projs = utils.image_flipud(vis_gt_projs)
- # vis_pred_projs = utils.image_flipud(vis_pred_projs)
- # vis_gt_projs is of shape [batch, height, width, channels]
- write_disk_op = model.write_disk_grid(
- global_step=global_step,
- log_dir=save_image_dir,
- input_images=vis_input_images,
- gt_projs=vis_gt_projs,
- pred_projs=vis_pred_projs,
- input_voxels=val_inputs['voxels'],
- output_voxels=val_outputs['voxels_1'])
- with tf.control_dependencies([write_disk_op]):
- train_op = tf.identity(train_op)
-
- #############
- ## init_fn ##
- #############
- if FLAGS.init_model:
- init_fn = model.get_init_fn(init_scopes)
- else:
- init_fn = None
-
- ##############
- ## training ##
- ##############
- slim.learning.train(
- train_op=train_op,
- logdir=train_dir,
- init_fn=init_fn,
- master=FLAGS.master,
- is_chief=(FLAGS.task == 0),
- number_of_steps=FLAGS.max_number_of_steps,
- saver=saver,
- save_summaries_secs=FLAGS.save_summaries_secs,
- save_interval_secs=FLAGS.save_interval_secs)
-
-
-if __name__ == '__main__':
- app.run()
diff --git a/research/ptn/utils.py b/research/ptn/utils.py
deleted file mode 100644
index adf71731edb78740c6716d7abddfd77b557aaecd..0000000000000000000000000000000000000000
--- a/research/ptn/utils.py
+++ /dev/null
@@ -1,119 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Utility functions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import StringIO
-import matplotlib
-matplotlib.use('Agg')
-from matplotlib import pylab as p
-# axes3d is being used implictly for visualization.
-from mpl_toolkits.mplot3d import axes3d as p3 # pylint:disable=unused-import
-import numpy as np
-from PIL import Image
-from skimage import measure
-from six.moves import xrange
-
-import tensorflow as tf
-
-
-def save_image(inp_array, image_file):
- """Function that dumps the image to disk."""
- inp_array = np.clip(inp_array, 0, 255).astype(np.uint8)
- image = Image.fromarray(inp_array)
- buf = StringIO.StringIO()
- image.save(buf, format='JPEG')
- with open(image_file, 'w') as f:
- f.write(buf.getvalue())
- return None
-
-
-def image_flipud(images):
- """Function that flip (up-down) the np image."""
- quantity = images.get_shape().as_list()[0]
- image_list = []
- for k in xrange(quantity):
- image_list.append(tf.image.flip_up_down(images[k, :, :, :]))
- outputs = tf.stack(image_list)
- return outputs
-
-
-def resize_image(inp_array, new_height, new_width):
- """Function that resize the np image."""
- inp_array = np.clip(inp_array, 0, 255).astype(np.uint8)
- image = Image.fromarray(inp_array)
- # Reverse order
- image = image.resize((new_width, new_height))
- return np.array(image)
-
-
-def display_voxel(points, vis_size=128):
- """Function to display 3D voxel."""
- try:
- data = visualize_voxel_spectral(points, vis_size)
- except ValueError:
- data = visualize_voxel_scatter(points, vis_size)
- return data
-
-
-def visualize_voxel_spectral(points, vis_size=128):
- """Function to visualize voxel (spectral)."""
- points = np.rint(points)
- points = np.swapaxes(points, 0, 2)
- fig = p.figure(figsize=(1, 1), dpi=vis_size)
- verts, faces = measure.marching_cubes_classic(points, 0, spacing=(0.1, 0.1, 0.1))
- ax = fig.add_subplot(111, projection='3d')
- ax.plot_trisurf(
- verts[:, 0], verts[:, 1], faces, verts[:, 2], cmap='Spectral_r', lw=0.1)
- ax.set_axis_off()
- fig.tight_layout(pad=0)
- fig.canvas.draw()
- data = np.fromstring(
- fig.canvas.tostring_rgb(), dtype=np.uint8, sep='').reshape(
- vis_size, vis_size, 3)
- p.close('all')
- return data
-
-
-def visualize_voxel_scatter(points, vis_size=128):
- """Function to visualize voxel (scatter)."""
- points = np.rint(points)
- points = np.swapaxes(points, 0, 2)
- fig = p.figure(figsize=(1, 1), dpi=vis_size)
- ax = fig.add_subplot(111, projection='3d')
- x = []
- y = []
- z = []
- (x_dimension, y_dimension, z_dimension) = points.shape
- for i in range(x_dimension):
- for j in range(y_dimension):
- for k in range(z_dimension):
- if points[i, j, k]:
- x.append(i)
- y.append(j)
- z.append(k)
- ax.scatter3D(x, y, z)
- ax.set_axis_off()
- fig.tight_layout(pad=0)
- fig.canvas.draw()
- data = np.fromstring(
- fig.canvas.tostring_rgb(), dtype=np.uint8, sep='').reshape(
- vis_size, vis_size, 3)
- p.close('all')
- return data
diff --git a/research/qa_kg/README.md b/research/qa_kg/README.md
deleted file mode 100644
index 7224ac8f8f5ff2f6c0003c5bbd9ac1717fe7addf..0000000000000000000000000000000000000000
--- a/research/qa_kg/README.md
+++ /dev/null
@@ -1,83 +0,0 @@
-
-
-
-
-# Module networks for question answering on knowledge graph
-
-This code repository contains a TensorFlow model for question answering on
-knowledge graph with end-to-end module networks. The original paper describing
-end-to-end module networks is as follows.
-
-R. Hu, J. Andreas, M. Rohrbach, T. Darrell, K. Saenko, *Learning to Reason:
-End-to-End Module Networks for Visual Question Answering*. in arXiv preprint
-arXiv:1704.05526, 2017. ([PDF](https://arxiv.org/pdf/1704.05526.pdf))
-
-```
-@article{hu2017learning,
- title={Learning to Reason: End-to-End Module Networks for Visual Question Answering},
- author={Hu, Ronghang and Andreas, Jacob and Rohrbach, Marcus and Darrell, Trevor and Saenko, Kate},
- journal={arXiv preprint arXiv:1704.05526},
- year={2017}
-}
-```
-
-The code in this repository is based on the original
-[implementation](https://github.com/ronghanghu/n2nmn) for this paper.
-
-## Requirements
-
-1. Install TensorFlow 1.0.0. Follow the [official
- guide](https://www.tensorflow.org/install/). Please note that newer or older
- versions of TensorFlow may fail to work due to incompatibility with
- TensorFlow Fold.
-2. Install TensorFlow Fold. Follow the
- [setup instructions](https://github.com/tensorflow/fold/blob/master/tensorflow_fold/g3doc/setup.md).
- TensorFlow Fold only supports Linux platform. We have not tested
- the code on other platforms.
-
-## Data
-
-1. Download the [MetaQA dataset](https://goo.gl/f3AmcY). Click the button
- `MetaQA` and then click `Download` in the drop-down list. Extract the zip
- file after downloading completed. Read the documents there for dataset
- details.
-2. Move the `MetaQA` folder to the root directory of this repository.
-
-## How to use this code
-
-We provide an experiment folder `exp_1_hop`, which applies the implemented model
-to the 1-hop vanilla dataset in MetaQA. More experiment folders are coming soon.
-
-Currently, we provide code for training with ground truth layout, and testing
-the saved model. Configurations can be modified in `config.py`. They can also be
-set via command line parameters.
-
-To train the model:
-
-```
-python exp_1_hop/train_gt_layout.py
-```
-
-To test the saved model (need to provide the snapshot name):
-
-```
-python exp_1_hop/test.py --snapshot_name 00010000
-```
-
-## Model introduction
-
-1. In this model, we store the knowledge graph in a key-value based memory. For
- each knowledge graph edge (subject, relation, object), we use the (subject,
- relation) as the key and the object as the value.
-2. All entities and relations are embedded as fixed-dimension vectors. These
- embeddings are also end-to-end learned.
-3. Neural modules can separately operate on either the key side or the value
- side.
-4. The attention is shared between keys and corresponding values.
-5. The answer output is based on the attention-weighted sum over keys or
- values, depending on the output module.
-
-## Contact
-Authors: Yuyu Zhang, Xin Pan
-
-Pull requests and issues: @yuyuz
diff --git a/research/qa_kg/exp_1_hop/config.py b/research/qa_kg/exp_1_hop/config.py
deleted file mode 100644
index 95d8cf5f512243279365ad99c9f582c945d6c8e2..0000000000000000000000000000000000000000
--- a/research/qa_kg/exp_1_hop/config.py
+++ /dev/null
@@ -1,80 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import argparse
-import os
-
-
-def str2bool(v):
- return v.lower() in ('true', '1')
-
-
-def add_argument_group(name):
- arg = parser.add_argument_group(name)
- arg_lists.append(arg)
- return arg
-
-
-def get_config():
- config, unparsed = parser.parse_known_args()
- return config, unparsed
-
-
-arg_lists = []
-parser = argparse.ArgumentParser()
-work_dir = os.path.abspath(os.path.join(__file__, '../../'))
-
-net_arg = add_argument_group('Network')
-net_arg.add_argument('--lstm_dim', type=int, default=128)
-net_arg.add_argument('--num_layers', type=int, default=1)
-net_arg.add_argument('--embed_dim_txt', type=int, default=128)
-net_arg.add_argument('--embed_dim_nmn', type=int, default=128)
-net_arg.add_argument(
- '--T_encoder', type=int, default=0) # will be updated when reading data
-net_arg.add_argument('--T_decoder', type=int, default=5)
-
-train_arg = add_argument_group('Training')
-train_arg.add_argument('--train_tag', type=str, default='n2nmn')
-train_arg.add_argument('--batch_size', type=int, default=128)
-train_arg.add_argument('--max_iter', type=int, default=1000000)
-train_arg.add_argument('--weight_decay', type=float, default=1e-5)
-train_arg.add_argument('--baseline_decay', type=float, default=0.99)
-train_arg.add_argument('--max_grad_norm', type=float, default=10)
-train_arg.add_argument('--random_seed', type=int, default=123)
-
-data_arg = add_argument_group('Data')
-data_path = work_dir + '/MetaQA/'
-data_arg.add_argument('--KB_file', type=str, default=data_path + 'kb.txt')
-data_arg.add_argument(
- '--data_dir', type=str, default=data_path + '1-hop/vanilla/')
-data_arg.add_argument('--train_data_file', type=str, default='qa_train.txt')
-data_arg.add_argument('--dev_data_file', type=str, default='qa_dev.txt')
-data_arg.add_argument('--test_data_file', type=str, default='qa_test.txt')
-
-exp_arg = add_argument_group('Experiment')
-exp_path = work_dir + '/exp_1_hop/'
-exp_arg.add_argument('--exp_dir', type=str, default=exp_path)
-
-log_arg = add_argument_group('Log')
-log_arg.add_argument('--log_dir', type=str, default='logs')
-log_arg.add_argument('--log_interval', type=int, default=1000)
-log_arg.add_argument('--num_log_samples', type=int, default=3)
-log_arg.add_argument(
- '--log_level', type=str, default='INFO', choices=['INFO', 'DEBUG', 'WARN'])
-
-io_arg = add_argument_group('IO')
-io_arg.add_argument('--model_dir', type=str, default='model')
-io_arg.add_argument('--snapshot_interval', type=int, default=1000)
-io_arg.add_argument('--output_dir', type=str, default='output')
diff --git a/research/qa_kg/exp_1_hop/test.py b/research/qa_kg/exp_1_hop/test.py
deleted file mode 100644
index 2937c0d582a54f6de2702a4f741963e0fe2b2f72..0000000000000000000000000000000000000000
--- a/research/qa_kg/exp_1_hop/test.py
+++ /dev/null
@@ -1,135 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import os
-import sys
-sys.path.append(os.path.abspath(os.path.join(__file__, '../../')))
-import numpy as np
-import tensorflow as tf
-from config import get_config
-from model_n2nmn.assembler import Assembler
-from model_n2nmn.model import Model
-from util.data_reader import DataReader
-from util.data_reader import SampleBuilder
-from util.misc import prepare_dirs_and_logger
-
-FLAGS = tf.flags.FLAGS
-tf.flags.DEFINE_string('snapshot_name', '00001000', 'snapshot file name')
-
-
-def main(_):
- config = prepare_dirs_and_logger(config_raw)
-
- rng = np.random.RandomState(config.random_seed)
- tf.set_random_seed(config.random_seed)
- config.rng = rng
-
- config.module_names = ['_key_find', '_key_filter', '_val_desc', '']
- config.gt_layout_tokens = ['_key_find', '_key_filter', '_val_desc', '']
- assembler = Assembler(config)
-
- sample_builder = SampleBuilder(config)
- config = sample_builder.config # update T_encoder according to data
- data_test = sample_builder.data_all['test']
- data_reader_test = DataReader(
- config, data_test, assembler, shuffle=False, one_pass=True)
-
- num_vocab_txt = len(sample_builder.dict_all)
- num_vocab_nmn = len(assembler.module_names)
- num_choices = len(sample_builder.dict_all)
-
- # Network inputs
- text_seq_batch = tf.placeholder(tf.int32, [None, None])
- seq_len_batch = tf.placeholder(tf.int32, [None])
-
- # The model
- model = Model(
- config,
- sample_builder.kb,
- text_seq_batch,
- seq_len_batch,
- num_vocab_txt=num_vocab_txt,
- num_vocab_nmn=num_vocab_nmn,
- EOS_idx=assembler.EOS_idx,
- num_choices=num_choices,
- decoder_sampling=False)
- compiler = model.compiler
- scores = model.scores
-
- sess = tf.Session()
- sess.run(tf.global_variables_initializer())
- snapshot_file = os.path.join(config.model_dir, FLAGS.snapshot_name)
- tf.logging.info('Snapshot file: %s' % snapshot_file)
-
- snapshot_saver = tf.train.Saver()
- snapshot_saver.restore(sess, snapshot_file)
-
- # Evaluation metrics
- num_questions = len(data_test.Y)
- tf.logging.info('# of test questions: %d' % num_questions)
-
- answer_correct = 0
- layout_correct = 0
- layout_valid = 0
- for batch in data_reader_test.batches():
- # set up input and output tensors
- h = sess.partial_run_setup(
- fetches=[model.predicted_tokens, scores],
- feeds=[text_seq_batch, seq_len_batch, compiler.loom_input_tensor])
-
- # Part 1: Generate module layout
- tokens = sess.partial_run(
- h,
- fetches=model.predicted_tokens,
- feed_dict={
- text_seq_batch: batch['input_seq_batch'],
- seq_len_batch: batch['seq_len_batch']
- })
-
- # Compute accuracy of the predicted layout
- gt_tokens = batch['gt_layout_batch']
- layout_correct += np.sum(
- np.all(
- np.logical_or(tokens == gt_tokens, gt_tokens == assembler.EOS_idx),
- axis=0))
-
- # Assemble the layout tokens into network structure
- expr_list, expr_validity_array = assembler.assemble(tokens)
- layout_valid += np.sum(expr_validity_array)
- labels = batch['ans_label_batch']
- # Build TensorFlow Fold input for NMN
- expr_feed = compiler.build_feed_dict(expr_list)
-
- # Part 2: Run NMN and learning steps
- scores_val = sess.partial_run(h, scores, feed_dict=expr_feed)
-
- # Compute accuracy
- predictions = np.argmax(scores_val, axis=1)
- answer_correct += np.sum(
- np.logical_and(expr_validity_array, predictions == labels))
-
- answer_accuracy = answer_correct * 1.0 / num_questions
- layout_accuracy = layout_correct * 1.0 / num_questions
- layout_validity = layout_valid * 1.0 / num_questions
-
- tf.logging.info('test answer accuracy = %f, '
- 'test layout accuracy = %f, '
- 'test layout validity = %f' %
- (answer_accuracy, layout_accuracy, layout_validity))
-
-
-if __name__ == '__main__':
- config_raw, unparsed = get_config()
- tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)
diff --git a/research/qa_kg/exp_1_hop/train_gt_layout.py b/research/qa_kg/exp_1_hop/train_gt_layout.py
deleted file mode 100644
index 02bafc428afc4d1f2b39d6bd56e6098d4b1b8ca7..0000000000000000000000000000000000000000
--- a/research/qa_kg/exp_1_hop/train_gt_layout.py
+++ /dev/null
@@ -1,194 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import os
-import sys
-sys.path.append(os.path.abspath(os.path.join(__file__, '../../')))
-import numpy as np
-import tensorflow as tf
-from config import get_config
-from model_n2nmn.assembler import Assembler
-from model_n2nmn.model import Model
-from util.data_reader import DataReader
-from util.data_reader import SampleBuilder
-from util.misc import prepare_dirs_and_logger
-from util.misc import save_config
-from util.misc import show_all_variables
-
-
-def main(_):
- config = prepare_dirs_and_logger(config_raw)
- save_config(config)
-
- rng = np.random.RandomState(config.random_seed)
- tf.set_random_seed(config.random_seed)
- config.rng = rng
-
- config.module_names = ['_key_find', '_key_filter', '_val_desc', '']
- config.gt_layout_tokens = ['_key_find', '_key_filter', '_val_desc', '']
- assembler = Assembler(config)
-
- sample_builder = SampleBuilder(config)
- config = sample_builder.config # update T_encoder according to data
- data_train = sample_builder.data_all['train']
- data_reader_train = DataReader(
- config, data_train, assembler, shuffle=True, one_pass=False)
-
- num_vocab_txt = len(sample_builder.dict_all)
- num_vocab_nmn = len(assembler.module_names)
- num_choices = len(sample_builder.dict_all)
-
- # Network inputs
- text_seq_batch = tf.placeholder(tf.int32, [None, None])
- seq_len_batch = tf.placeholder(tf.int32, [None])
- ans_label_batch = tf.placeholder(tf.int32, [None])
- use_gt_layout = tf.constant(True, dtype=tf.bool)
- gt_layout_batch = tf.placeholder(tf.int32, [None, None])
-
- # The model for training
- model = Model(
- config,
- sample_builder.kb,
- text_seq_batch,
- seq_len_batch,
- num_vocab_txt=num_vocab_txt,
- num_vocab_nmn=num_vocab_nmn,
- EOS_idx=assembler.EOS_idx,
- num_choices=num_choices,
- decoder_sampling=True,
- use_gt_layout=use_gt_layout,
- gt_layout_batch=gt_layout_batch)
- compiler = model.compiler
- scores = model.scores
- log_seq_prob = model.log_seq_prob
-
- # Loss function
- softmax_loss_per_sample = tf.nn.sparse_softmax_cross_entropy_with_logits(
- logits=scores, labels=ans_label_batch)
- # The final per-sample loss, which is loss for valid expr
- # and invalid_expr_loss for invalid expr
- final_loss_per_sample = softmax_loss_per_sample # All exprs are valid
-
- avg_sample_loss = tf.reduce_mean(final_loss_per_sample)
- seq_likelihood_loss = tf.reduce_mean(-log_seq_prob)
-
- total_training_loss = seq_likelihood_loss + avg_sample_loss
- total_loss = total_training_loss + config.weight_decay * model.l2_reg
-
- # Train with Adam optimizer
- solver = tf.train.AdamOptimizer()
- gradients = solver.compute_gradients(total_loss)
-
- # Clip gradient by L2 norm
- gradients = [(tf.clip_by_norm(g, config.max_grad_norm), v)
- for g, v in gradients]
- solver_op = solver.apply_gradients(gradients)
-
- # Training operation
- with tf.control_dependencies([solver_op]):
- train_step = tf.constant(0)
-
- # Write summary to TensorBoard
- log_writer = tf.summary.FileWriter(config.log_dir, tf.get_default_graph())
-
- loss_ph = tf.placeholder(tf.float32, [])
- entropy_ph = tf.placeholder(tf.float32, [])
- accuracy_ph = tf.placeholder(tf.float32, [])
- summary_train = [
- tf.summary.scalar('avg_sample_loss', loss_ph),
- tf.summary.scalar('entropy', entropy_ph),
- tf.summary.scalar('avg_accuracy', accuracy_ph)
- ]
- log_step_train = tf.summary.merge(summary_train)
-
- # Training
- sess = tf.Session()
- sess.run(tf.global_variables_initializer())
- snapshot_saver = tf.train.Saver(max_to_keep=None) # keep all snapshots
- show_all_variables()
-
- avg_accuracy = 0
- accuracy_decay = 0.99
- for n_iter, batch in enumerate(data_reader_train.batches()):
- if n_iter >= config.max_iter:
- break
-
- # set up input and output tensors
- h = sess.partial_run_setup(
- fetches=[
- model.predicted_tokens, model.entropy_reg, scores, avg_sample_loss,
- train_step
- ],
- feeds=[
- text_seq_batch, seq_len_batch, gt_layout_batch,
- compiler.loom_input_tensor, ans_label_batch
- ])
-
- # Part 1: Generate module layout
- tokens, entropy_reg_val = sess.partial_run(
- h,
- fetches=(model.predicted_tokens, model.entropy_reg),
- feed_dict={
- text_seq_batch: batch['input_seq_batch'],
- seq_len_batch: batch['seq_len_batch'],
- gt_layout_batch: batch['gt_layout_batch']
- })
- # Assemble the layout tokens into network structure
- expr_list, expr_validity_array = assembler.assemble(tokens)
- # all exprs should be valid (since they are ground-truth)
- assert np.all(expr_validity_array)
- labels = batch['ans_label_batch']
- # Build TensorFlow Fold input for NMN
- expr_feed = compiler.build_feed_dict(expr_list)
- expr_feed[ans_label_batch] = labels
-
- # Part 2: Run NMN and learning steps
- scores_val, avg_sample_loss_val, _ = sess.partial_run(
- h, fetches=(scores, avg_sample_loss, train_step), feed_dict=expr_feed)
-
- # Compute accuracy
- predictions = np.argmax(scores_val, axis=1)
- accuracy = np.mean(
- np.logical_and(expr_validity_array, predictions == labels))
- avg_accuracy += (1 - accuracy_decay) * (accuracy - avg_accuracy)
-
- # Add to TensorBoard summary
- if (n_iter + 1) % config.log_interval == 0:
- tf.logging.info('iter = %d\n\t'
- 'loss = %f, accuracy (cur) = %f, '
- 'accuracy (avg) = %f, entropy = %f' %
- (n_iter + 1, avg_sample_loss_val, accuracy, avg_accuracy,
- -entropy_reg_val))
- summary = sess.run(
- fetches=log_step_train,
- feed_dict={
- loss_ph: avg_sample_loss_val,
- entropy_ph: -entropy_reg_val,
- accuracy_ph: avg_accuracy
- })
- log_writer.add_summary(summary, n_iter + 1)
-
- # Save snapshot
- if (n_iter + 1) % config.snapshot_interval == 0:
- snapshot_file = os.path.join(config.model_dir, '%08d' % (n_iter + 1))
- snapshot_saver.save(sess, snapshot_file, write_meta_graph=False)
- tf.logging.info('Snapshot saved to %s' % snapshot_file)
-
- tf.logging.info('Run finished.')
-
-
-if __name__ == '__main__':
- config_raw, unparsed = get_config()
- tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)
diff --git a/research/qa_kg/model_n2nmn/__init__.py b/research/qa_kg/model_n2nmn/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/qa_kg/model_n2nmn/assembler.py b/research/qa_kg/model_n2nmn/assembler.py
deleted file mode 100644
index f5839f6f49d7d30774195749405d43ed014a0049..0000000000000000000000000000000000000000
--- a/research/qa_kg/model_n2nmn/assembler.py
+++ /dev/null
@@ -1,145 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import numpy as np
-
-# the number of attention input to each module
-_module_input_num = {
- '_key_find': 0,
- '_key_filter': 1,
- '_val_desc': 1}
-_module_output_type = {
- '_key_find': 'att',
- '_key_filter': 'att',
- '_val_desc': 'ans'
-}
-
-INVALID_EXPR = 'INVALID_EXPR'
-
-
-class Assembler:
-
- def __init__(self, config):
- # read the module list, and record the index of each module and
- self.module_names = config.module_names
- # find the index of
- for n_s in range(len(self.module_names)):
- if self.module_names[n_s] == '':
- self.EOS_idx = n_s
- break
- # build a dictionary from module name to token index
- self.name2idx_dict = {
- name: n_s
- for n_s, name in enumerate(self.module_names)
- }
-
- def module_list2tokens(self, module_list, max_len=None):
- layout_tokens = [self.name2idx_dict[name] for name in module_list]
- if max_len is not None:
- if len(module_list) >= max_len:
- raise ValueError('Not enough time steps to add ')
- layout_tokens += [self.EOS_idx] * (max_len - len(module_list))
- return layout_tokens
-
- def _layout_tokens2str(self, layout_tokens):
- return ' '.join([self.module_names[idx] for idx in layout_tokens])
-
- def _invalid_expr(self, layout_tokens, error_str):
- return {
- 'module': INVALID_EXPR,
- 'expr_str': self._layout_tokens2str(layout_tokens),
- 'error': error_str
- }
-
- def _assemble_layout_tokens(self, layout_tokens, batch_idx):
- # Every module takes a time_idx as the index from LSTM hidden states
- # (even if it doesn't need it, like _and), and different arity of
- # attention inputs. The output type can be either attention or answer
- #
- # The final assembled expression for each instance is as follows:
- # expr_type :=
- # {'module': '_find', 'output_type': 'att', 'time_idx': idx}
- # | {'module': '_relocate', 'output_type': 'att', 'time_idx': idx,
- # 'inputs_0': }
- # | {'module': '_and', 'output_type': 'att', 'time_idx': idx,
- # 'inputs_0': , 'inputs_1': )}
- # | {'module': '_describe', 'output_type': 'ans', 'time_idx': idx,
- # 'inputs_0': }
- # | {'module': INVALID_EXPR, 'expr_str': '...', 'error': '...',
- # 'assembly_loss': } (for invalid expressions)
- #
-
- # A valid layout must contain . Assembly fails if it doesn't.
- if not np.any(layout_tokens == self.EOS_idx):
- return self._invalid_expr(layout_tokens, 'cannot find ')
-
- # Decoding Reverse Polish Notation with a stack
- decoding_stack = []
- for t in range(len(layout_tokens)):
- # decode a module/operation
- module_idx = layout_tokens[t]
- if module_idx == self.EOS_idx:
- break
- module_name = self.module_names[module_idx]
- expr = {
- 'module': module_name,
- 'output_type': _module_output_type[module_name],
- 'time_idx': t,
- 'batch_idx': batch_idx
- }
-
- input_num = _module_input_num[module_name]
- # Check if there are enough input in the stack
- if len(decoding_stack) < input_num:
- # Invalid expression. Not enough input.
- return self._invalid_expr(layout_tokens,
- 'not enough input for ' + module_name)
-
- # Get the input from stack
- for n_input in range(input_num - 1, -1, -1):
- stack_top = decoding_stack.pop()
- if stack_top['output_type'] != 'att':
- # Invalid expression. Input must be attention
- return self._invalid_expr(layout_tokens,
- 'input incompatible for ' + module_name)
- expr['input_%d' % n_input] = stack_top
-
- decoding_stack.append(expr)
-
- # After decoding the reverse polish expression, there should be exactly
- # one expression in the stack
- if len(decoding_stack) != 1:
- return self._invalid_expr(
- layout_tokens,
- 'final stack size not equal to 1 (%d remains)' % len(decoding_stack))
-
- result = decoding_stack[0]
- # The result type should be answer, not attention
- if result['output_type'] != 'ans':
- return self._invalid_expr(layout_tokens,
- 'result type must be ans, not att')
- return result
-
- def assemble(self, layout_tokens_batch):
- # layout_tokens_batch is a numpy array with shape [max_dec_len, batch_size],
- # containing module tokens and , in Reverse Polish Notation.
- _, batch_size = layout_tokens_batch.shape
- expr_list = [
- self._assemble_layout_tokens(layout_tokens_batch[:, batch_i], batch_i)
- for batch_i in range(batch_size)
- ]
- expr_validity = np.array(
- [expr['module'] != INVALID_EXPR for expr in expr_list], np.bool)
- return expr_list, expr_validity
diff --git a/research/qa_kg/model_n2nmn/model.py b/research/qa_kg/model_n2nmn/model.py
deleted file mode 100644
index 56896f438006ac28c82d8e92ded2d7bbf8cf3863..0000000000000000000000000000000000000000
--- a/research/qa_kg/model_n2nmn/model.py
+++ /dev/null
@@ -1,119 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import numpy as np
-import tensorflow as tf
-import tensorflow_fold as td
-from model_n2nmn import netgen_att
-from model_n2nmn import assembler
-from model_n2nmn.modules import Modules
-
-
-class Model:
-
- def __init__(self,
- config,
- kb,
- text_seq_batch,
- seq_length_batch,
- num_vocab_txt,
- num_vocab_nmn,
- EOS_idx,
- num_choices,
- decoder_sampling,
- use_gt_layout=None,
- gt_layout_batch=None,
- scope='neural_module_network',
- reuse=None):
- with tf.variable_scope(scope, reuse=reuse):
- # Part 1: Seq2seq RNN to generate module layout tokens
-
- embedding_mat = tf.get_variable(
- 'embedding_mat', [num_vocab_txt, config.embed_dim_txt],
- initializer=tf.contrib.layers.xavier_initializer())
-
- with tf.variable_scope('layout_generation'):
- att_seq2seq = netgen_att.AttentionSeq2Seq(
- config, text_seq_batch, seq_length_batch, num_vocab_txt,
- num_vocab_nmn, EOS_idx, decoder_sampling, embedding_mat,
- use_gt_layout, gt_layout_batch)
- self.att_seq2seq = att_seq2seq
- predicted_tokens = att_seq2seq.predicted_tokens
- token_probs = att_seq2seq.token_probs
- word_vecs = att_seq2seq.word_vecs
- neg_entropy = att_seq2seq.neg_entropy
- self.atts = att_seq2seq.atts
-
- self.predicted_tokens = predicted_tokens
- self.token_probs = token_probs
- self.word_vecs = word_vecs
- self.neg_entropy = neg_entropy
-
- # log probability of each generated sequence
- self.log_seq_prob = tf.reduce_sum(tf.log(token_probs), axis=0)
-
- # Part 2: Neural Module Network
- with tf.variable_scope('layout_execution'):
- modules = Modules(config, kb, word_vecs, num_choices, embedding_mat)
- self.modules = modules
- # Recursion of modules
- att_shape = [len(kb)]
- # Forward declaration of module recursion
- att_expr_decl = td.ForwardDeclaration(td.PyObjectType(),
- td.TensorType(att_shape))
- # _key_find
- case_key_find = td.Record([('time_idx', td.Scalar(dtype='int32')),
- ('batch_idx', td.Scalar(dtype='int32'))])
- case_key_find = case_key_find >> td.ScopedLayer(
- modules.KeyFindModule, name_or_scope='KeyFindModule')
- # _key_filter
- case_key_filter = td.Record([('input_0', att_expr_decl()),
- ('time_idx', td.Scalar('int32')),
- ('batch_idx', td.Scalar('int32'))])
- case_key_filter = case_key_filter >> td.ScopedLayer(
- modules.KeyFilterModule, name_or_scope='KeyFilterModule')
- recursion_cases = td.OneOf(
- td.GetItem('module'),
- {'_key_find': case_key_find,
- '_key_filter': case_key_filter})
- att_expr_decl.resolve_to(recursion_cases)
- # _val_desc: output scores for choice (for valid expressions)
- predicted_scores = td.Record([('input_0', recursion_cases),
- ('time_idx', td.Scalar('int32')),
- ('batch_idx', td.Scalar('int32'))])
- predicted_scores = predicted_scores >> td.ScopedLayer(
- modules.ValDescribeModule, name_or_scope='ValDescribeModule')
-
- # For invalid expressions, define a dummy answer
- # so that all answers have the same form
- INVALID = assembler.INVALID_EXPR
- dummy_scores = td.Void() >> td.FromTensor(
- np.zeros(num_choices, np.float32))
- output_scores = td.OneOf(
- td.GetItem('module'),
- {'_val_desc': predicted_scores,
- INVALID: dummy_scores})
-
- # compile and get the output scores
- self.compiler = td.Compiler.create(output_scores)
- self.scores = self.compiler.output_tensors[0]
-
- # Regularization: Entropy + L2
- self.entropy_reg = tf.reduce_mean(neg_entropy)
- module_weights = [
- v for v in tf.trainable_variables()
- if (scope in v.op.name and v.op.name.endswith('weights'))
- ]
- self.l2_reg = tf.add_n([tf.nn.l2_loss(v) for v in module_weights])
diff --git a/research/qa_kg/model_n2nmn/modules.py b/research/qa_kg/model_n2nmn/modules.py
deleted file mode 100644
index 8c7a7370f81a5b81d08c87136688765dce556ada..0000000000000000000000000000000000000000
--- a/research/qa_kg/model_n2nmn/modules.py
+++ /dev/null
@@ -1,131 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import tensorflow as tf
-
-
-class Modules:
-
- def __init__(self, config, kb, word_vecs, num_choices, embedding_mat):
- self.config = config
-
- self.embedding_mat = embedding_mat
-
- # kb has shape [N_kb, 3]
- self.kb = kb
- self.embed_keys_e, self.embed_keys_r, self.embed_vals_e = self.embed_kb()
-
- # word_vecs has shape [T_decoder, N, D_txt]
- self.word_vecs = word_vecs
- self.num_choices = num_choices
-
- def embed_kb(self):
- keys_e, keys_r, vals_e = [], [], []
- for idx_sub, idx_rel, idx_obj in self.kb:
- keys_e.append(idx_sub)
- keys_r.append(idx_rel)
- vals_e.append(idx_obj)
- embed_keys_e = tf.nn.embedding_lookup(self.embedding_mat, keys_e)
- embed_keys_r = tf.nn.embedding_lookup(self.embedding_mat, keys_r)
- embed_vals_e = tf.nn.embedding_lookup(self.embedding_mat, vals_e)
- return embed_keys_e, embed_keys_r, embed_vals_e
-
- def _slice_word_vecs(self, time_idx, batch_idx):
- # this callable will be wrapped into a td.Function
- # In TF Fold, batch_idx and time_idx are both [N_batch, 1] tensors
- # time is highest dim in word_vecs
- joint_index = tf.stack([time_idx, batch_idx], axis=1)
- return tf.gather_nd(self.word_vecs, joint_index)
-
- # All the layers are wrapped with td.ScopedLayer
- def KeyFindModule(self,
- time_idx,
- batch_idx,
- scope='KeyFindModule',
- reuse=None):
- # In TF Fold, batch_idx and time_idx are both [N_batch, 1] tensors
- text_param = self._slice_word_vecs(time_idx, batch_idx)
-
- # Mapping: embed_keys_e x text_param -> att
- # Input:
- # embed_keys_e: [N_kb, D_txt]
- # text_param: [N, D_txt]
- # Output:
- # att: [N, N_kb]
- #
- # Implementation:
- # 1. Elementwise multiplication between embed_key_e and text_param
- # 2. L2-normalization
- with tf.variable_scope(scope, reuse=reuse):
- m = tf.matmul(text_param, self.embed_keys_e, transpose_b=True)
- att = tf.nn.l2_normalize(m, dim=1)
- return att
-
- def KeyFilterModule(self,
- input_0,
- time_idx,
- batch_idx,
- scope='KeyFilterModule',
- reuse=None):
- att_0 = input_0
- text_param = self._slice_word_vecs(time_idx, batch_idx)
-
- # Mapping: and(embed_keys_r x text_param, att) -> att
- # Input:
- # embed_keys_r: [N_kb, D_txt]
- # text_param: [N, D_txt]
- # att_0: [N, N_kb]
- # Output:
- # att: [N, N_kb]
- #
- # Implementation:
- # 1. Elementwise multiplication between embed_key_r and text_param
- # 2. L2-normalization
- # 3. Take the elementwise-min
- with tf.variable_scope(scope, reuse=reuse):
- m = tf.matmul(text_param, self.embed_keys_r, transpose_b=True)
- att_1 = tf.nn.l2_normalize(m, dim=1)
- att = tf.minimum(att_0, att_1)
- return att
-
- def ValDescribeModule(self,
- input_0,
- time_idx,
- batch_idx,
- scope='ValDescribeModule',
- reuse=None):
- att = input_0
-
- # Mapping: att -> answer probs
- # Input:
- # embed_vals_e: [N_kb, D_txt]
- # att: [N, N_kb]
- # embedding_mat: [self.num_choices, D_txt]
- # Output:
- # answer_scores: [N, self.num_choices]
- #
- # Implementation:
- # 1. Attention-weighted sum over values
- # 2. Compute cosine similarity scores between the weighted sum and
- # each candidate answer
- with tf.variable_scope(scope, reuse=reuse):
- # weighted_sum has shape [N, D_txt]
- weighted_sum = tf.matmul(att, self.embed_vals_e)
- # scores has shape [N, self.num_choices]
- scores = tf.matmul(
- weighted_sum,
- tf.nn.l2_normalize(self.embedding_mat, dim=1),
- transpose_b=True)
- return scores
diff --git a/research/qa_kg/model_n2nmn/netgen_att.py b/research/qa_kg/model_n2nmn/netgen_att.py
deleted file mode 100644
index df6509946a5457bb07f2dfdcfab44aaf67447d0f..0000000000000000000000000000000000000000
--- a/research/qa_kg/model_n2nmn/netgen_att.py
+++ /dev/null
@@ -1,295 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import tensorflow as tf
-from util.nn import fc_layer as fc
-
-
-def _get_lstm_cell(num_layers, lstm_dim):
- cell_list = [
- tf.contrib.rnn.BasicLSTMCell(lstm_dim, state_is_tuple=True)
- for _ in range(num_layers)
- ]
- cell = tf.contrib.rnn.MultiRNNCell(cell_list, state_is_tuple=True)
- return cell
-
-
-class AttentionSeq2Seq:
-
- def __init__(self,
- config,
- text_seq_batch,
- seq_length_batch,
- num_vocab_txt,
- num_vocab_nmn,
- EOS_token,
- decoder_sampling,
- embedding_mat,
- use_gt_layout=None,
- gt_layout_batch=None,
- scope='encoder_decoder',
- reuse=None):
- self.T_decoder = config.T_decoder
- self.encoder_num_vocab = num_vocab_txt
- self.encoder_embed_dim = config.embed_dim_txt
- self.decoder_num_vocab = num_vocab_nmn
- self.decoder_embed_dim = config.embed_dim_nmn
- self.lstm_dim = config.lstm_dim
- self.num_layers = config.num_layers
- self.EOS_token = EOS_token
- self.decoder_sampling = decoder_sampling
- self.embedding_mat = embedding_mat
-
- with tf.variable_scope(scope, reuse=reuse):
- self._build_encoder(text_seq_batch, seq_length_batch)
- self._build_decoder(use_gt_layout, gt_layout_batch)
-
- def _build_encoder(self,
- text_seq_batch,
- seq_length_batch,
- scope='encoder',
- reuse=None):
- lstm_dim = self.lstm_dim
- num_layers = self.num_layers
-
- with tf.variable_scope(scope, reuse=reuse):
- T = tf.shape(text_seq_batch)[0]
- N = tf.shape(text_seq_batch)[1]
- self.T_encoder = T
- self.N = N
-
- # text_seq has shape [T, N] and embedded_seq has shape [T, N, D]
- embedded_seq = tf.nn.embedding_lookup(self.embedding_mat, text_seq_batch)
- self.embedded_input_seq = embedded_seq
-
- # The RNN
- cell = _get_lstm_cell(num_layers, lstm_dim)
-
- # encoder_outputs has shape [T, N, lstm_dim]
- encoder_outputs, encoder_states = tf.nn.dynamic_rnn(
- cell,
- embedded_seq,
- seq_length_batch,
- dtype=tf.float32,
- time_major=True,
- scope='lstm')
- self.encoder_outputs = encoder_outputs
- self.encoder_states = encoder_states
-
- # transform the encoder outputs for further attention alignments
- # encoder_outputs_flat has shape [T, N, lstm_dim]
- encoder_h_transformed = fc(
- 'encoder_h_transform',
- tf.reshape(encoder_outputs, [-1, lstm_dim]),
- output_dim=lstm_dim)
- encoder_h_transformed = tf.reshape(encoder_h_transformed,
- [T, N, lstm_dim])
- self.encoder_h_transformed = encoder_h_transformed
-
- # seq_not_finished is a shape [T, N, 1] tensor,
- # where seq_not_finished[t, n]
- # is 1 iff sequence n is not finished at time t, and 0 otherwise
- seq_not_finished = tf.less(
- tf.range(T)[:, tf.newaxis, tf.newaxis],
- seq_length_batch[:, tf.newaxis])
- seq_not_finished = tf.cast(seq_not_finished, tf.float32)
- self.seq_not_finished = seq_not_finished
-
- def _build_decoder(self,
- use_gt_layout,
- gt_layout_batch,
- scope='decoder',
- reuse=None):
- # The main difference from before is that the decoders now takes another
- # input (the attention) when computing the next step
- # T_max is the maximum length of decoded sequence (including )
- #
- # This function is for decoding only. It performs greedy search or sampling.
- # the first input is (its embedding vector) and the subsequent inputs
- # are the outputs from previous time step
- # num_vocab does not include
- #
- # use_gt_layout is None or a bool tensor, and gt_layout_batch is a tensor
- # with shape [T_max, N].
- # If use_gt_layout is not None, then when use_gt_layout is true, predict
- # exactly the tokens in gt_layout_batch, regardless of actual probability.
- # Otherwise, if sampling is True, sample from the token probability
- # If sampling is False, do greedy decoding (beam size 1)
- N = self.N
- encoder_states = self.encoder_states
- T_max = self.T_decoder
- lstm_dim = self.lstm_dim
- num_layers = self.num_layers
- EOS_token = self.EOS_token
- sampling = self.decoder_sampling
-
- with tf.variable_scope(scope, reuse=reuse):
- embedding_mat = tf.get_variable(
- 'embedding_mat', [self.decoder_num_vocab, self.decoder_embed_dim])
- # we use a separate embedding for , as it is only used in the
- # beginning of the sequence
- go_embedding = tf.get_variable('go_embedding',
- [1, self.decoder_embed_dim])
-
- with tf.variable_scope('att_prediction'):
- v = tf.get_variable('v', [lstm_dim])
- W_a = tf.get_variable(
- 'weights', [lstm_dim, lstm_dim],
- initializer=tf.contrib.layers.xavier_initializer())
- b_a = tf.get_variable(
- 'biases', lstm_dim, initializer=tf.constant_initializer(0.))
-
- # The parameters to predict the next token
- with tf.variable_scope('token_prediction'):
- W_y = tf.get_variable(
- 'weights', [lstm_dim * 2, self.decoder_num_vocab],
- initializer=tf.contrib.layers.xavier_initializer())
- b_y = tf.get_variable(
- 'biases',
- self.decoder_num_vocab,
- initializer=tf.constant_initializer(0.))
-
- # Attentional decoding
- # Loop function is called at time t BEFORE the cell execution at time t,
- # and its next_input is used as the input at time t (not t+1)
- # c.f. https://www.tensorflow.org/api_docs/python/tf/nn/raw_rnn
- mask_range = tf.reshape(
- tf.range(self.decoder_num_vocab, dtype=tf.int32), [1, -1])
- all_eos_pred = EOS_token * tf.ones([N], tf.int32)
- all_one_prob = tf.ones([N], tf.float32)
- all_zero_entropy = tf.zeros([N], tf.float32)
- if use_gt_layout is not None:
- gt_layout_mult = tf.cast(use_gt_layout, tf.int32)
- pred_layout_mult = 1 - gt_layout_mult
-
- def loop_fn(time, cell_output, cell_state, loop_state):
- if cell_output is None: # time == 0
- next_cell_state = encoder_states
- next_input = tf.tile(go_embedding, [N, 1])
- else: # time > 0
- next_cell_state = cell_state
-
- # compute the attention map over the input sequence
- # a_raw has shape [T, N, 1]
- att_raw = tf.reduce_sum(
- tf.tanh(
- tf.nn.xw_plus_b(cell_output, W_a, b_a) +
- self.encoder_h_transformed) * v,
- axis=2,
- keep_dims=True)
- # softmax along the first dimension (T) over not finished examples
- # att has shape [T, N, 1]
- att = tf.nn.softmax(att_raw, dim=0) * self.seq_not_finished
- att = att / tf.reduce_sum(att, axis=0, keep_dims=True)
- # d has shape [N, lstm_dim]
- d2 = tf.reduce_sum(att * self.encoder_outputs, axis=0)
-
- # token_scores has shape [N, num_vocab]
- token_scores = tf.nn.xw_plus_b(
- tf.concat([cell_output, d2], axis=1), W_y, b_y)
- # predict the next token (behavior depending on parameters)
- if sampling:
- # predicted_token has shape [N]
- logits = token_scores
- predicted_token = tf.cast(
- tf.reshape(tf.multinomial(token_scores, 1), [-1]), tf.int32)
- else:
- # predicted_token has shape [N]
- predicted_token = tf.cast(tf.argmax(token_scores, 1), tf.int32)
- if use_gt_layout is not None:
- predicted_token = (gt_layout_batch[time - 1] * gt_layout_mult +
- predicted_token * pred_layout_mult)
-
- # token_prob has shape [N], the probability of the predicted token
- # although token_prob is not needed for predicting the next token
- # it is needed in output (for policy gradient training)
- # [N, num_vocab]
- # mask has shape [N, num_vocab]
- mask = tf.equal(mask_range, tf.reshape(predicted_token, [-1, 1]))
- all_token_probs = tf.nn.softmax(token_scores)
- token_prob = tf.reduce_sum(
- all_token_probs * tf.cast(mask, tf.float32), axis=1)
- neg_entropy = tf.reduce_sum(
- all_token_probs * tf.log(all_token_probs), axis=1)
-
- # is_eos_predicted is a [N] bool tensor, indicating whether
- # has already been predicted previously in each sequence
- is_eos_predicted = loop_state[2]
- predicted_token_old = predicted_token
- # if has already been predicted, now predict with
- # prob 1
- predicted_token = tf.where(is_eos_predicted, all_eos_pred,
- predicted_token)
- token_prob = tf.where(is_eos_predicted, all_one_prob, token_prob)
- neg_entropy = tf.where(is_eos_predicted, all_zero_entropy,
- neg_entropy)
- is_eos_predicted = tf.logical_or(is_eos_predicted,
- tf.equal(predicted_token_old,
- EOS_token))
-
- # the prediction is from the cell output of the last step
- # timestep (t-1), feed it as input into timestep t
- next_input = tf.nn.embedding_lookup(embedding_mat, predicted_token)
-
- elements_finished = tf.greater_equal(time, T_max)
-
- # loop_state is a 5-tuple, representing
- # 1) the predicted_tokens
- # 2) the prob of predicted_tokens
- # 3) whether has already been predicted
- # 4) the negative entropy of policy (accumulated across timesteps)
- # 5) the attention
- if loop_state is None: # time == 0
- # Write the predicted token into the output
- predicted_token_array = tf.TensorArray(
- dtype=tf.int32, size=T_max, infer_shape=False)
- token_prob_array = tf.TensorArray(
- dtype=tf.float32, size=T_max, infer_shape=False)
- att_array = tf.TensorArray(
- dtype=tf.float32, size=T_max, infer_shape=False)
- next_loop_state = (predicted_token_array, token_prob_array, tf.zeros(
- [N], dtype=tf.bool), tf.zeros([N], dtype=tf.float32), att_array)
- else: # time > 0
- t_write = time - 1
- next_loop_state = (
- loop_state[0].write(t_write, predicted_token),
- loop_state[1].write(t_write, token_prob),
- is_eos_predicted,
- loop_state[3] + neg_entropy,
- loop_state[4].write(t_write, att))
- return (elements_finished, next_input, next_cell_state, cell_output,
- next_loop_state)
-
- # The RNN
- cell = _get_lstm_cell(num_layers, lstm_dim)
- _, _, decodes_ta = tf.nn.raw_rnn(cell, loop_fn, scope='lstm')
- predicted_tokens = decodes_ta[0].stack()
- token_probs = decodes_ta[1].stack()
- neg_entropy = decodes_ta[3]
- # atts has shape [T_decoder, T_encoder, N, 1]
- atts = decodes_ta[4].stack()
- self.atts = atts
- # word_vec has shape [T_decoder, N, D]
- word_vecs = tf.reduce_sum(atts * self.embedded_input_seq, axis=1)
-
- predicted_tokens.set_shape([None, None])
- token_probs.set_shape([None, None])
- neg_entropy.set_shape([None])
- word_vecs.set_shape([None, None, self.encoder_embed_dim])
-
- self.predicted_tokens = predicted_tokens
- self.token_probs = token_probs
- self.neg_entropy = neg_entropy
- self.word_vecs = word_vecs
diff --git a/research/qa_kg/util/__init__.py b/research/qa_kg/util/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/qa_kg/util/data_reader.py b/research/qa_kg/util/data_reader.py
deleted file mode 100644
index 397390af6d95b350559fbd20cc55e85a12ce03c0..0000000000000000000000000000000000000000
--- a/research/qa_kg/util/data_reader.py
+++ /dev/null
@@ -1,231 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-from collections import namedtuple
-try:
- from queue import Queue # Python 3
-except ImportError:
- from Queue import Queue # Python 2
-import re
-import threading
-import numpy as np
-import tensorflow as tf
-
-Data = namedtuple('Data', ['X', 'Y', 'MultiYs', 'qid'])
-
-
-class SampleBuilder:
-
- def __init__(self, config):
- self.config = config
-
- self.kb_raw = self.read_kb()
- self.data_raw = self.read_raw_data()
-
- # dictionary of entities, normal words, and relations
- self.dict_all = self.gen_dict()
- self.reverse_dict_all = dict(
- zip(self.dict_all.values(), self.dict_all.keys()))
-
- tf.logging.info('size of dict: %d' % len(self.dict_all))
-
- self.kb = self.build_kb()
- self.data_all = self.build_samples()
-
- def read_kb(self):
- kb_raw = []
- for line in open(self.config.KB_file):
- sub, rel, obj = line.strip().split('|')
- kb_raw.append((sub, rel, obj))
- tf.logging.info('# of KB records: %d' % len(kb_raw))
- return kb_raw
-
- def read_raw_data(self):
- data = dict()
- for name in self.config.data_files:
- raw = []
- tf.logging.info(
- 'Reading data file {}'.format(self.config.data_files[name]))
- for line in open(self.config.data_files[name]):
- question, answers = line.strip().split('\t')
- question = question.replace('],', ']') # ignore ',' in the template
- raw.append((question, answers))
- data[name] = raw
- return data
-
- def build_kb(self):
- tf.logging.info('Indexing KB...')
- kb = []
- for sub, rel, obj in self.kb_raw:
- kb.append([self.dict_all[sub], self.dict_all[rel], self.dict_all[obj]])
- return kb
-
- def gen_dict(self):
- s = set()
- for sub, rel, obj in self.kb_raw:
- s.add(sub)
- s.add(rel)
- s.add(obj)
- for name in self.data_raw:
- for question, answers in self.data_raw[name]:
- normal = re.split('\[[^\]]+\]', question)
- for phrase in normal:
- for word in phrase.split():
- s.add(word)
- s = list(s)
- d = {s[idx]: idx for idx in range(len(s))}
- return d
-
- def build_samples(self):
-
- def map_entity_idx(text):
- entities = re.findall('\[[^\]]+\]', text)
- for entity in entities:
- entity = entity[1:-1]
- index = self.dict_all[entity]
- text = text.replace('[%s]' % entity, '@%d' % index)
- return text
-
- data_all = dict()
-
- for name in self.data_raw:
- X, Y, MultiYs, qid = [], [], [], []
- for i, (question, answers) in enumerate(self.data_raw[name]):
- qdata, labels = [], []
- question = map_entity_idx(question)
- for word in question.split():
- if word[0] == '@':
- qdata.append(int(word[1:]))
- else:
- qdata.append(self.dict_all[word])
- for answer in answers.split('|'):
- labels.append(self.dict_all[answer])
- if len(qdata) > self.config.T_encoder:
- self.config.T_encoder = len(qdata)
- for label in labels:
- X.append(qdata)
- Y.append(label)
- MultiYs.append(set(labels))
- qid.append(i)
- data_all[name] = Data(X=X, Y=Y, MultiYs=MultiYs, qid=qid)
-
- return data_all
-
-
-def _run_prefetch(prefetch_queue, batch_loader, data, shuffle, one_pass,
- config):
- assert len(data.X) == len(data.Y) == len(data.MultiYs) == len(data.qid)
- num_samples = len(data.X)
- batch_size = config.batch_size
-
- n_sample = 0
- fetch_order = config.rng.permutation(num_samples)
- while True:
- sample_ids = fetch_order[n_sample:n_sample + batch_size]
- batch = batch_loader.load_one_batch(sample_ids)
- prefetch_queue.put(batch, block=True)
-
- n_sample += len(sample_ids)
- if n_sample >= num_samples:
- if one_pass:
- prefetch_queue.put(None, block=True)
- n_sample = 0
- if shuffle:
- fetch_order = config.rng.permutation(num_samples)
-
-
-class DataReader:
- def __init__(self,
- config,
- data,
- assembler,
- shuffle=True,
- one_pass=False,
- prefetch_num=10):
- self.config = config
-
- self.data = data
- self.assembler = assembler
- self.batch_loader = BatchLoader(self.config,
- self.data, self.assembler)
-
- self.shuffle = shuffle
- self.one_pass = one_pass
- self.prefetch_queue = Queue(maxsize=prefetch_num)
- self.prefetch_thread = threading.Thread(target=_run_prefetch,
- args=(self.prefetch_queue,
- self.batch_loader, self.data,
- self.shuffle, self.one_pass,
- self.config))
- self.prefetch_thread.daemon = True
- self.prefetch_thread.start()
-
- def batches(self):
- while True:
- if self.prefetch_queue.empty():
- tf.logging.warning('Waiting for data loading (IO is slow)...')
- batch = self.prefetch_queue.get(block=True)
- if batch is None:
- assert self.one_pass
- tf.logging.info('One pass finished!')
- raise StopIteration()
- yield batch
-
-
-class BatchLoader:
- def __init__(self, config,
- data, assembler):
- self.config = config
-
- self.data = data
- self.assembler = assembler
-
- self.T_encoder = config.T_encoder
- self.T_decoder = config.T_decoder
-
- tf.logging.info('T_encoder: %d' % self.T_encoder)
- tf.logging.info('T_decoder: %d' % self.T_decoder)
- tf.logging.info('batch size: %d' % self.config.batch_size)
-
- self.gt_layout_tokens = config.gt_layout_tokens
-
- def load_one_batch(self, sample_ids):
- actual_batch_size = len(sample_ids)
- input_seq_batch = np.zeros((self.T_encoder, actual_batch_size), np.int32)
- seq_len_batch = np.zeros(actual_batch_size, np.int32)
- ans_label_batch = np.zeros(actual_batch_size, np.int32)
- ans_set_labels_list = [None] * actual_batch_size
- question_id_list = [None] * actual_batch_size
- gt_layout_batch = np.zeros((self.T_decoder, actual_batch_size), np.int32)
-
- for batch_i in range(actual_batch_size):
- idx = sample_ids[batch_i]
- seq_len = len(self.data.X[idx])
- seq_len_batch[batch_i] = seq_len
- input_seq_batch[:seq_len, batch_i] = self.data.X[idx]
- ans_label_batch[batch_i] = self.data.Y[idx]
- ans_set_labels_list[batch_i] = self.data.MultiYs[idx]
- question_id_list[batch_i] = self.data.qid[idx]
-
- gt_layout_batch[:, batch_i] = self.assembler.module_list2tokens(
- self.gt_layout_tokens, self.T_decoder)
-
- batch = dict(input_seq_batch=input_seq_batch,
- seq_len_batch=seq_len_batch,
- ans_label_batch=ans_label_batch,
- gt_layout_batch=gt_layout_batch,
- ans_set_labels_list=ans_set_labels_list,
- question_id_list=question_id_list)
- return batch
diff --git a/research/qa_kg/util/misc.py b/research/qa_kg/util/misc.py
deleted file mode 100644
index 9a0199bb403709f3c04e58c17951459febdb40f4..0000000000000000000000000000000000000000
--- a/research/qa_kg/util/misc.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-from datetime import datetime
-import json
-import logging
-import os
-import tensorflow as tf
-import tensorflow.contrib.slim as slim
-
-
-def prepare_dirs_and_logger(config):
- formatter = logging.Formatter('%(asctime)s:%(levelname)s::%(message)s')
- logger = logging.getLogger('tensorflow')
-
- for hdlr in logger.handlers:
- logger.removeHandler(hdlr)
-
- handler = logging.StreamHandler()
- handler.setFormatter(formatter)
-
- logger.addHandler(handler)
- logger.setLevel(tf.logging.INFO)
-
- config.log_dir = os.path.join(config.exp_dir, config.log_dir,
- config.train_tag)
- config.model_dir = os.path.join(config.exp_dir, config.model_dir,
- config.train_tag)
- config.output_dir = os.path.join(config.exp_dir, config.output_dir,
- config.train_tag)
-
- for path in [
- config.log_dir, config.model_dir, config.output_dir
- ]:
- if not os.path.exists(path):
- os.makedirs(path)
-
- config.data_files = {
- 'train': os.path.join(config.data_dir, config.train_data_file),
- 'dev': os.path.join(config.data_dir, config.dev_data_file),
- 'test': os.path.join(config.data_dir, config.test_data_file)
- }
-
- return config
-
-
-def get_time():
- return datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
-
-
-def show_all_variables():
- model_vars = tf.trainable_variables()
- slim.model_analyzer.analyze_vars(model_vars, print_info=True)
-
-
-def save_config(config):
- param_path = os.path.join(config.model_dir, 'params.json')
-
- tf.logging.info('log dir: %s' % config.log_dir)
- tf.logging.info('model dir: %s' % config.model_dir)
- tf.logging.info('param path: %s' % param_path)
- tf.logging.info('output dir: %s' % config.output_dir)
-
- with open(param_path, 'w') as f:
- f.write(json.dumps(config.__dict__, indent=4, sort_keys=True))
diff --git a/research/qa_kg/util/nn.py b/research/qa_kg/util/nn.py
deleted file mode 100644
index 38ba02b2ecac1cea51308287a48e3062ee51fa81..0000000000000000000000000000000000000000
--- a/research/qa_kg/util/nn.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 2017 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import tensorflow as tf
-
-
-def fc_layer(name,
- bottom,
- output_dim,
- bias_term=True,
- weights_initializer=None,
- biases_initializer=None,
- reuse=None):
- # flatten bottom input
- shape = bottom.get_shape().as_list()
- input_dim = 1
- for d in shape[1:]:
- input_dim *= d
- flat_bottom = tf.reshape(bottom, [-1, input_dim])
-
- # weights and biases variables
- with tf.variable_scope(name, reuse=reuse):
- # initialize the variables
- if weights_initializer is None:
- weights_initializer = tf.contrib.layers.xavier_initializer()
- if bias_term and biases_initializer is None:
- biases_initializer = tf.constant_initializer(0.)
-
- # weights has shape [input_dim, output_dim]
- weights = tf.get_variable(
- 'weights', [input_dim, output_dim], initializer=weights_initializer)
- if bias_term:
- biases = tf.get_variable(
- 'biases', output_dim, initializer=biases_initializer)
- if not reuse:
- tf.add_to_collection(tf.GraphKeys.REGULARIZATION_LOSSES,
- tf.nn.l2_loss(weights))
-
- if bias_term:
- fc = tf.nn.xw_plus_b(flat_bottom, weights, biases)
- else:
- fc = tf.matmul(flat_bottom, weights)
- return fc
diff --git a/research/real_nvp/README.md b/research/real_nvp/README.md
deleted file mode 100644
index c20ef111eb070be94bf6c11ea15ec1ce9d2ad686..0000000000000000000000000000000000000000
--- a/research/real_nvp/README.md
+++ /dev/null
@@ -1,282 +0,0 @@
-
-
-
-
-# Real NVP in TensorFlow
-
-*A Tensorflow implementation of the training procedure of*
-[*Density estimation using Real NVP*](https://arxiv.org/abs/1605.08803)*, by
-Laurent Dinh, Jascha Sohl-Dickstein and Samy Bengio, for Imagenet
-(32x32 and 64x64), CelebA and LSUN Including the scripts to
-put the datasets in `.tfrecords` format.*
-
-We are happy to open source the code for *Real NVP*, a novel approach to
-density estimation using deep neural networks that enables tractable density
-estimation and efficient one-pass inference and sampling. This model
-successfully decomposes images into hierarchical features ranging from
-high-level concepts to low-resolution details. Visualizations are available
-[here](http://goo.gl/yco14s).
-
-## Installation
-* python 2.7:
- * python 3 support is not available yet
-* pip (python package manager)
- * `apt-get install python-pip` on Ubuntu
- * `brew` installs pip along with python on OSX
-* Install the dependencies for [LSUN](https://github.com/fyu/lsun.git)
- * Install [OpenCV](http://opencv.org/)
- * `pip install numpy lmdb`
-* Install the python dependencies
- * `pip install scipy scikit-image Pillow`
-* Install the
-[latest Tensorflow Pip package](https://www.tensorflow.org/get_started/os_setup.html#using-pip)
-for Python 2.7
-
-## Getting Started
-Once you have successfully installed the dependencies, you can start by
-downloading the repository:
-```shell
-git clone --recursive https://github.com/tensorflow/models.git
-```
-Afterward, you can use the utilities in this folder prepare the datasets.
-
-## Preparing datasets
-### CelebA
-For [*CelebA*](http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html), download
-`img_align_celeba.zip` from the Dropbox link on this
-[page](http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html) under the
-link *Align&Cropped Images* in the *Img* directory and `list_eval_partition.txt`
-under the link *Train/Val/Test Partitions* in the *Eval* directory. Then do:
-
-```shell
-mkdir celeba
-cd celeba
-unzip img_align_celeba.zip
-```
-
-We'll format the training subset:
-```shell
-python2.7 ../models/real_nvp/celeba_formatting.py \
- --partition_fn list_eval_partition.txt \
- --file_out celeba_train \
- --fn_root img_align_celeba \
- --set 0
-```
-
-Then the validation subset:
-```shell
-python2.7 ../models/real_nvp/celeba_formatting.py \
- --partition_fn list_eval_partition.txt \
- --file_out celeba_valid \
- --fn_root img_align_celeba \
- --set 1
-```
-
-And finally the test subset:
-```shell
-python2.7 ../models/real_nvp/celeba_formatting.py \
- --partition_fn list_eval_partition.txt \
- --file_out celeba_test \
- --fn_root img_align_celeba \
- --set 2
-```
-
-Afterward:
-```shell
-cd ..
-```
-
-### Small Imagenet
-Downloading the [*small Imagenet*](http://image-net.org/small/download.php)
-dataset is more straightforward and can be done
-entirely in Shell:
-```shell
-mkdir small_imnet
-cd small_imnet
-for FILENAME in train_32x32.tar valid_32x32.tar train_64x64.tar valid_64x64.tar
-do
- curl -O http://image-net.org/small/$FILENAME
- tar -xvf $FILENAME
-done
-```
-
-Then, you can format the datasets as follow:
-```shell
-for DIRNAME in train_32x32 valid_32x32 train_64x64 valid_64x64
-do
- python2.7 ../models/real_nvp/imnet_formatting.py \
- --file_out $DIRNAME \
- --fn_root $DIRNAME
-done
-cd ..
-```
-
-### LSUN
-To prepare the [*LSUN*](http://lsun.cs.princeton.edu/2016/) dataset, we will
-need to use the code associated:
-```shell
-git clone https://github.com/fyu/lsun.git
-cd lsun
-```
-Then we'll download the db files:
-```shell
-for CATEGORY in bedroom church_outdoor tower
-do
- python2.7 download.py -c $CATEGORY
- unzip "$CATEGORY"_train_lmdb.zip
- unzip "$CATEGORY"_val_lmdb.zip
- python2.7 data.py export "$CATEGORY"_train_lmdb \
- --out_dir "$CATEGORY"_train --flat
- python2.7 data.py export "$CATEGORY"_val_lmdb \
- --out_dir "$CATEGORY"_val --flat
-done
-```
-
-Finally, we then format the dataset into `.tfrecords`:
-```shell
-for CATEGORY in bedroom church_outdoor tower
-do
- python2.7 ../models/real_nvp/lsun_formatting.py \
- --file_out "$CATEGORY"_train \
- --fn_root "$CATEGORY"_train
- python2.7 ../models/real_nvp/lsun_formatting.py \
- --file_out "$CATEGORY"_val \
- --fn_root "$CATEGORY"_val
-done
-cd ..
-```
-
-
-## Training
-We'll give an example on how to train a model on the small Imagenet
-dataset (32x32):
-```shell
-cd models/real_nvp/
-python2.7 real_nvp_multiscale_dataset.py \
---image_size 32 \
---hpconfig=n_scale=4,base_dim=32,clip_gradient=100,residual_blocks=4 \
---dataset imnet \
---traindir /tmp/real_nvp_imnet32/train \
---logdir /tmp/real_nvp_imnet32/train \
---data_path ../../small_imnet/train_32x32_?????.tfrecords
-```
-In parallel, you can run the script to generate visualization from the model:
-```shell
-python2.7 real_nvp_multiscale_dataset.py \
---image_size 32 \
---hpconfig=n_scale=4,base_dim=32,clip_gradient=100,residual_blocks=4 \
---dataset imnet \
---traindir /tmp/real_nvp_imnet32/train \
---logdir /tmp/real_nvp_imnet32/sample \
---data_path ../../small_imnet/valid_32x32_?????.tfrecords \
---mode sample
-```
-Additionally, you can also run in the script to evaluate the model on the
-validation set:
-```shell
-python2.7 real_nvp_multiscale_dataset.py \
---image_size 32 \
---hpconfig=n_scale=4,base_dim=32,clip_gradient=100,residual_blocks=4 \
---dataset imnet \
---traindir /tmp/real_nvp_imnet32/train \
---logdir /tmp/real_nvp_imnet32/eval \
---data_path ../../small_imnet/valid_32x32_?????.tfrecords \
---eval_set_size 50000
---mode eval
-```
-The visualizations and validation set evaluation can be seen through
-[Tensorboard](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/tensorboard/README.md).
-
-Another example would be how to run the model on LSUN (bedroom category):
-```shell
-# train the model
-python2.7 real_nvp_multiscale_dataset.py \
---image_size 64 \
---hpconfig=n_scale=5,base_dim=32,clip_gradient=100,residual_blocks=4 \
---dataset lsun \
---traindir /tmp/real_nvp_church_outdoor/train \
---logdir /tmp/real_nvp_church_outdoor/train \
---data_path ../../lsun/church_outdoor_train_?????.tfrecords
-```
-
-```shell
-# sample from the model
-python2.7 real_nvp_multiscale_dataset.py \
---image_size 64 \
---hpconfig=n_scale=5,base_dim=32,clip_gradient=100,residual_blocks=4 \
---dataset lsun \
---traindir /tmp/real_nvp_church_outdoor/train \
---logdir /tmp/real_nvp_church_outdoor/sample \
---data_path ../../lsun/church_outdoor_val_?????.tfrecords \
---mode sample
-```
-
-```shell
-# evaluate the model
-python2.7 real_nvp_multiscale_dataset.py \
---image_size 64 \
---hpconfig=n_scale=5,base_dim=32,clip_gradient=100,residual_blocks=4 \
---dataset lsun \
---traindir /tmp/real_nvp_church_outdoor/train \
---logdir /tmp/real_nvp_church_outdoor/eval \
---data_path ../../lsun/church_outdoor_val_?????.tfrecords \
---eval_set_size 300
---mode eval
-```
-
-Finally, we'll give the commands to run the model on the CelebA dataset:
-```shell
-# train the model
-python2.7 real_nvp_multiscale_dataset.py \
---image_size 64 \
---hpconfig=n_scale=5,base_dim=32,clip_gradient=100,residual_blocks=4 \
---dataset lsun \
---traindir /tmp/real_nvp_celeba/train \
---logdir /tmp/real_nvp_celeba/train \
---data_path ../../celeba/celeba_train.tfrecords
-```
-
-```shell
-# sample from the model
-python2.7 real_nvp_multiscale_dataset.py \
---image_size 64 \
---hpconfig=n_scale=5,base_dim=32,clip_gradient=100,residual_blocks=4 \
---dataset celeba \
---traindir /tmp/real_nvp_celeba/train \
---logdir /tmp/real_nvp_celeba/sample \
---data_path ../../celeba/celeba_valid.tfrecords \
---mode sample
-```
-
-```shell
-# evaluate the model on validation set
-python2.7 real_nvp_multiscale_dataset.py \
---image_size 64 \
---hpconfig=n_scale=5,base_dim=32,clip_gradient=100,residual_blocks=4 \
---dataset celeba \
---traindir /tmp/real_nvp_celeba/train \
---logdir /tmp/real_nvp_celeba/eval_valid \
---data_path ../../celeba/celeba_valid.tfrecords \
---eval_set_size 19867
---mode eval
-
-# evaluate the model on test set
-python2.7 real_nvp_multiscale_dataset.py \
---image_size 64 \
---hpconfig=n_scale=5,base_dim=32,clip_gradient=100,residual_blocks=4 \
---dataset celeba \
---traindir /tmp/real_nvp_celeba/train \
---logdir /tmp/real_nvp_celeba/eval_test \
---data_path ../../celeba/celeba_test.tfrecords \
---eval_set_size 19962
---mode eval
-```
-
-## Credits
-This code was written by Laurent Dinh
-([@laurent-dinh](https://github.com/laurent-dinh)) with
-the help of
-Jascha Sohl-Dickstein ([@Sohl-Dickstein](https://github.com/Sohl-Dickstein)
-and [jaschasd@google.com](mailto:jaschasd@google.com)),
-Samy Bengio, Jon Shlens, Sherry Moore and
-David Andersen.
diff --git a/research/real_nvp/__init__.py b/research/real_nvp/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/real_nvp/celeba_formatting.py b/research/real_nvp/celeba_formatting.py
deleted file mode 100644
index e03571086d88763264d7660aa5e9db5e9074dec5..0000000000000000000000000000000000000000
--- a/research/real_nvp/celeba_formatting.py
+++ /dev/null
@@ -1,96 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-r"""CelebA dataset formating.
-
-Download img_align_celeba.zip from
-http://mmlab.ie.cuhk.edu.hk/projects/CelebA.html under the
-link "Align&Cropped Images" in the "Img" directory and list_eval_partition.txt
-under the link "Train/Val/Test Partitions" in the "Eval" directory. Then do:
-unzip img_align_celeba.zip
-
-Use the script as follow:
-python celeba_formatting.py \
- --partition_fn [PARTITION_FILE_PATH] \
- --file_out [OUTPUT_FILE_PATH_PREFIX] \
- --fn_root [CELEBA_FOLDER] \
- --set [SUBSET_INDEX]
-
-"""
-
-from __future__ import print_function
-
-import os
-import os.path
-
-import scipy.io
-import scipy.io.wavfile
-import scipy.ndimage
-import tensorflow as tf
-
-
-tf.flags.DEFINE_string("file_out", "",
- "Filename of the output .tfrecords file.")
-tf.flags.DEFINE_string("fn_root", "", "Name of root file path.")
-tf.flags.DEFINE_string("partition_fn", "", "Partition file path.")
-tf.flags.DEFINE_string("set", "", "Name of subset.")
-
-FLAGS = tf.flags.FLAGS
-
-
-def _int64_feature(value):
- return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
-
-
-def _bytes_feature(value):
- return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
-
-
-def main():
- """Main converter function."""
- # Celeb A
- with open(FLAGS.partition_fn, "r") as infile:
- img_fn_list = infile.readlines()
- img_fn_list = [elem.strip().split() for elem in img_fn_list]
- img_fn_list = [elem[0] for elem in img_fn_list if elem[1] == FLAGS.set]
- fn_root = FLAGS.fn_root
- num_examples = len(img_fn_list)
-
- file_out = "%s.tfrecords" % FLAGS.file_out
- writer = tf.python_io.TFRecordWriter(file_out)
- for example_idx, img_fn in enumerate(img_fn_list):
- if example_idx % 1000 == 0:
- print(example_idx, "/", num_examples)
- image_raw = scipy.ndimage.imread(os.path.join(fn_root, img_fn))
- rows = image_raw.shape[0]
- cols = image_raw.shape[1]
- depth = image_raw.shape[2]
- image_raw = image_raw.tostring()
- example = tf.train.Example(
- features=tf.train.Features(
- feature={
- "height": _int64_feature(rows),
- "width": _int64_feature(cols),
- "depth": _int64_feature(depth),
- "image_raw": _bytes_feature(image_raw)
- }
- )
- )
- writer.write(example.SerializeToString())
- writer.close()
-
-
-if __name__ == "__main__":
- main()
diff --git a/research/real_nvp/imnet_formatting.py b/research/real_nvp/imnet_formatting.py
deleted file mode 100644
index 1775dd54d368b62d047d1428d4bcf79ad4a68ae0..0000000000000000000000000000000000000000
--- a/research/real_nvp/imnet_formatting.py
+++ /dev/null
@@ -1,105 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-r"""LSUN dataset formatting.
-
-Download and format the Imagenet dataset as follow:
-mkdir [IMAGENET_PATH]
-cd [IMAGENET_PATH]
-for FILENAME in train_32x32.tar valid_32x32.tar train_64x64.tar valid_64x64.tar
-do
- curl -O http://image-net.org/small/$FILENAME
- tar -xvf $FILENAME
-done
-
-Then use the script as follow:
-for DIRNAME in train_32x32 valid_32x32 train_64x64 valid_64x64
-do
- python imnet_formatting.py \
- --file_out $DIRNAME \
- --fn_root $DIRNAME
-done
-
-"""
-
-from __future__ import print_function
-
-import os
-import os.path
-
-import scipy.io
-import scipy.io.wavfile
-import scipy.ndimage
-import tensorflow as tf
-
-
-tf.flags.DEFINE_string("file_out", "",
- "Filename of the output .tfrecords file.")
-tf.flags.DEFINE_string("fn_root", "", "Name of root file path.")
-
-FLAGS = tf.flags.FLAGS
-
-
-def _int64_feature(value):
- return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
-
-
-def _bytes_feature(value):
- return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
-
-
-def main():
- """Main converter function."""
- # LSUN
- fn_root = FLAGS.fn_root
- img_fn_list = os.listdir(fn_root)
- img_fn_list = [img_fn for img_fn in img_fn_list
- if img_fn.endswith('.png')]
- num_examples = len(img_fn_list)
-
- n_examples_per_file = 10000
- for example_idx, img_fn in enumerate(img_fn_list):
- if example_idx % n_examples_per_file == 0:
- file_out = "%s_%05d.tfrecords"
- file_out = file_out % (FLAGS.file_out,
- example_idx // n_examples_per_file)
- print("Writing on:", file_out)
- writer = tf.python_io.TFRecordWriter(file_out)
- if example_idx % 1000 == 0:
- print(example_idx, "/", num_examples)
- image_raw = scipy.ndimage.imread(os.path.join(fn_root, img_fn))
- rows = image_raw.shape[0]
- cols = image_raw.shape[1]
- depth = image_raw.shape[2]
- image_raw = image_raw.astype("uint8")
- image_raw = image_raw.tostring()
- example = tf.train.Example(
- features=tf.train.Features(
- feature={
- "height": _int64_feature(rows),
- "width": _int64_feature(cols),
- "depth": _int64_feature(depth),
- "image_raw": _bytes_feature(image_raw)
- }
- )
- )
- writer.write(example.SerializeToString())
- if example_idx % n_examples_per_file == (n_examples_per_file - 1):
- writer.close()
- writer.close()
-
-
-if __name__ == "__main__":
- main()
diff --git a/research/real_nvp/lsun_formatting.py b/research/real_nvp/lsun_formatting.py
deleted file mode 100644
index 13a21c5e90f86dcdea777419d1df848fcea03d45..0000000000000000000000000000000000000000
--- a/research/real_nvp/lsun_formatting.py
+++ /dev/null
@@ -1,105 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-r"""LSUN dataset formatting.
-
-Download and format the LSUN dataset as follow:
-git clone https://github.com/fyu/lsun.git
-cd lsun
-python2.7 download.py -c [CATEGORY]
-
-Then unzip the downloaded .zip files before executing:
-python2.7 data.py export [IMAGE_DB_PATH] --out_dir [LSUN_FOLDER] --flat
-
-Then use the script as follow:
-python lsun_formatting.py \
- --file_out [OUTPUT_FILE_PATH_PREFIX] \
- --fn_root [LSUN_FOLDER]
-
-"""
-from __future__ import print_function
-
-import os
-import os.path
-
-import numpy
-import skimage.transform
-from PIL import Image
-import tensorflow as tf
-
-
-tf.flags.DEFINE_string("file_out", "",
- "Filename of the output .tfrecords file.")
-tf.flags.DEFINE_string("fn_root", "", "Name of root file path.")
-
-FLAGS = tf.flags.FLAGS
-
-
-def _int64_feature(value):
- return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
-
-
-def _bytes_feature(value):
- return tf.train.Feature(bytes_list=tf.train.BytesList(value=[value]))
-
-
-def main():
- """Main converter function."""
- fn_root = FLAGS.fn_root
- img_fn_list = os.listdir(fn_root)
- img_fn_list = [img_fn for img_fn in img_fn_list
- if img_fn.endswith('.webp')]
- num_examples = len(img_fn_list)
-
- n_examples_per_file = 10000
- for example_idx, img_fn in enumerate(img_fn_list):
- if example_idx % n_examples_per_file == 0:
- file_out = "%s_%05d.tfrecords"
- file_out = file_out % (FLAGS.file_out,
- example_idx // n_examples_per_file)
- print("Writing on:", file_out)
- writer = tf.python_io.TFRecordWriter(file_out)
- if example_idx % 1000 == 0:
- print(example_idx, "/", num_examples)
- image_raw = numpy.array(Image.open(os.path.join(fn_root, img_fn)))
- rows = image_raw.shape[0]
- cols = image_raw.shape[1]
- depth = image_raw.shape[2]
- downscale = min(rows / 96., cols / 96.)
- image_raw = skimage.transform.pyramid_reduce(image_raw, downscale)
- image_raw *= 255.
- image_raw = image_raw.astype("uint8")
- rows = image_raw.shape[0]
- cols = image_raw.shape[1]
- depth = image_raw.shape[2]
- image_raw = image_raw.tostring()
- example = tf.train.Example(
- features=tf.train.Features(
- feature={
- "height": _int64_feature(rows),
- "width": _int64_feature(cols),
- "depth": _int64_feature(depth),
- "image_raw": _bytes_feature(image_raw)
- }
- )
- )
- writer.write(example.SerializeToString())
- if example_idx % n_examples_per_file == (n_examples_per_file - 1):
- writer.close()
- writer.close()
-
-
-if __name__ == "__main__":
- main()
diff --git a/research/real_nvp/real_nvp_multiscale_dataset.py b/research/real_nvp/real_nvp_multiscale_dataset.py
deleted file mode 100644
index c0e1864f1988cd983cdba14ced2462dae1b67e29..0000000000000000000000000000000000000000
--- a/research/real_nvp/real_nvp_multiscale_dataset.py
+++ /dev/null
@@ -1,1639 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-r"""Script for training, evaluation and sampling for Real NVP.
-
-$ python real_nvp_multiscale_dataset.py \
---alsologtostderr \
---image_size 64 \
---hpconfig=n_scale=5,base_dim=8 \
---dataset imnet \
---data_path [DATA_PATH]
-"""
-
-from __future__ import print_function
-
-import time
-from datetime import datetime
-import os
-
-import numpy
-from six.moves import xrange
-import tensorflow as tf
-
-from tensorflow import gfile
-
-from real_nvp_utils import (
- batch_norm, batch_norm_log_diff, conv_layer,
- squeeze_2x2, squeeze_2x2_ordered, standard_normal_ll,
- standard_normal_sample, unsqueeze_2x2, variable_on_cpu)
-
-
-tf.flags.DEFINE_string("master", "local",
- "BNS name of the TensorFlow master, or local.")
-
-tf.flags.DEFINE_string("logdir", "/tmp/real_nvp_multiscale",
- "Directory to which writes logs.")
-
-tf.flags.DEFINE_string("traindir", "/tmp/real_nvp_multiscale",
- "Directory to which writes logs.")
-
-tf.flags.DEFINE_integer("train_steps", 1000000000000000000,
- "Number of steps to train for.")
-
-tf.flags.DEFINE_string("data_path", "", "Path to the data.")
-
-tf.flags.DEFINE_string("mode", "train",
- "Mode of execution. Must be 'train', "
- "'sample' or 'eval'.")
-
-tf.flags.DEFINE_string("dataset", "imnet",
- "Dataset used. Must be 'imnet', "
- "'celeba' or 'lsun'.")
-
-tf.flags.DEFINE_integer("recursion_type", 2,
- "Type of the recursion.")
-
-tf.flags.DEFINE_integer("image_size", 64,
- "Size of the input image.")
-
-tf.flags.DEFINE_integer("eval_set_size", 0,
- "Size of evaluation dataset.")
-
-tf.flags.DEFINE_string(
- "hpconfig", "",
- "A comma separated list of hyperparameters for the model. Format is "
- "hp1=value1,hp2=value2,etc. If this FLAG is set, the model will be trained "
- "with the specified hyperparameters, filling in missing hyperparameters "
- "from the default_values in |hyper_params|.")
-
-FLAGS = tf.flags.FLAGS
-
-class HParams(object):
- """Dictionary of hyperparameters."""
- def __init__(self, **kwargs):
- self.dict_ = kwargs
- self.__dict__.update(self.dict_)
-
- def update_config(self, in_string):
- """Update the dictionary with a comma separated list."""
- pairs = in_string.split(",")
- pairs = [pair.split("=") for pair in pairs]
- for key, val in pairs:
- self.dict_[key] = type(self.dict_[key])(val)
- self.__dict__.update(self.dict_)
- return self
-
- def __getitem__(self, key):
- return self.dict_[key]
-
- def __setitem__(self, key, val):
- self.dict_[key] = val
- self.__dict__.update(self.dict_)
-
-
-def get_default_hparams():
- """Get the default hyperparameters."""
- return HParams(
- batch_size=64,
- residual_blocks=2,
- n_couplings=2,
- n_scale=4,
- learning_rate=0.001,
- momentum=1e-1,
- decay=1e-3,
- l2_coeff=0.00005,
- clip_gradient=100.,
- optimizer="adam",
- dropout_mask=0,
- base_dim=32,
- bottleneck=0,
- use_batch_norm=1,
- alternate=1,
- use_aff=1,
- skip=1,
- data_constraint=.9,
- n_opt=0)
-
-
-# RESNET UTILS
-def residual_block(input_, dim, name, use_batch_norm=True,
- train=True, weight_norm=True, bottleneck=False):
- """Residual convolutional block."""
- with tf.variable_scope(name):
- res = input_
- if use_batch_norm:
- res = batch_norm(
- input_=res, dim=dim, name="bn_in", scale=False,
- train=train, epsilon=1e-4, axes=[0, 1, 2])
- res = tf.nn.relu(res)
- if bottleneck:
- res = conv_layer(
- input_=res, filter_size=[1, 1], dim_in=dim, dim_out=dim,
- name="h_0", stddev=numpy.sqrt(2. / (dim)),
- strides=[1, 1, 1, 1], padding="SAME",
- nonlinearity=None, bias=(not use_batch_norm),
- weight_norm=weight_norm, scale=False)
- if use_batch_norm:
- res = batch_norm(
- input_=res, dim=dim,
- name="bn_0", scale=False, train=train,
- epsilon=1e-4, axes=[0, 1, 2])
- res = tf.nn.relu(res)
- res = conv_layer(
- input_=res, filter_size=[3, 3], dim_in=dim,
- dim_out=dim, name="h_1", stddev=numpy.sqrt(2. / (1. * dim)),
- strides=[1, 1, 1, 1], padding="SAME", nonlinearity=None,
- bias=(not use_batch_norm),
- weight_norm=weight_norm, scale=False)
- if use_batch_norm:
- res = batch_norm(
- input_=res, dim=dim, name="bn_1", scale=False,
- train=train, epsilon=1e-4, axes=[0, 1, 2])
- res = tf.nn.relu(res)
- res = conv_layer(
- input_=res, filter_size=[1, 1], dim_in=dim, dim_out=dim,
- name="out", stddev=numpy.sqrt(2. / (1. * dim)),
- strides=[1, 1, 1, 1], padding="SAME", nonlinearity=None,
- bias=True, weight_norm=weight_norm, scale=True)
- else:
- res = conv_layer(
- input_=res, filter_size=[3, 3], dim_in=dim, dim_out=dim,
- name="h_0", stddev=numpy.sqrt(2. / (dim)),
- strides=[1, 1, 1, 1], padding="SAME",
- nonlinearity=None, bias=(not use_batch_norm),
- weight_norm=weight_norm, scale=False)
- if use_batch_norm:
- res = batch_norm(
- input_=res, dim=dim, name="bn_0", scale=False,
- train=train, epsilon=1e-4, axes=[0, 1, 2])
- res = tf.nn.relu(res)
- res = conv_layer(
- input_=res, filter_size=[3, 3], dim_in=dim, dim_out=dim,
- name="out", stddev=numpy.sqrt(2. / (1. * dim)),
- strides=[1, 1, 1, 1], padding="SAME", nonlinearity=None,
- bias=True, weight_norm=weight_norm, scale=True)
- res += input_
-
- return res
-
-
-def resnet(input_, dim_in, dim, dim_out, name, use_batch_norm=True,
- train=True, weight_norm=True, residual_blocks=5,
- bottleneck=False, skip=True):
- """Residual convolutional network."""
- with tf.variable_scope(name):
- res = input_
- if residual_blocks != 0:
- res = conv_layer(
- input_=res, filter_size=[3, 3], dim_in=dim_in, dim_out=dim,
- name="h_in", stddev=numpy.sqrt(2. / (dim_in)),
- strides=[1, 1, 1, 1], padding="SAME",
- nonlinearity=None, bias=True,
- weight_norm=weight_norm, scale=False)
- if skip:
- out = conv_layer(
- input_=res, filter_size=[1, 1], dim_in=dim, dim_out=dim,
- name="skip_in", stddev=numpy.sqrt(2. / (dim)),
- strides=[1, 1, 1, 1], padding="SAME",
- nonlinearity=None, bias=True,
- weight_norm=weight_norm, scale=True)
-
- # residual blocks
- for idx_block in xrange(residual_blocks):
- res = residual_block(res, dim, "block_%d" % idx_block,
- use_batch_norm=use_batch_norm, train=train,
- weight_norm=weight_norm,
- bottleneck=bottleneck)
- if skip:
- out += conv_layer(
- input_=res, filter_size=[1, 1], dim_in=dim, dim_out=dim,
- name="skip_%d" % idx_block, stddev=numpy.sqrt(2. / (dim)),
- strides=[1, 1, 1, 1], padding="SAME",
- nonlinearity=None, bias=True,
- weight_norm=weight_norm, scale=True)
- # outputs
- if skip:
- res = out
- if use_batch_norm:
- res = batch_norm(
- input_=res, dim=dim, name="bn_pre_out", scale=False,
- train=train, epsilon=1e-4, axes=[0, 1, 2])
- res = tf.nn.relu(res)
- res = conv_layer(
- input_=res, filter_size=[1, 1], dim_in=dim,
- dim_out=dim_out,
- name="out", stddev=numpy.sqrt(2. / (1. * dim)),
- strides=[1, 1, 1, 1], padding="SAME",
- nonlinearity=None, bias=True,
- weight_norm=weight_norm, scale=True)
- else:
- if bottleneck:
- res = conv_layer(
- input_=res, filter_size=[1, 1], dim_in=dim_in, dim_out=dim,
- name="h_0", stddev=numpy.sqrt(2. / (dim_in)),
- strides=[1, 1, 1, 1], padding="SAME",
- nonlinearity=None, bias=(not use_batch_norm),
- weight_norm=weight_norm, scale=False)
- if use_batch_norm:
- res = batch_norm(
- input_=res, dim=dim, name="bn_0", scale=False,
- train=train, epsilon=1e-4, axes=[0, 1, 2])
- res = tf.nn.relu(res)
- res = conv_layer(
- input_=res, filter_size=[3, 3], dim_in=dim,
- dim_out=dim, name="h_1", stddev=numpy.sqrt(2. / (1. * dim)),
- strides=[1, 1, 1, 1], padding="SAME",
- nonlinearity=None,
- bias=(not use_batch_norm),
- weight_norm=weight_norm, scale=False)
- if use_batch_norm:
- res = batch_norm(
- input_=res, dim=dim, name="bn_1", scale=False,
- train=train, epsilon=1e-4, axes=[0, 1, 2])
- res = tf.nn.relu(res)
- res = conv_layer(
- input_=res, filter_size=[1, 1], dim_in=dim, dim_out=dim_out,
- name="out", stddev=numpy.sqrt(2. / (1. * dim)),
- strides=[1, 1, 1, 1], padding="SAME",
- nonlinearity=None, bias=True,
- weight_norm=weight_norm, scale=True)
- else:
- res = conv_layer(
- input_=res, filter_size=[3, 3], dim_in=dim_in, dim_out=dim,
- name="h_0", stddev=numpy.sqrt(2. / (dim_in)),
- strides=[1, 1, 1, 1], padding="SAME",
- nonlinearity=None, bias=(not use_batch_norm),
- weight_norm=weight_norm, scale=False)
- if use_batch_norm:
- res = batch_norm(
- input_=res, dim=dim, name="bn_0", scale=False,
- train=train, epsilon=1e-4, axes=[0, 1, 2])
- res = tf.nn.relu(res)
- res = conv_layer(
- input_=res, filter_size=[3, 3], dim_in=dim, dim_out=dim_out,
- name="out", stddev=numpy.sqrt(2. / (1. * dim)),
- strides=[1, 1, 1, 1], padding="SAME",
- nonlinearity=None, bias=True,
- weight_norm=weight_norm, scale=True)
- return res
-
-
-# COUPLING LAYERS
-# masked convolution implementations
-def masked_conv_aff_coupling(input_, mask_in, dim, name,
- use_batch_norm=True, train=True, weight_norm=True,
- reverse=False, residual_blocks=5,
- bottleneck=False, use_width=1., use_height=1.,
- mask_channel=0., skip=True):
- """Affine coupling with masked convolution."""
- with tf.variable_scope(name) as scope:
- if reverse or (not train):
- scope.reuse_variables()
- shape = input_.get_shape().as_list()
- batch_size = shape[0]
- height = shape[1]
- width = shape[2]
- channels = shape[3]
-
- # build mask
- mask = use_width * numpy.arange(width)
- mask = use_height * numpy.arange(height).reshape((-1, 1)) + mask
- mask = mask.astype("float32")
- mask = tf.mod(mask_in + mask, 2)
- mask = tf.reshape(mask, [-1, height, width, 1])
- if mask.get_shape().as_list()[0] == 1:
- mask = tf.tile(mask, [batch_size, 1, 1, 1])
- res = input_ * tf.mod(mask_channel + mask, 2)
-
- # initial input
- if use_batch_norm:
- res = batch_norm(
- input_=res, dim=channels, name="bn_in", scale=False,
- train=train, epsilon=1e-4, axes=[0, 1, 2])
- res *= 2.
- res = tf.concat([res, -res], 3)
- res = tf.concat([res, mask], 3)
- dim_in = 2. * channels + 1
- res = tf.nn.relu(res)
- res = resnet(input_=res, dim_in=dim_in, dim=dim,
- dim_out=2 * channels,
- name="resnet", use_batch_norm=use_batch_norm,
- train=train, weight_norm=weight_norm,
- residual_blocks=residual_blocks,
- bottleneck=bottleneck, skip=skip)
- mask = tf.mod(mask_channel + mask, 2)
- res = tf.split(axis=3, num_or_size_splits=2, value=res)
- shift, log_rescaling = res[-2], res[-1]
- scale = variable_on_cpu(
- "rescaling_scale", [],
- tf.constant_initializer(0.))
- shift = tf.reshape(
- shift, [batch_size, height, width, channels])
- log_rescaling = tf.reshape(
- log_rescaling, [batch_size, height, width, channels])
- log_rescaling = scale * tf.tanh(log_rescaling)
- if not use_batch_norm:
- scale_shift = variable_on_cpu(
- "scale_shift", [],
- tf.constant_initializer(0.))
- log_rescaling += scale_shift
- shift *= (1. - mask)
- log_rescaling *= (1. - mask)
- if reverse:
- res = input_
- if use_batch_norm:
- mean, var = batch_norm_log_diff(
- input_=res * (1. - mask), dim=channels, name="bn_out",
- train=False, epsilon=1e-4, axes=[0, 1, 2])
- log_var = tf.log(var)
- res *= tf.exp(.5 * log_var * (1. - mask))
- res += mean * (1. - mask)
- res *= tf.exp(-log_rescaling)
- res -= shift
- log_diff = -log_rescaling
- if use_batch_norm:
- log_diff += .5 * log_var * (1. - mask)
- else:
- res = input_
- res += shift
- res *= tf.exp(log_rescaling)
- log_diff = log_rescaling
- if use_batch_norm:
- mean, var = batch_norm_log_diff(
- input_=res * (1. - mask), dim=channels, name="bn_out",
- train=train, epsilon=1e-4, axes=[0, 1, 2])
- log_var = tf.log(var)
- res -= mean * (1. - mask)
- res *= tf.exp(-.5 * log_var * (1. - mask))
- log_diff -= .5 * log_var * (1. - mask)
-
- return res, log_diff
-
-
-def masked_conv_add_coupling(input_, mask_in, dim, name,
- use_batch_norm=True, train=True, weight_norm=True,
- reverse=False, residual_blocks=5,
- bottleneck=False, use_width=1., use_height=1.,
- mask_channel=0., skip=True):
- """Additive coupling with masked convolution."""
- with tf.variable_scope(name) as scope:
- if reverse or (not train):
- scope.reuse_variables()
- shape = input_.get_shape().as_list()
- batch_size = shape[0]
- height = shape[1]
- width = shape[2]
- channels = shape[3]
-
- # build mask
- mask = use_width * numpy.arange(width)
- mask = use_height * numpy.arange(height).reshape((-1, 1)) + mask
- mask = mask.astype("float32")
- mask = tf.mod(mask_in + mask, 2)
- mask = tf.reshape(mask, [-1, height, width, 1])
- if mask.get_shape().as_list()[0] == 1:
- mask = tf.tile(mask, [batch_size, 1, 1, 1])
- res = input_ * tf.mod(mask_channel + mask, 2)
-
- # initial input
- if use_batch_norm:
- res = batch_norm(
- input_=res, dim=channels, name="bn_in", scale=False,
- train=train, epsilon=1e-4, axes=[0, 1, 2])
- res *= 2.
- res = tf.concat([res, -res], 3)
- res = tf.concat([res, mask], 3)
- dim_in = 2. * channels + 1
- res = tf.nn.relu(res)
- shift = resnet(input_=res, dim_in=dim_in, dim=dim, dim_out=channels,
- name="resnet", use_batch_norm=use_batch_norm,
- train=train, weight_norm=weight_norm,
- residual_blocks=residual_blocks,
- bottleneck=bottleneck, skip=skip)
- mask = tf.mod(mask_channel + mask, 2)
- shift *= (1. - mask)
- # use_batch_norm = False
- if reverse:
- res = input_
- if use_batch_norm:
- mean, var = batch_norm_log_diff(
- input_=res * (1. - mask),
- dim=channels, name="bn_out", train=False, epsilon=1e-4)
- log_var = tf.log(var)
- res *= tf.exp(.5 * log_var * (1. - mask))
- res += mean * (1. - mask)
- res -= shift
- log_diff = tf.zeros_like(res)
- if use_batch_norm:
- log_diff += .5 * log_var * (1. - mask)
- else:
- res = input_
- res += shift
- log_diff = tf.zeros_like(res)
- if use_batch_norm:
- mean, var = batch_norm_log_diff(
- input_=res * (1. - mask), dim=channels,
- name="bn_out", train=train, epsilon=1e-4, axes=[0, 1, 2])
- log_var = tf.log(var)
- res -= mean * (1. - mask)
- res *= tf.exp(-.5 * log_var * (1. - mask))
- log_diff -= .5 * log_var * (1. - mask)
-
- return res, log_diff
-
-
-def masked_conv_coupling(input_, mask_in, dim, name,
- use_batch_norm=True, train=True, weight_norm=True,
- reverse=False, residual_blocks=5,
- bottleneck=False, use_aff=True,
- use_width=1., use_height=1.,
- mask_channel=0., skip=True):
- """Coupling with masked convolution."""
- if use_aff:
- return masked_conv_aff_coupling(
- input_=input_, mask_in=mask_in, dim=dim, name=name,
- use_batch_norm=use_batch_norm, train=train, weight_norm=weight_norm,
- reverse=reverse, residual_blocks=residual_blocks,
- bottleneck=bottleneck, use_width=use_width, use_height=use_height,
- mask_channel=mask_channel, skip=skip)
- else:
- return masked_conv_add_coupling(
- input_=input_, mask_in=mask_in, dim=dim, name=name,
- use_batch_norm=use_batch_norm, train=train, weight_norm=weight_norm,
- reverse=reverse, residual_blocks=residual_blocks,
- bottleneck=bottleneck, use_width=use_width, use_height=use_height,
- mask_channel=mask_channel, skip=skip)
-
-
-# channel-axis splitting implementations
-def conv_ch_aff_coupling(input_, dim, name,
- use_batch_norm=True, train=True, weight_norm=True,
- reverse=False, residual_blocks=5,
- bottleneck=False, change_bottom=True, skip=True):
- """Affine coupling with channel-wise splitting."""
- with tf.variable_scope(name) as scope:
- if reverse or (not train):
- scope.reuse_variables()
-
- if change_bottom:
- input_, canvas = tf.split(axis=3, num_or_size_splits=2, value=input_)
- else:
- canvas, input_ = tf.split(axis=3, num_or_size_splits=2, value=input_)
- shape = input_.get_shape().as_list()
- batch_size = shape[0]
- height = shape[1]
- width = shape[2]
- channels = shape[3]
- res = input_
-
- # initial input
- if use_batch_norm:
- res = batch_norm(
- input_=res, dim=channels, name="bn_in", scale=False,
- train=train, epsilon=1e-4, axes=[0, 1, 2])
- res = tf.concat([res, -res], 3)
- dim_in = 2. * channels
- res = tf.nn.relu(res)
- res = resnet(input_=res, dim_in=dim_in, dim=dim, dim_out=2 * channels,
- name="resnet", use_batch_norm=use_batch_norm,
- train=train, weight_norm=weight_norm,
- residual_blocks=residual_blocks,
- bottleneck=bottleneck, skip=skip)
- shift, log_rescaling = tf.split(axis=3, num_or_size_splits=2, value=res)
- scale = variable_on_cpu(
- "scale", [],
- tf.constant_initializer(1.))
- shift = tf.reshape(
- shift, [batch_size, height, width, channels])
- log_rescaling = tf.reshape(
- log_rescaling, [batch_size, height, width, channels])
- log_rescaling = scale * tf.tanh(log_rescaling)
- if not use_batch_norm:
- scale_shift = variable_on_cpu(
- "scale_shift", [],
- tf.constant_initializer(0.))
- log_rescaling += scale_shift
- if reverse:
- res = canvas
- if use_batch_norm:
- mean, var = batch_norm_log_diff(
- input_=res, dim=channels, name="bn_out", train=False,
- epsilon=1e-4, axes=[0, 1, 2])
- log_var = tf.log(var)
- res *= tf.exp(.5 * log_var)
- res += mean
- res *= tf.exp(-log_rescaling)
- res -= shift
- log_diff = -log_rescaling
- if use_batch_norm:
- log_diff += .5 * log_var
- else:
- res = canvas
- res += shift
- res *= tf.exp(log_rescaling)
- log_diff = log_rescaling
- if use_batch_norm:
- mean, var = batch_norm_log_diff(
- input_=res, dim=channels, name="bn_out", train=train,
- epsilon=1e-4, axes=[0, 1, 2])
- log_var = tf.log(var)
- res -= mean
- res *= tf.exp(-.5 * log_var)
- log_diff -= .5 * log_var
- if change_bottom:
- res = tf.concat([input_, res], 3)
- log_diff = tf.concat([tf.zeros_like(log_diff), log_diff], 3)
- else:
- res = tf.concat([res, input_], 3)
- log_diff = tf.concat([log_diff, tf.zeros_like(log_diff)], 3)
-
- return res, log_diff
-
-
-def conv_ch_add_coupling(input_, dim, name,
- use_batch_norm=True, train=True, weight_norm=True,
- reverse=False, residual_blocks=5,
- bottleneck=False, change_bottom=True, skip=True):
- """Additive coupling with channel-wise splitting."""
- with tf.variable_scope(name) as scope:
- if reverse or (not train):
- scope.reuse_variables()
-
- if change_bottom:
- input_, canvas = tf.split(axis=3, num_or_size_splits=2, value=input_)
- else:
- canvas, input_ = tf.split(axis=3, num_or_size_splits=2, value=input_)
- shape = input_.get_shape().as_list()
- channels = shape[3]
- res = input_
-
- # initial input
- if use_batch_norm:
- res = batch_norm(
- input_=res, dim=channels, name="bn_in", scale=False,
- train=train, epsilon=1e-4, axes=[0, 1, 2])
- res = tf.concat([res, -res], 3)
- dim_in = 2. * channels
- res = tf.nn.relu(res)
- shift = resnet(input_=res, dim_in=dim_in, dim=dim, dim_out=channels,
- name="resnet", use_batch_norm=use_batch_norm,
- train=train, weight_norm=weight_norm,
- residual_blocks=residual_blocks,
- bottleneck=bottleneck, skip=skip)
- if reverse:
- res = canvas
- if use_batch_norm:
- mean, var = batch_norm_log_diff(
- input_=res, dim=channels, name="bn_out", train=False,
- epsilon=1e-4, axes=[0, 1, 2])
- log_var = tf.log(var)
- res *= tf.exp(.5 * log_var)
- res += mean
- res -= shift
- log_diff = tf.zeros_like(res)
- if use_batch_norm:
- log_diff += .5 * log_var
- else:
- res = canvas
- res += shift
- log_diff = tf.zeros_like(res)
- if use_batch_norm:
- mean, var = batch_norm_log_diff(
- input_=res, dim=channels, name="bn_out", train=train,
- epsilon=1e-4, axes=[0, 1, 2])
- log_var = tf.log(var)
- res -= mean
- res *= tf.exp(-.5 * log_var)
- log_diff -= .5 * log_var
- if change_bottom:
- res = tf.concat([input_, res], 3)
- log_diff = tf.concat([tf.zeros_like(log_diff), log_diff], 3)
- else:
- res = tf.concat([res, input_], 3)
- log_diff = tf.concat([log_diff, tf.zeros_like(log_diff)], 3)
-
- return res, log_diff
-
-
-def conv_ch_coupling(input_, dim, name,
- use_batch_norm=True, train=True, weight_norm=True,
- reverse=False, residual_blocks=5,
- bottleneck=False, use_aff=True, change_bottom=True,
- skip=True):
- """Coupling with channel-wise splitting."""
- if use_aff:
- return conv_ch_aff_coupling(
- input_=input_, dim=dim, name=name,
- use_batch_norm=use_batch_norm, train=train, weight_norm=weight_norm,
- reverse=reverse, residual_blocks=residual_blocks,
- bottleneck=bottleneck, change_bottom=change_bottom, skip=skip)
- else:
- return conv_ch_add_coupling(
- input_=input_, dim=dim, name=name,
- use_batch_norm=use_batch_norm, train=train, weight_norm=weight_norm,
- reverse=reverse, residual_blocks=residual_blocks,
- bottleneck=bottleneck, change_bottom=change_bottom, skip=skip)
-
-
-# RECURSIVE USE OF COUPLING LAYERS
-def rec_masked_conv_coupling(input_, hps, scale_idx, n_scale,
- use_batch_norm=True, weight_norm=True,
- train=True):
- """Recursion on coupling layers."""
- shape = input_.get_shape().as_list()
- channels = shape[3]
- residual_blocks = hps.residual_blocks
- base_dim = hps.base_dim
- mask = 1.
- use_aff = hps.use_aff
- res = input_
- skip = hps.skip
- log_diff = tf.zeros_like(input_)
- dim = base_dim
- if FLAGS.recursion_type < 4:
- dim *= 2 ** scale_idx
- with tf.variable_scope("scale_%d" % scale_idx):
- # initial coupling layers
- res, inc_log_diff = masked_conv_coupling(
- input_=res,
- mask_in=mask, dim=dim,
- name="coupling_0",
- use_batch_norm=use_batch_norm, train=train,
- weight_norm=weight_norm,
- reverse=False, residual_blocks=residual_blocks,
- bottleneck=hps.bottleneck, use_aff=use_aff,
- use_width=1., use_height=1., skip=skip)
- log_diff += inc_log_diff
- res, inc_log_diff = masked_conv_coupling(
- input_=res,
- mask_in=1. - mask, dim=dim,
- name="coupling_1",
- use_batch_norm=use_batch_norm, train=train,
- weight_norm=weight_norm,
- reverse=False, residual_blocks=residual_blocks,
- bottleneck=hps.bottleneck, use_aff=use_aff,
- use_width=1., use_height=1., skip=skip)
- log_diff += inc_log_diff
- res, inc_log_diff = masked_conv_coupling(
- input_=res,
- mask_in=mask, dim=dim,
- name="coupling_2",
- use_batch_norm=use_batch_norm, train=train,
- weight_norm=weight_norm,
- reverse=False, residual_blocks=residual_blocks,
- bottleneck=hps.bottleneck, use_aff=True,
- use_width=1., use_height=1., skip=skip)
- log_diff += inc_log_diff
- if scale_idx < (n_scale - 1):
- with tf.variable_scope("scale_%d" % scale_idx):
- res = squeeze_2x2(res)
- log_diff = squeeze_2x2(log_diff)
- res, inc_log_diff = conv_ch_coupling(
- input_=res,
- change_bottom=True, dim=2 * dim,
- name="coupling_4",
- use_batch_norm=use_batch_norm, train=train,
- weight_norm=weight_norm,
- reverse=False, residual_blocks=residual_blocks,
- bottleneck=hps.bottleneck, use_aff=use_aff, skip=skip)
- log_diff += inc_log_diff
- res, inc_log_diff = conv_ch_coupling(
- input_=res,
- change_bottom=False, dim=2 * dim,
- name="coupling_5",
- use_batch_norm=use_batch_norm, train=train,
- weight_norm=weight_norm,
- reverse=False, residual_blocks=residual_blocks,
- bottleneck=hps.bottleneck, use_aff=use_aff, skip=skip)
- log_diff += inc_log_diff
- res, inc_log_diff = conv_ch_coupling(
- input_=res,
- change_bottom=True, dim=2 * dim,
- name="coupling_6",
- use_batch_norm=use_batch_norm, train=train,
- weight_norm=weight_norm,
- reverse=False, residual_blocks=residual_blocks,
- bottleneck=hps.bottleneck, use_aff=True, skip=skip)
- log_diff += inc_log_diff
- res = unsqueeze_2x2(res)
- log_diff = unsqueeze_2x2(log_diff)
- if FLAGS.recursion_type > 1:
- res = squeeze_2x2_ordered(res)
- log_diff = squeeze_2x2_ordered(log_diff)
- if FLAGS.recursion_type > 2:
- res_1 = res[:, :, :, :channels]
- res_2 = res[:, :, :, channels:]
- log_diff_1 = log_diff[:, :, :, :channels]
- log_diff_2 = log_diff[:, :, :, channels:]
- else:
- res_1, res_2 = tf.split(axis=3, num_or_size_splits=2, value=res)
- log_diff_1, log_diff_2 = tf.split(axis=3, num_or_size_splits=2, value=log_diff)
- res_1, inc_log_diff = rec_masked_conv_coupling(
- input_=res_1, hps=hps, scale_idx=scale_idx + 1, n_scale=n_scale,
- use_batch_norm=use_batch_norm, weight_norm=weight_norm,
- train=train)
- res = tf.concat([res_1, res_2], 3)
- log_diff_1 += inc_log_diff
- log_diff = tf.concat([log_diff_1, log_diff_2], 3)
- res = squeeze_2x2_ordered(res, reverse=True)
- log_diff = squeeze_2x2_ordered(log_diff, reverse=True)
- else:
- res = squeeze_2x2_ordered(res)
- log_diff = squeeze_2x2_ordered(log_diff)
- res, inc_log_diff = rec_masked_conv_coupling(
- input_=res, hps=hps, scale_idx=scale_idx + 1, n_scale=n_scale,
- use_batch_norm=use_batch_norm, weight_norm=weight_norm,
- train=train)
- log_diff += inc_log_diff
- res = squeeze_2x2_ordered(res, reverse=True)
- log_diff = squeeze_2x2_ordered(log_diff, reverse=True)
- else:
- with tf.variable_scope("scale_%d" % scale_idx):
- res, inc_log_diff = masked_conv_coupling(
- input_=res,
- mask_in=1. - mask, dim=dim,
- name="coupling_3",
- use_batch_norm=use_batch_norm, train=train,
- weight_norm=weight_norm,
- reverse=False, residual_blocks=residual_blocks,
- bottleneck=hps.bottleneck, use_aff=True,
- use_width=1., use_height=1., skip=skip)
- log_diff += inc_log_diff
- return res, log_diff
-
-
-def rec_masked_deconv_coupling(input_, hps, scale_idx, n_scale,
- use_batch_norm=True, weight_norm=True,
- train=True):
- """Recursion on inverting coupling layers."""
- shape = input_.get_shape().as_list()
- channels = shape[3]
- residual_blocks = hps.residual_blocks
- base_dim = hps.base_dim
- mask = 1.
- use_aff = hps.use_aff
- res = input_
- log_diff = tf.zeros_like(input_)
- skip = hps.skip
- dim = base_dim
- if FLAGS.recursion_type < 4:
- dim *= 2 ** scale_idx
- if scale_idx < (n_scale - 1):
- if FLAGS.recursion_type > 1:
- res = squeeze_2x2_ordered(res)
- log_diff = squeeze_2x2_ordered(log_diff)
- if FLAGS.recursion_type > 2:
- res_1 = res[:, :, :, :channels]
- res_2 = res[:, :, :, channels:]
- log_diff_1 = log_diff[:, :, :, :channels]
- log_diff_2 = log_diff[:, :, :, channels:]
- else:
- res_1, res_2 = tf.split(axis=3, num_or_size_splits=2, value=res)
- log_diff_1, log_diff_2 = tf.split(axis=3, num_or_size_splits=2, value=log_diff)
- res_1, log_diff_1 = rec_masked_deconv_coupling(
- input_=res_1, hps=hps,
- scale_idx=scale_idx + 1, n_scale=n_scale,
- use_batch_norm=use_batch_norm, weight_norm=weight_norm,
- train=train)
- res = tf.concat([res_1, res_2], 3)
- log_diff = tf.concat([log_diff_1, log_diff_2], 3)
- res = squeeze_2x2_ordered(res, reverse=True)
- log_diff = squeeze_2x2_ordered(log_diff, reverse=True)
- else:
- res = squeeze_2x2_ordered(res)
- log_diff = squeeze_2x2_ordered(log_diff)
- res, log_diff = rec_masked_deconv_coupling(
- input_=res, hps=hps,
- scale_idx=scale_idx + 1, n_scale=n_scale,
- use_batch_norm=use_batch_norm, weight_norm=weight_norm,
- train=train)
- res = squeeze_2x2_ordered(res, reverse=True)
- log_diff = squeeze_2x2_ordered(log_diff, reverse=True)
- with tf.variable_scope("scale_%d" % scale_idx):
- res = squeeze_2x2(res)
- log_diff = squeeze_2x2(log_diff)
- res, inc_log_diff = conv_ch_coupling(
- input_=res,
- change_bottom=True, dim=2 * dim,
- name="coupling_6",
- use_batch_norm=use_batch_norm, train=train,
- weight_norm=weight_norm,
- reverse=True, residual_blocks=residual_blocks,
- bottleneck=hps.bottleneck, use_aff=True, skip=skip)
- log_diff += inc_log_diff
- res, inc_log_diff = conv_ch_coupling(
- input_=res,
- change_bottom=False, dim=2 * dim,
- name="coupling_5",
- use_batch_norm=use_batch_norm, train=train,
- weight_norm=weight_norm,
- reverse=True, residual_blocks=residual_blocks,
- bottleneck=hps.bottleneck, use_aff=use_aff, skip=skip)
- log_diff += inc_log_diff
- res, inc_log_diff = conv_ch_coupling(
- input_=res,
- change_bottom=True, dim=2 * dim,
- name="coupling_4",
- use_batch_norm=use_batch_norm, train=train,
- weight_norm=weight_norm,
- reverse=True, residual_blocks=residual_blocks,
- bottleneck=hps.bottleneck, use_aff=use_aff, skip=skip)
- log_diff += inc_log_diff
- res = unsqueeze_2x2(res)
- log_diff = unsqueeze_2x2(log_diff)
- else:
- with tf.variable_scope("scale_%d" % scale_idx):
- res, inc_log_diff = masked_conv_coupling(
- input_=res,
- mask_in=1. - mask, dim=dim,
- name="coupling_3",
- use_batch_norm=use_batch_norm, train=train,
- weight_norm=weight_norm,
- reverse=True, residual_blocks=residual_blocks,
- bottleneck=hps.bottleneck, use_aff=True,
- use_width=1., use_height=1., skip=skip)
- log_diff += inc_log_diff
-
- with tf.variable_scope("scale_%d" % scale_idx):
- res, inc_log_diff = masked_conv_coupling(
- input_=res,
- mask_in=mask, dim=dim,
- name="coupling_2",
- use_batch_norm=use_batch_norm, train=train, weight_norm=weight_norm,
- reverse=True, residual_blocks=residual_blocks,
- bottleneck=hps.bottleneck, use_aff=True,
- use_width=1., use_height=1., skip=skip)
- log_diff += inc_log_diff
- res, inc_log_diff = masked_conv_coupling(
- input_=res,
- mask_in=1. - mask, dim=dim,
- name="coupling_1",
- use_batch_norm=use_batch_norm, train=train, weight_norm=weight_norm,
- reverse=True, residual_blocks=residual_blocks,
- bottleneck=hps.bottleneck, use_aff=use_aff,
- use_width=1., use_height=1., skip=skip)
- log_diff += inc_log_diff
- res, inc_log_diff = masked_conv_coupling(
- input_=res,
- mask_in=mask, dim=dim,
- name="coupling_0",
- use_batch_norm=use_batch_norm, train=train, weight_norm=weight_norm,
- reverse=True, residual_blocks=residual_blocks,
- bottleneck=hps.bottleneck, use_aff=use_aff,
- use_width=1., use_height=1., skip=skip)
- log_diff += inc_log_diff
-
- return res, log_diff
-
-
-# ENCODER AND DECODER IMPLEMENTATIONS
-# start the recursions
-def encoder(input_, hps, n_scale, use_batch_norm=True,
- weight_norm=True, train=True):
- """Encoding/gaussianization function."""
- res = input_
- log_diff = tf.zeros_like(input_)
- res, inc_log_diff = rec_masked_conv_coupling(
- input_=res, hps=hps, scale_idx=0, n_scale=n_scale,
- use_batch_norm=use_batch_norm, weight_norm=weight_norm,
- train=train)
- log_diff += inc_log_diff
-
- return res, log_diff
-
-
-def decoder(input_, hps, n_scale, use_batch_norm=True,
- weight_norm=True, train=True):
- """Decoding/generator function."""
- res, log_diff = rec_masked_deconv_coupling(
- input_=input_, hps=hps, scale_idx=0, n_scale=n_scale,
- use_batch_norm=use_batch_norm, weight_norm=weight_norm,
- train=train)
-
- return res, log_diff
-
-
-class RealNVP(object):
- """Real NVP model."""
-
- def __init__(self, hps, sampling=False):
- # DATA TENSOR INSTANTIATION
- device = "/cpu:0"
- if FLAGS.dataset == "imnet":
- with tf.device(
- tf.train.replica_device_setter(0, worker_device=device)):
- filename_queue = tf.train.string_input_producer(
- gfile.Glob(FLAGS.data_path), num_epochs=None)
- reader = tf.TFRecordReader()
- _, serialized_example = reader.read(filename_queue)
- features = tf.parse_single_example(
- serialized_example,
- features={
- "image_raw": tf.FixedLenFeature([], tf.string),
- })
- image = tf.decode_raw(features["image_raw"], tf.uint8)
- image.set_shape([FLAGS.image_size * FLAGS.image_size * 3])
- image = tf.cast(image, tf.float32)
- if FLAGS.mode == "train":
- images = tf.train.shuffle_batch(
- [image], batch_size=hps.batch_size, num_threads=1,
- capacity=1000 + 3 * hps.batch_size,
- # Ensures a minimum amount of shuffling of examples.
- min_after_dequeue=1000)
- else:
- images = tf.train.batch(
- [image], batch_size=hps.batch_size, num_threads=1,
- capacity=1000 + 3 * hps.batch_size)
- self.x_orig = x_orig = images
- image_size = FLAGS.image_size
- x_in = tf.reshape(
- x_orig,
- [hps.batch_size, FLAGS.image_size, FLAGS.image_size, 3])
- x_in = tf.clip_by_value(x_in, 0, 255)
- x_in = (tf.cast(x_in, tf.float32)
- + tf.random_uniform(tf.shape(x_in))) / 256.
- elif FLAGS.dataset == "celeba":
- with tf.device(
- tf.train.replica_device_setter(0, worker_device=device)):
- filename_queue = tf.train.string_input_producer(
- gfile.Glob(FLAGS.data_path), num_epochs=None)
- reader = tf.TFRecordReader()
- _, serialized_example = reader.read(filename_queue)
- features = tf.parse_single_example(
- serialized_example,
- features={
- "image_raw": tf.FixedLenFeature([], tf.string),
- })
- image = tf.decode_raw(features["image_raw"], tf.uint8)
- image.set_shape([218 * 178 * 3]) # 218, 178
- image = tf.cast(image, tf.float32)
- image = tf.reshape(image, [218, 178, 3])
- image = image[40:188, 15:163, :]
- if FLAGS.mode == "train":
- image = tf.image.random_flip_left_right(image)
- images = tf.train.shuffle_batch(
- [image], batch_size=hps.batch_size, num_threads=1,
- capacity=1000 + 3 * hps.batch_size,
- min_after_dequeue=1000)
- else:
- images = tf.train.batch(
- [image], batch_size=hps.batch_size, num_threads=1,
- capacity=1000 + 3 * hps.batch_size)
- self.x_orig = x_orig = images
- image_size = 64
- x_in = tf.reshape(x_orig, [hps.batch_size, 148, 148, 3])
- x_in = tf.image.resize_images(
- x_in, [64, 64], method=0, align_corners=False)
- x_in = (tf.cast(x_in, tf.float32)
- + tf.random_uniform(tf.shape(x_in))) / 256.
- elif FLAGS.dataset == "lsun":
- with tf.device(
- tf.train.replica_device_setter(0, worker_device=device)):
- filename_queue = tf.train.string_input_producer(
- gfile.Glob(FLAGS.data_path), num_epochs=None)
- reader = tf.TFRecordReader()
- _, serialized_example = reader.read(filename_queue)
- features = tf.parse_single_example(
- serialized_example,
- features={
- "image_raw": tf.FixedLenFeature([], tf.string),
- "height": tf.FixedLenFeature([], tf.int64),
- "width": tf.FixedLenFeature([], tf.int64),
- "depth": tf.FixedLenFeature([], tf.int64)
- })
- image = tf.decode_raw(features["image_raw"], tf.uint8)
- height = tf.reshape((features["height"], tf.int64)[0], [1])
- height = tf.cast(height, tf.int32)
- width = tf.reshape((features["width"], tf.int64)[0], [1])
- width = tf.cast(width, tf.int32)
- depth = tf.reshape((features["depth"], tf.int64)[0], [1])
- depth = tf.cast(depth, tf.int32)
- image = tf.reshape(image, tf.concat([height, width, depth], 0))
- image = tf.random_crop(image, [64, 64, 3])
- if FLAGS.mode == "train":
- image = tf.image.random_flip_left_right(image)
- images = tf.train.shuffle_batch(
- [image], batch_size=hps.batch_size, num_threads=1,
- capacity=1000 + 3 * hps.batch_size,
- # Ensures a minimum amount of shuffling of examples.
- min_after_dequeue=1000)
- else:
- images = tf.train.batch(
- [image], batch_size=hps.batch_size, num_threads=1,
- capacity=1000 + 3 * hps.batch_size)
- self.x_orig = x_orig = images
- image_size = 64
- x_in = tf.reshape(x_orig, [hps.batch_size, 64, 64, 3])
- x_in = (tf.cast(x_in, tf.float32)
- + tf.random_uniform(tf.shape(x_in))) / 256.
- else:
- raise ValueError("Unknown dataset.")
- x_in = tf.reshape(x_in, [hps.batch_size, image_size, image_size, 3])
- side_shown = int(numpy.sqrt(hps.batch_size))
- shown_x = tf.transpose(
- tf.reshape(
- x_in[:(side_shown * side_shown), :, :, :],
- [side_shown, image_size * side_shown, image_size, 3]),
- [0, 2, 1, 3])
- shown_x = tf.transpose(
- tf.reshape(
- shown_x,
- [1, image_size * side_shown, image_size * side_shown, 3]),
- [0, 2, 1, 3]) * 255.
- tf.summary.image(
- "inputs",
- tf.cast(shown_x, tf.uint8),
- max_outputs=1)
-
- # restrict the data
- FLAGS.image_size = image_size
- data_constraint = hps.data_constraint
- pre_logit_scale = numpy.log(data_constraint)
- pre_logit_scale -= numpy.log(1. - data_constraint)
- pre_logit_scale = tf.cast(pre_logit_scale, tf.float32)
- logit_x_in = 2. * x_in # [0, 2]
- logit_x_in -= 1. # [-1, 1]
- logit_x_in *= data_constraint # [-.9, .9]
- logit_x_in += 1. # [.1, 1.9]
- logit_x_in /= 2. # [.05, .95]
- # logit the data
- logit_x_in = tf.log(logit_x_in) - tf.log(1. - logit_x_in)
- transform_cost = tf.reduce_sum(
- tf.nn.softplus(logit_x_in) + tf.nn.softplus(-logit_x_in)
- - tf.nn.softplus(-pre_logit_scale),
- [1, 2, 3])
-
- # INFERENCE AND COSTS
- z_out, log_diff = encoder(
- input_=logit_x_in, hps=hps, n_scale=hps.n_scale,
- use_batch_norm=hps.use_batch_norm, weight_norm=True,
- train=True)
- if FLAGS.mode != "train":
- z_out, log_diff = encoder(
- input_=logit_x_in, hps=hps, n_scale=hps.n_scale,
- use_batch_norm=hps.use_batch_norm, weight_norm=True,
- train=False)
- final_shape = [image_size, image_size, 3]
- prior_ll = standard_normal_ll(z_out)
- prior_ll = tf.reduce_sum(prior_ll, [1, 2, 3])
- log_diff = tf.reduce_sum(log_diff, [1, 2, 3])
- log_diff += transform_cost
- cost = -(prior_ll + log_diff)
-
- self.x_in = x_in
- self.z_out = z_out
- self.cost = cost = tf.reduce_mean(cost)
-
- l2_reg = sum(
- [tf.reduce_sum(tf.square(v)) for v in tf.trainable_variables()
- if ("magnitude" in v.name) or ("rescaling_scale" in v.name)])
-
- bit_per_dim = ((cost + numpy.log(256.) * image_size * image_size * 3.)
- / (image_size * image_size * 3. * numpy.log(2.)))
- self.bit_per_dim = bit_per_dim
-
- # OPTIMIZATION
- momentum = 1. - hps.momentum
- decay = 1. - hps.decay
- if hps.optimizer == "adam":
- optimizer = tf.train.AdamOptimizer(
- learning_rate=hps.learning_rate,
- beta1=momentum, beta2=decay, epsilon=1e-08,
- use_locking=False, name="Adam")
- elif hps.optimizer == "rmsprop":
- optimizer = tf.train.RMSPropOptimizer(
- learning_rate=hps.learning_rate, decay=decay,
- momentum=momentum, epsilon=1e-04,
- use_locking=False, name="RMSProp")
- else:
- optimizer = tf.train.MomentumOptimizer(hps.learning_rate,
- momentum=momentum)
-
- step = tf.get_variable(
- "global_step", [], tf.int64,
- tf.zeros_initializer(),
- trainable=False)
- self.step = step
- grads_and_vars = optimizer.compute_gradients(
- cost + hps.l2_coeff * l2_reg,
- tf.trainable_variables())
- grads, vars_ = zip(*grads_and_vars)
- capped_grads, gradient_norm = tf.clip_by_global_norm(
- grads, clip_norm=hps.clip_gradient)
- gradient_norm = tf.check_numerics(gradient_norm,
- "Gradient norm is NaN or Inf.")
-
- l2_z = tf.reduce_sum(tf.square(z_out), [1, 2, 3])
- if not sampling:
- tf.summary.scalar("negative_log_likelihood", tf.reshape(cost, []))
- tf.summary.scalar("gradient_norm", tf.reshape(gradient_norm, []))
- tf.summary.scalar("bit_per_dim", tf.reshape(bit_per_dim, []))
- tf.summary.scalar("log_diff", tf.reshape(tf.reduce_mean(log_diff), []))
- tf.summary.scalar("prior_ll", tf.reshape(tf.reduce_mean(prior_ll), []))
- tf.summary.scalar(
- "log_diff_var",
- tf.reshape(tf.reduce_mean(tf.square(log_diff))
- - tf.square(tf.reduce_mean(log_diff)), []))
- tf.summary.scalar(
- "prior_ll_var",
- tf.reshape(tf.reduce_mean(tf.square(prior_ll))
- - tf.square(tf.reduce_mean(prior_ll)), []))
- tf.summary.scalar("l2_z_mean", tf.reshape(tf.reduce_mean(l2_z), []))
- tf.summary.scalar(
- "l2_z_var",
- tf.reshape(tf.reduce_mean(tf.square(l2_z))
- - tf.square(tf.reduce_mean(l2_z)), []))
-
-
- capped_grads_and_vars = zip(capped_grads, vars_)
- self.train_step = optimizer.apply_gradients(
- capped_grads_and_vars, global_step=step)
-
- # SAMPLING AND VISUALIZATION
- if sampling:
- # SAMPLES
- sample = standard_normal_sample([100] + final_shape)
- sample, _ = decoder(
- input_=sample, hps=hps, n_scale=hps.n_scale,
- use_batch_norm=hps.use_batch_norm, weight_norm=True,
- train=True)
- sample = tf.nn.sigmoid(sample)
-
- sample = tf.clip_by_value(sample, 0, 1) * 255.
- sample = tf.reshape(sample, [100, image_size, image_size, 3])
- sample = tf.transpose(
- tf.reshape(sample, [10, image_size * 10, image_size, 3]),
- [0, 2, 1, 3])
- sample = tf.transpose(
- tf.reshape(sample, [1, image_size * 10, image_size * 10, 3]),
- [0, 2, 1, 3])
- tf.summary.image(
- "samples",
- tf.cast(sample, tf.uint8),
- max_outputs=1)
-
- # CONCATENATION
- concatenation, _ = encoder(
- input_=logit_x_in, hps=hps,
- n_scale=hps.n_scale,
- use_batch_norm=hps.use_batch_norm, weight_norm=True,
- train=False)
- concatenation = tf.reshape(
- concatenation,
- [(side_shown * side_shown), image_size, image_size, 3])
- concatenation = tf.transpose(
- tf.reshape(
- concatenation,
- [side_shown, image_size * side_shown, image_size, 3]),
- [0, 2, 1, 3])
- concatenation = tf.transpose(
- tf.reshape(
- concatenation,
- [1, image_size * side_shown, image_size * side_shown, 3]),
- [0, 2, 1, 3])
- concatenation, _ = decoder(
- input_=concatenation, hps=hps, n_scale=hps.n_scale,
- use_batch_norm=hps.use_batch_norm, weight_norm=True,
- train=False)
- concatenation = tf.nn.sigmoid(concatenation) * 255.
- tf.summary.image(
- "concatenation",
- tf.cast(concatenation, tf.uint8),
- max_outputs=1)
-
- # MANIFOLD
-
- # Data basis
- z_u, _ = encoder(
- input_=logit_x_in[:8, :, :, :], hps=hps,
- n_scale=hps.n_scale,
- use_batch_norm=hps.use_batch_norm, weight_norm=True,
- train=False)
- u_1 = tf.reshape(z_u[0, :, :, :], [-1])
- u_2 = tf.reshape(z_u[1, :, :, :], [-1])
- u_3 = tf.reshape(z_u[2, :, :, :], [-1])
- u_4 = tf.reshape(z_u[3, :, :, :], [-1])
- u_5 = tf.reshape(z_u[4, :, :, :], [-1])
- u_6 = tf.reshape(z_u[5, :, :, :], [-1])
- u_7 = tf.reshape(z_u[6, :, :, :], [-1])
- u_8 = tf.reshape(z_u[7, :, :, :], [-1])
-
- # 3D dome
- manifold_side = 8
- angle_1 = numpy.arange(manifold_side) * 1. / manifold_side
- angle_2 = numpy.arange(manifold_side) * 1. / manifold_side
- angle_1 *= 2. * numpy.pi
- angle_2 *= 2. * numpy.pi
- angle_1 = angle_1.astype("float32")
- angle_2 = angle_2.astype("float32")
- angle_1 = tf.reshape(angle_1, [1, -1, 1])
- angle_1 += tf.zeros([manifold_side, manifold_side, 1])
- angle_2 = tf.reshape(angle_2, [-1, 1, 1])
- angle_2 += tf.zeros([manifold_side, manifold_side, 1])
- n_angle_3 = 40
- angle_3 = numpy.arange(n_angle_3) * 1. / n_angle_3
- angle_3 *= 2 * numpy.pi
- angle_3 = angle_3.astype("float32")
- angle_3 = tf.reshape(angle_3, [-1, 1, 1, 1])
- angle_3 += tf.zeros([n_angle_3, manifold_side, manifold_side, 1])
- manifold = tf.cos(angle_1) * (
- tf.cos(angle_2) * (
- tf.cos(angle_3) * u_1 + tf.sin(angle_3) * u_2)
- + tf.sin(angle_2) * (
- tf.cos(angle_3) * u_3 + tf.sin(angle_3) * u_4))
- manifold += tf.sin(angle_1) * (
- tf.cos(angle_2) * (
- tf.cos(angle_3) * u_5 + tf.sin(angle_3) * u_6)
- + tf.sin(angle_2) * (
- tf.cos(angle_3) * u_7 + tf.sin(angle_3) * u_8))
- manifold = tf.reshape(
- manifold,
- [n_angle_3 * manifold_side * manifold_side] + final_shape)
- manifold, _ = decoder(
- input_=manifold, hps=hps, n_scale=hps.n_scale,
- use_batch_norm=hps.use_batch_norm, weight_norm=True,
- train=False)
- manifold = tf.nn.sigmoid(manifold)
-
- manifold = tf.clip_by_value(manifold, 0, 1) * 255.
- manifold = tf.reshape(
- manifold,
- [n_angle_3,
- manifold_side * manifold_side,
- image_size,
- image_size,
- 3])
- manifold = tf.transpose(
- tf.reshape(
- manifold,
- [n_angle_3, manifold_side,
- image_size * manifold_side, image_size, 3]), [0, 1, 3, 2, 4])
- manifold = tf.transpose(
- tf.reshape(
- manifold,
- [n_angle_3, image_size * manifold_side,
- image_size * manifold_side, 3]),
- [0, 2, 1, 3])
- manifold = tf.transpose(manifold, [1, 2, 0, 3])
- manifold = tf.reshape(
- manifold,
- [1, image_size * manifold_side,
- image_size * manifold_side, 3 * n_angle_3])
- tf.summary.image(
- "manifold",
- tf.cast(manifold[:, :, :, :3], tf.uint8),
- max_outputs=1)
-
- # COMPRESSION
- z_complete, _ = encoder(
- input_=logit_x_in[:hps.n_scale, :, :, :], hps=hps,
- n_scale=hps.n_scale,
- use_batch_norm=hps.use_batch_norm, weight_norm=True,
- train=False)
- z_compressed_list = [z_complete]
- z_noisy_list = [z_complete]
- z_lost = z_complete
- for scale_idx in xrange(hps.n_scale - 1):
- z_lost = squeeze_2x2_ordered(z_lost)
- z_lost, _ = tf.split(axis=3, num_or_size_splits=2, value=z_lost)
- z_compressed = z_lost
- z_noisy = z_lost
- for _ in xrange(scale_idx + 1):
- z_compressed = tf.concat(
- [z_compressed, tf.zeros_like(z_compressed)], 3)
- z_compressed = squeeze_2x2_ordered(
- z_compressed, reverse=True)
- z_noisy = tf.concat(
- [z_noisy, tf.random_normal(
- z_noisy.get_shape().as_list())], 3)
- z_noisy = squeeze_2x2_ordered(z_noisy, reverse=True)
- z_compressed_list.append(z_compressed)
- z_noisy_list.append(z_noisy)
- self.z_reduced = z_lost
- z_compressed = tf.concat(z_compressed_list, 0)
- z_noisy = tf.concat(z_noisy_list, 0)
- noisy_images, _ = decoder(
- input_=z_noisy, hps=hps, n_scale=hps.n_scale,
- use_batch_norm=hps.use_batch_norm, weight_norm=True,
- train=False)
- compressed_images, _ = decoder(
- input_=z_compressed, hps=hps, n_scale=hps.n_scale,
- use_batch_norm=hps.use_batch_norm, weight_norm=True,
- train=False)
- noisy_images = tf.nn.sigmoid(noisy_images)
- compressed_images = tf.nn.sigmoid(compressed_images)
-
- noisy_images = tf.clip_by_value(noisy_images, 0, 1) * 255.
- noisy_images = tf.reshape(
- noisy_images,
- [(hps.n_scale * hps.n_scale), image_size, image_size, 3])
- noisy_images = tf.transpose(
- tf.reshape(
- noisy_images,
- [hps.n_scale, image_size * hps.n_scale, image_size, 3]),
- [0, 2, 1, 3])
- noisy_images = tf.transpose(
- tf.reshape(
- noisy_images,
- [1, image_size * hps.n_scale, image_size * hps.n_scale, 3]),
- [0, 2, 1, 3])
- tf.summary.image(
- "noise",
- tf.cast(noisy_images, tf.uint8),
- max_outputs=1)
- compressed_images = tf.clip_by_value(compressed_images, 0, 1) * 255.
- compressed_images = tf.reshape(
- compressed_images,
- [(hps.n_scale * hps.n_scale), image_size, image_size, 3])
- compressed_images = tf.transpose(
- tf.reshape(
- compressed_images,
- [hps.n_scale, image_size * hps.n_scale, image_size, 3]),
- [0, 2, 1, 3])
- compressed_images = tf.transpose(
- tf.reshape(
- compressed_images,
- [1, image_size * hps.n_scale, image_size * hps.n_scale, 3]),
- [0, 2, 1, 3])
- tf.summary.image(
- "compression",
- tf.cast(compressed_images, tf.uint8),
- max_outputs=1)
-
- # SAMPLES x2
- final_shape[0] *= 2
- final_shape[1] *= 2
- big_sample = standard_normal_sample([25] + final_shape)
- big_sample, _ = decoder(
- input_=big_sample, hps=hps, n_scale=hps.n_scale,
- use_batch_norm=hps.use_batch_norm, weight_norm=True,
- train=True)
- big_sample = tf.nn.sigmoid(big_sample)
-
- big_sample = tf.clip_by_value(big_sample, 0, 1) * 255.
- big_sample = tf.reshape(
- big_sample,
- [25, image_size * 2, image_size * 2, 3])
- big_sample = tf.transpose(
- tf.reshape(
- big_sample,
- [5, image_size * 10, image_size * 2, 3]), [0, 2, 1, 3])
- big_sample = tf.transpose(
- tf.reshape(
- big_sample,
- [1, image_size * 10, image_size * 10, 3]),
- [0, 2, 1, 3])
- tf.summary.image(
- "big_sample",
- tf.cast(big_sample, tf.uint8),
- max_outputs=1)
-
- # SAMPLES x10
- final_shape[0] *= 5
- final_shape[1] *= 5
- extra_large = standard_normal_sample([1] + final_shape)
- extra_large, _ = decoder(
- input_=extra_large, hps=hps, n_scale=hps.n_scale,
- use_batch_norm=hps.use_batch_norm, weight_norm=True,
- train=True)
- extra_large = tf.nn.sigmoid(extra_large)
-
- extra_large = tf.clip_by_value(extra_large, 0, 1) * 255.
- tf.summary.image(
- "extra_large",
- tf.cast(extra_large, tf.uint8),
- max_outputs=1)
-
- def eval_epoch(self, hps):
- """Evaluate bits/dim."""
- n_eval_dict = {
- "imnet": 50000,
- "lsun": 300,
- "celeba": 19962,
- "svhn": 26032,
- }
- if FLAGS.eval_set_size == 0:
- num_examples_eval = n_eval_dict[FLAGS.dataset]
- else:
- num_examples_eval = FLAGS.eval_set_size
- n_epoch = num_examples_eval / hps.batch_size
- eval_costs = []
- bar_len = 70
- for epoch_idx in xrange(n_epoch):
- n_equal = epoch_idx * bar_len * 1. / n_epoch
- n_equal = numpy.ceil(n_equal)
- n_equal = int(n_equal)
- n_dash = bar_len - n_equal
- progress_bar = "[" + "=" * n_equal + "-" * n_dash + "]\r"
- print(progress_bar, end=' ')
- cost = self.bit_per_dim.eval()
- eval_costs.append(cost)
- print("")
- return float(numpy.mean(eval_costs))
-
-
-def train_model(hps, logdir):
- """Training."""
- with tf.Graph().as_default():
- with tf.device(tf.train.replica_device_setter(0)):
- with tf.variable_scope("model"):
- model = RealNVP(hps)
-
- saver = tf.train.Saver(tf.global_variables())
-
- # Build the summary operation from the last tower summaries.
- summary_op = tf.summary.merge_all()
-
- # Build an initialization operation to run below.
- init = tf.global_variables_initializer()
-
- # Start running operations on the Graph. allow_soft_placement must be set to
- # True to build towers on GPU, as some of the ops do not have GPU
- # implementations.
- sess = tf.Session(config=tf.ConfigProto(
- allow_soft_placement=True,
- log_device_placement=True))
- sess.run(init)
-
- ckpt_state = tf.train.get_checkpoint_state(logdir)
- if ckpt_state and ckpt_state.model_checkpoint_path:
- print("Loading file %s" % ckpt_state.model_checkpoint_path)
- saver.restore(sess, ckpt_state.model_checkpoint_path)
-
- # Start the queue runners.
- tf.train.start_queue_runners(sess=sess)
-
- summary_writer = tf.summary.FileWriter(
- logdir,
- graph=sess.graph)
-
- local_step = 0
- while True:
- fetches = [model.step, model.bit_per_dim, model.train_step]
- # The chief worker evaluates the summaries every 10 steps.
- should_eval_summaries = local_step % 100 == 0
- if should_eval_summaries:
- fetches += [summary_op]
-
-
- start_time = time.time()
- outputs = sess.run(fetches)
- global_step_val = outputs[0]
- loss = outputs[1]
- duration = time.time() - start_time
- assert not numpy.isnan(
- loss), 'Model diverged with loss = NaN'
-
- if local_step % 10 == 0:
- examples_per_sec = hps.batch_size / float(duration)
- format_str = ('%s: step %d, loss = %.2f '
- '(%.1f examples/sec; %.3f '
- 'sec/batch)')
- print(format_str % (datetime.now(), global_step_val, loss,
- examples_per_sec, duration))
-
- if should_eval_summaries:
- summary_str = outputs[-1]
- summary_writer.add_summary(summary_str, global_step_val)
-
- # Save the model checkpoint periodically.
- if local_step % 1000 == 0 or (local_step + 1) == FLAGS.train_steps:
- checkpoint_path = os.path.join(logdir, 'model.ckpt')
- saver.save(
- sess,
- checkpoint_path,
- global_step=global_step_val)
-
- if outputs[0] >= FLAGS.train_steps:
- break
-
- local_step += 1
-
-
-def evaluate(hps, logdir, traindir, subset="valid", return_val=False):
- """Evaluation."""
- hps.batch_size = 100
- with tf.Graph().as_default():
- with tf.device("/cpu:0"):
- with tf.variable_scope("model") as var_scope:
- eval_model = RealNVP(hps)
- summary_writer = tf.summary.FileWriter(logdir)
- var_scope.reuse_variables()
-
- saver = tf.train.Saver()
- sess = tf.Session(config=tf.ConfigProto(
- allow_soft_placement=True,
- log_device_placement=True))
- tf.train.start_queue_runners(sess)
-
- previous_global_step = 0 # don"t run eval for step = 0
-
- with sess.as_default():
- while True:
- ckpt_state = tf.train.get_checkpoint_state(traindir)
- if not (ckpt_state and ckpt_state.model_checkpoint_path):
- print("No model to eval yet at %s" % traindir)
- time.sleep(30)
- continue
- print("Loading file %s" % ckpt_state.model_checkpoint_path)
- saver.restore(sess, ckpt_state.model_checkpoint_path)
-
- current_step = tf.train.global_step(sess, eval_model.step)
- if current_step == previous_global_step:
- print("Waiting for the checkpoint to be updated.")
- time.sleep(30)
- continue
- previous_global_step = current_step
-
- print("Evaluating...")
- bit_per_dim = eval_model.eval_epoch(hps)
- print("Epoch: %d, %s -> %.3f bits/dim"
- % (current_step, subset, bit_per_dim))
- print("Writing summary...")
- summary = tf.Summary()
- summary.value.extend(
- [tf.Summary.Value(
- tag="bit_per_dim",
- simple_value=bit_per_dim)])
- summary_writer.add_summary(summary, current_step)
-
- if return_val:
- return current_step, bit_per_dim
-
-
-def sample_from_model(hps, logdir, traindir):
- """Sampling."""
- hps.batch_size = 100
- with tf.Graph().as_default():
- with tf.device("/cpu:0"):
- with tf.variable_scope("model") as var_scope:
- eval_model = RealNVP(hps, sampling=True)
- summary_writer = tf.summary.FileWriter(logdir)
- var_scope.reuse_variables()
-
- summary_op = tf.summary.merge_all()
- saver = tf.train.Saver()
- sess = tf.Session(config=tf.ConfigProto(
- allow_soft_placement=True,
- log_device_placement=True))
- coord = tf.train.Coordinator()
- threads = tf.train.start_queue_runners(sess=sess, coord=coord)
-
- previous_global_step = 0 # don"t run eval for step = 0
-
- initialized = False
- with sess.as_default():
- while True:
- ckpt_state = tf.train.get_checkpoint_state(traindir)
- if not (ckpt_state and ckpt_state.model_checkpoint_path):
- if not initialized:
- print("No model to eval yet at %s" % traindir)
- time.sleep(30)
- continue
- else:
- print ("Loading file %s"
- % ckpt_state.model_checkpoint_path)
- saver.restore(sess, ckpt_state.model_checkpoint_path)
-
- current_step = tf.train.global_step(sess, eval_model.step)
- if current_step == previous_global_step:
- print("Waiting for the checkpoint to be updated.")
- time.sleep(30)
- continue
- previous_global_step = current_step
-
- fetches = [summary_op]
-
- outputs = sess.run(fetches)
- summary_writer.add_summary(outputs[0], current_step)
- coord.request_stop()
- coord.join(threads)
-
-
-def main(unused_argv):
- hps = get_default_hparams().update_config(FLAGS.hpconfig)
- if FLAGS.mode == "train":
- train_model(hps=hps, logdir=FLAGS.logdir)
- elif FLAGS.mode == "sample":
- sample_from_model(hps=hps, logdir=FLAGS.logdir,
- traindir=FLAGS.traindir)
- else:
- hps.batch_size = 100
- evaluate(hps=hps, logdir=FLAGS.logdir,
- traindir=FLAGS.traindir, subset=FLAGS.mode)
-
-if __name__ == "__main__":
- tf.app.run()
diff --git a/research/real_nvp/real_nvp_utils.py b/research/real_nvp/real_nvp_utils.py
deleted file mode 100644
index d8240f0e98d5b0d91bab8a9027ac737eb425a999..0000000000000000000000000000000000000000
--- a/research/real_nvp/real_nvp_utils.py
+++ /dev/null
@@ -1,475 +0,0 @@
-# Copyright 2016 Google Inc. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-r"""Utility functions for Real NVP.
-"""
-
-# pylint: disable=dangerous-default-value
-
-import numpy
-from six.moves import xrange
-import tensorflow as tf
-from tensorflow.python.framework import ops
-
-DEFAULT_BN_LAG = .0
-
-
-def stable_var(input_, mean=None, axes=[0]):
- """Numerically more stable variance computation."""
- if mean is None:
- mean = tf.reduce_mean(input_, axes)
- res = tf.square(input_ - mean)
- max_sqr = tf.reduce_max(res, axes)
- res /= max_sqr
- res = tf.reduce_mean(res, axes)
- res *= max_sqr
-
- return res
-
-
-def variable_on_cpu(name, shape, initializer, trainable=True):
- """Helper to create a Variable stored on CPU memory.
-
- Args:
- name: name of the variable
- shape: list of ints
- initializer: initializer for Variable
- trainable: boolean defining if the variable is for training
- Returns:
- Variable Tensor
- """
- var = tf.get_variable(
- name, shape, initializer=initializer, trainable=trainable)
- return var
-
-
-# layers
-def conv_layer(input_,
- filter_size,
- dim_in,
- dim_out,
- name,
- stddev=1e-2,
- strides=[1, 1, 1, 1],
- padding="SAME",
- nonlinearity=None,
- bias=False,
- weight_norm=False,
- scale=False):
- """Convolutional layer."""
- with tf.variable_scope(name) as scope:
- weights = variable_on_cpu(
- "weights",
- filter_size + [dim_in, dim_out],
- tf.random_uniform_initializer(
- minval=-stddev, maxval=stddev))
- # weight normalization
- if weight_norm:
- weights /= tf.sqrt(tf.reduce_sum(tf.square(weights), [0, 1, 2]))
- if scale:
- magnitude = variable_on_cpu(
- "magnitude", [dim_out],
- tf.constant_initializer(
- stddev * numpy.sqrt(dim_in * numpy.prod(filter_size) / 12.)))
- weights *= magnitude
- res = input_
- # handling filter size bigger than image size
- if hasattr(input_, "shape"):
- if input_.get_shape().as_list()[1] < filter_size[0]:
- pad_1 = tf.zeros([
- input_.get_shape().as_list()[0],
- filter_size[0] - input_.get_shape().as_list()[1],
- input_.get_shape().as_list()[2],
- input_.get_shape().as_list()[3]
- ])
- pad_2 = tf.zeros([
- input_.get_shape().as_list[0],
- filter_size[0],
- filter_size[1] - input_.get_shape().as_list()[2],
- input_.get_shape().as_list()[3]
- ])
- res = tf.concat(axis=1, values=[pad_1, res])
- res = tf.concat(axis=2, values=[pad_2, res])
- res = tf.nn.conv2d(
- input=res,
- filter=weights,
- strides=strides,
- padding=padding,
- name=scope.name)
-
- if hasattr(input_, "shape"):
- if input_.get_shape().as_list()[1] < filter_size[0]:
- res = tf.slice(res, [
- 0, filter_size[0] - input_.get_shape().as_list()[1],
- filter_size[1] - input_.get_shape().as_list()[2], 0
- ], [-1, -1, -1, -1])
-
- if bias:
- biases = variable_on_cpu("biases", [dim_out], tf.constant_initializer(0.))
- res = tf.nn.bias_add(res, biases)
- if nonlinearity is not None:
- res = nonlinearity(res)
-
- return res
-
-
-def max_pool_2x2(input_):
- """Max pooling."""
- return tf.nn.max_pool(
- input_, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
-
-
-def depool_2x2(input_, stride=2):
- """Depooling."""
- shape = input_.get_shape().as_list()
- batch_size = shape[0]
- height = shape[1]
- width = shape[2]
- channels = shape[3]
- res = tf.reshape(input_, [batch_size, height, 1, width, 1, channels])
- res = tf.concat(
- axis=2, values=[res, tf.zeros([batch_size, height, stride - 1, width, 1, channels])])
- res = tf.concat(axis=4, values=[
- res, tf.zeros([batch_size, height, stride, width, stride - 1, channels])
- ])
- res = tf.reshape(res, [batch_size, stride * height, stride * width, channels])
-
- return res
-
-
-# random flip on a batch of images
-def batch_random_flip(input_):
- """Simultaneous horizontal random flip."""
- if isinstance(input_, (float, int)):
- return input_
- shape = input_.get_shape().as_list()
- batch_size = shape[0]
- height = shape[1]
- width = shape[2]
- channels = shape[3]
- res = tf.split(axis=0, num_or_size_splits=batch_size, value=input_)
- res = [elem[0, :, :, :] for elem in res]
- res = [tf.image.random_flip_left_right(elem) for elem in res]
- res = [tf.reshape(elem, [1, height, width, channels]) for elem in res]
- res = tf.concat(axis=0, values=res)
-
- return res
-
-
-# build a one hot representation corresponding to the integer tensor
-# the one-hot dimension is appended to the integer tensor shape
-def as_one_hot(input_, n_indices):
- """Convert indices to one-hot."""
- shape = input_.get_shape().as_list()
- n_elem = numpy.prod(shape)
- indices = tf.range(n_elem)
- indices = tf.cast(indices, tf.int64)
- indices_input = tf.concat(axis=0, values=[indices, tf.reshape(input_, [-1])])
- indices_input = tf.reshape(indices_input, [2, -1])
- indices_input = tf.transpose(indices_input)
- res = tf.sparse_to_dense(
- indices_input, [n_elem, n_indices], 1., 0., name="flat_one_hot")
- res = tf.reshape(res, [elem for elem in shape] + [n_indices])
-
- return res
-
-
-def squeeze_2x2(input_):
- """Squeezing operation: reshape to convert space to channels."""
- return squeeze_nxn(input_, n_factor=2)
-
-
-def squeeze_nxn(input_, n_factor=2):
- """Squeezing operation: reshape to convert space to channels."""
- if isinstance(input_, (float, int)):
- return input_
- shape = input_.get_shape().as_list()
- batch_size = shape[0]
- height = shape[1]
- width = shape[2]
- channels = shape[3]
- if height % n_factor != 0:
- raise ValueError("Height not divisible by %d." % n_factor)
- if width % n_factor != 0:
- raise ValueError("Width not divisible by %d." % n_factor)
- res = tf.reshape(
- input_,
- [batch_size,
- height // n_factor,
- n_factor, width // n_factor,
- n_factor, channels])
- res = tf.transpose(res, [0, 1, 3, 5, 2, 4])
- res = tf.reshape(
- res,
- [batch_size,
- height // n_factor,
- width // n_factor,
- channels * n_factor * n_factor])
-
- return res
-
-
-def unsqueeze_2x2(input_):
- """Unsqueezing operation: reshape to convert channels into space."""
- if isinstance(input_, (float, int)):
- return input_
- shape = input_.get_shape().as_list()
- batch_size = shape[0]
- height = shape[1]
- width = shape[2]
- channels = shape[3]
- if channels % 4 != 0:
- raise ValueError("Number of channels not divisible by 4.")
- res = tf.reshape(input_, [batch_size, height, width, channels // 4, 2, 2])
- res = tf.transpose(res, [0, 1, 4, 2, 5, 3])
- res = tf.reshape(res, [batch_size, 2 * height, 2 * width, channels // 4])
-
- return res
-
-
-# batch norm
-def batch_norm(input_,
- dim,
- name,
- scale=True,
- train=True,
- epsilon=1e-8,
- decay=.1,
- axes=[0],
- bn_lag=DEFAULT_BN_LAG):
- """Batch normalization."""
- # create variables
- with tf.variable_scope(name):
- var = variable_on_cpu(
- "var", [dim], tf.constant_initializer(1.), trainable=False)
- mean = variable_on_cpu(
- "mean", [dim], tf.constant_initializer(0.), trainable=False)
- step = variable_on_cpu("step", [], tf.constant_initializer(0.), trainable=False)
- if scale:
- gamma = variable_on_cpu("gamma", [dim], tf.constant_initializer(1.))
- beta = variable_on_cpu("beta", [dim], tf.constant_initializer(0.))
- # choose the appropriate moments
- if train:
- used_mean, used_var = tf.nn.moments(input_, axes, name="batch_norm")
- cur_mean, cur_var = used_mean, used_var
- if bn_lag > 0.:
- used_mean -= (1. - bn_lag) * (used_mean - tf.stop_gradient(mean))
- used_var -= (1 - bn_lag) * (used_var - tf.stop_gradient(var))
- used_mean /= (1. - bn_lag**(step + 1))
- used_var /= (1. - bn_lag**(step + 1))
- else:
- used_mean, used_var = mean, var
- cur_mean, cur_var = used_mean, used_var
-
- # normalize
- res = (input_ - used_mean) / tf.sqrt(used_var + epsilon)
- # de-normalize
- if scale:
- res *= gamma
- res += beta
-
- # update variables
- if train:
- with tf.name_scope(name, "AssignMovingAvg", [mean, cur_mean, decay]):
- with ops.colocate_with(mean):
- new_mean = tf.assign_sub(
- mean,
- tf.check_numerics(decay * (mean - cur_mean), "NaN in moving mean."))
- with tf.name_scope(name, "AssignMovingAvg", [var, cur_var, decay]):
- with ops.colocate_with(var):
- new_var = tf.assign_sub(
- var,
- tf.check_numerics(decay * (var - cur_var),
- "NaN in moving variance."))
- with tf.name_scope(name, "IncrementTime", [step]):
- with ops.colocate_with(step):
- new_step = tf.assign_add(step, 1.)
- res += 0. * new_mean * new_var * new_step
-
- return res
-
-
-# batch normalization taking into account the volume transformation
-def batch_norm_log_diff(input_,
- dim,
- name,
- train=True,
- epsilon=1e-8,
- decay=.1,
- axes=[0],
- reuse=None,
- bn_lag=DEFAULT_BN_LAG):
- """Batch normalization with corresponding log determinant Jacobian."""
- if reuse is None:
- reuse = not train
- # create variables
- with tf.variable_scope(name) as scope:
- if reuse:
- scope.reuse_variables()
- var = variable_on_cpu(
- "var", [dim], tf.constant_initializer(1.), trainable=False)
- mean = variable_on_cpu(
- "mean", [dim], tf.constant_initializer(0.), trainable=False)
- step = variable_on_cpu("step", [], tf.constant_initializer(0.), trainable=False)
- # choose the appropriate moments
- if train:
- used_mean, used_var = tf.nn.moments(input_, axes, name="batch_norm")
- cur_mean, cur_var = used_mean, used_var
- if bn_lag > 0.:
- used_var = stable_var(input_=input_, mean=used_mean, axes=axes)
- cur_var = used_var
- used_mean -= (1 - bn_lag) * (used_mean - tf.stop_gradient(mean))
- used_mean /= (1. - bn_lag**(step + 1))
- used_var -= (1 - bn_lag) * (used_var - tf.stop_gradient(var))
- used_var /= (1. - bn_lag**(step + 1))
- else:
- used_mean, used_var = mean, var
- cur_mean, cur_var = used_mean, used_var
-
- # update variables
- if train:
- with tf.name_scope(name, "AssignMovingAvg", [mean, cur_mean, decay]):
- with ops.colocate_with(mean):
- new_mean = tf.assign_sub(
- mean,
- tf.check_numerics(
- decay * (mean - cur_mean), "NaN in moving mean."))
- with tf.name_scope(name, "AssignMovingAvg", [var, cur_var, decay]):
- with ops.colocate_with(var):
- new_var = tf.assign_sub(
- var,
- tf.check_numerics(decay * (var - cur_var),
- "NaN in moving variance."))
- with tf.name_scope(name, "IncrementTime", [step]):
- with ops.colocate_with(step):
- new_step = tf.assign_add(step, 1.)
- used_var += 0. * new_mean * new_var * new_step
- used_var += epsilon
-
- return used_mean, used_var
-
-
-def convnet(input_,
- dim_in,
- dim_hid,
- filter_sizes,
- dim_out,
- name,
- use_batch_norm=True,
- train=True,
- nonlinearity=tf.nn.relu):
- """Chaining of convolutional layers."""
- dims_in = [dim_in] + dim_hid[:-1]
- dims_out = dim_hid
- res = input_
-
- bias = (not use_batch_norm)
- with tf.variable_scope(name):
- for layer_idx in xrange(len(dim_hid)):
- res = conv_layer(
- input_=res,
- filter_size=filter_sizes[layer_idx],
- dim_in=dims_in[layer_idx],
- dim_out=dims_out[layer_idx],
- name="h_%d" % layer_idx,
- stddev=1e-2,
- nonlinearity=None,
- bias=bias)
- if use_batch_norm:
- res = batch_norm(
- input_=res,
- dim=dims_out[layer_idx],
- name="bn_%d" % layer_idx,
- scale=(nonlinearity == tf.nn.relu),
- train=train,
- epsilon=1e-8,
- axes=[0, 1, 2])
- if nonlinearity is not None:
- res = nonlinearity(res)
-
- res = conv_layer(
- input_=res,
- filter_size=filter_sizes[-1],
- dim_in=dims_out[-1],
- dim_out=dim_out,
- name="out",
- stddev=1e-2,
- nonlinearity=None)
-
- return res
-
-
-# distributions
-# log-likelihood estimation
-def standard_normal_ll(input_):
- """Log-likelihood of standard Gaussian distribution."""
- res = -.5 * (tf.square(input_) + numpy.log(2. * numpy.pi))
-
- return res
-
-
-def standard_normal_sample(shape):
- """Samples from standard Gaussian distribution."""
- return tf.random_normal(shape)
-
-
-SQUEEZE_MATRIX = numpy.array([[[[1., 0., 0., 0.]], [[0., 0., 1., 0.]]],
- [[[0., 0., 0., 1.]], [[0., 1., 0., 0.]]]])
-
-
-def squeeze_2x2_ordered(input_, reverse=False):
- """Squeezing operation with a controlled ordering."""
- shape = input_.get_shape().as_list()
- batch_size = shape[0]
- height = shape[1]
- width = shape[2]
- channels = shape[3]
- if reverse:
- if channels % 4 != 0:
- raise ValueError("Number of channels not divisible by 4.")
- channels /= 4
- else:
- if height % 2 != 0:
- raise ValueError("Height not divisible by 2.")
- if width % 2 != 0:
- raise ValueError("Width not divisible by 2.")
- weights = numpy.zeros((2, 2, channels, 4 * channels))
- for idx_ch in xrange(channels):
- slice_2 = slice(idx_ch, (idx_ch + 1))
- slice_3 = slice((idx_ch * 4), ((idx_ch + 1) * 4))
- weights[:, :, slice_2, slice_3] = SQUEEZE_MATRIX
- shuffle_channels = [idx_ch * 4 for idx_ch in xrange(channels)]
- shuffle_channels += [idx_ch * 4 + 1 for idx_ch in xrange(channels)]
- shuffle_channels += [idx_ch * 4 + 2 for idx_ch in xrange(channels)]
- shuffle_channels += [idx_ch * 4 + 3 for idx_ch in xrange(channels)]
- shuffle_channels = numpy.array(shuffle_channels)
- weights = weights[:, :, :, shuffle_channels].astype("float32")
- if reverse:
- res = tf.nn.conv2d_transpose(
- value=input_,
- filter=weights,
- output_shape=[batch_size, height * 2, width * 2, channels],
- strides=[1, 2, 2, 1],
- padding="SAME",
- name="unsqueeze_2x2")
- else:
- res = tf.nn.conv2d(
- input=input_,
- filter=weights,
- strides=[1, 2, 2, 1],
- padding="SAME",
- name="squeeze_2x2")
-
- return res
diff --git a/research/sentiment_analysis/README.md b/research/sentiment_analysis/README.md
deleted file mode 100644
index f98c42751df2475b4dbdc1db0cc303b42d2b7b4c..0000000000000000000000000000000000000000
--- a/research/sentiment_analysis/README.md
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-# Sentiment Analysis
-## Overview
-This is an implementation of the Sentiment Analysis model as described in the [this paper](https://arxiv.org/abs/1412.1058). The implementation is with the reference to [paddle version](https://github.com/mlperf/reference/tree/master/sentiment_analysis/paddle).
-
-The model makes use of concatenation of two CNN layers with different kernel sizes. Batch normalization and dropout layers are used to prevent over-fitting.
-
-## Dataset
-The [keras](https://keras.io)'s [IMDB Movie reviews sentiment classification](https://keras.io/datasets/#imdb-movie-reviews-sentiment-classification) dataset is used. The dataset file download is handled by keras module, and the downloaded files are stored at ``~/.keras/datasets` directory. The compressed file's filesize as of June 15 2018 is 17MB.
-
-## Running Code
-### Train and evaluate model
-To train and evaluate the model, issue the following command:
-```
-python sentiment_main.py
-```
-Arguments:
- * `--dataset`: The dataset name to be downloaded and preprocessed. By default, it is `imdb`.
-
-There are other arguments about models and training process. Use the `--help` or `-h` flag to get a full list of possible arguments with detailed descriptions.
-
-## Benchmarks
-The model was recorded to have the accuracy of 90.1% for the IMDB dataset.
diff --git a/research/sentiment_analysis/__init__.py b/research/sentiment_analysis/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/sentiment_analysis/data/__init__.py b/research/sentiment_analysis/data/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/sentiment_analysis/data/dataset.py b/research/sentiment_analysis/data/dataset.py
deleted file mode 100644
index 9ba4b9ac677296fbc7d1db549c5dd011117a16c4..0000000000000000000000000000000000000000
--- a/research/sentiment_analysis/data/dataset.py
+++ /dev/null
@@ -1,52 +0,0 @@
-"""Dataset module for sentiment analysis.
-
-Currently imdb dataset is available.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import data.imdb as imdb
-
-DATASET_IMDB = "imdb"
-
-
-def load(dataset, vocabulary_size, sentence_length):
- """Returns training and evaluation input.
-
- Args:
- dataset: Dataset to be trained and evaluated.
- Currently only imdb is supported.
- vocabulary_size: The number of the most frequent tokens
- to be used from the corpus.
- sentence_length: The number of words in each sentence.
- Longer sentences get cut, shorter ones padded.
- Raises:
- ValueError: if the dataset value is not valid.
- Returns:
- A tuple of length 4, for training sentences, labels,
- evaluation sentences, and evaluation labels,
- each being an numpy array.
- """
- if dataset == DATASET_IMDB:
- return imdb.load(vocabulary_size, sentence_length)
- else:
- raise ValueError("unsupported dataset: " + dataset)
-
-
-def get_num_class(dataset):
- """Returns an integer for the number of label classes.
-
- Args:
- dataset: Dataset to be trained and evaluated.
- Currently only imdb is supported.
- Raises:
- ValueError: if the dataset value is not valid.
- Returns:
- int: The number of label classes.
- """
- if dataset == DATASET_IMDB:
- return imdb.NUM_CLASS
- else:
- raise ValueError("unsupported dataset: " + dataset)
diff --git a/research/sentiment_analysis/data/imdb.py b/research/sentiment_analysis/data/imdb.py
deleted file mode 100644
index f8160ca2f71ac158a4ee42119a04e2dafec033ee..0000000000000000000000000000000000000000
--- a/research/sentiment_analysis/data/imdb.py
+++ /dev/null
@@ -1,54 +0,0 @@
-"""IMDB Dataset module for sentiment analysis."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import tensorflow as tf
-
-from data.util import OOV_CHAR
-from data.util import pad_sentence
-from data.util import START_CHAR
-
-NUM_CLASS = 2
-
-
-def load(vocabulary_size, sentence_length):
- """Returns training and evaluation input for imdb dataset.
-
- Args:
- vocabulary_size: The number of the most frequent tokens
- to be used from the corpus.
- sentence_length: The number of words in each sentence.
- Longer sentences get cut, shorter ones padded.
- Raises:
- ValueError: if the dataset value is not valid.
- Returns:
- A tuple of length 4, for training and evaluation data,
- each being an numpy array.
- """
- (x_train, y_train), (x_test, y_test) = tf.keras.datasets.imdb.load_data(
- path="imdb.npz",
- num_words=vocabulary_size,
- skip_top=0,
- maxlen=None,
- seed=113,
- start_char=START_CHAR,
- oov_char=OOV_CHAR,
- index_from=OOV_CHAR+1)
-
- x_train_processed = []
- for sen in x_train:
- sen = pad_sentence(sen, sentence_length)
- x_train_processed.append(np.array(sen))
- x_train_processed = np.array(x_train_processed)
-
- x_test_processed = []
- for sen in x_test:
- sen = pad_sentence(sen, sentence_length)
- x_test_processed.append(np.array(sen))
- x_test_processed = np.array(x_test_processed)
-
- return x_train_processed, np.eye(NUM_CLASS)[y_train], \
- x_test_processed, np.eye(NUM_CLASS)[y_test]
diff --git a/research/sentiment_analysis/data/util.py b/research/sentiment_analysis/data/util.py
deleted file mode 100644
index c8f8808f7e1d7f26876d052c108d1948cbd2fe9f..0000000000000000000000000000000000000000
--- a/research/sentiment_analysis/data/util.py
+++ /dev/null
@@ -1,32 +0,0 @@
-"""Utility module for sentiment analysis."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-
-START_CHAR = 1
-END_CHAR = 2
-OOV_CHAR = 3
-
-
-def pad_sentence(sentence, sentence_length):
- """Pad the given sentense at the end.
-
- If the input is longer than sentence_length,
- the remaining portion is dropped.
- END_CHAR is used for the padding.
-
- Args:
- sentence: A numpy array of integers.
- sentence_length: The length of the input after the padding.
- Returns:
- A numpy array of integers of the given length.
- """
- sentence = sentence[:sentence_length]
- if len(sentence) < sentence_length:
- sentence = np.pad(sentence, (0, sentence_length - len(sentence)),
- "constant", constant_values=(START_CHAR, END_CHAR))
-
- return sentence
diff --git a/research/sentiment_analysis/sentiment_main.py b/research/sentiment_analysis/sentiment_main.py
deleted file mode 100644
index 8b9ba5f921eef72377b480669bd81087fd1b160a..0000000000000000000000000000000000000000
--- a/research/sentiment_analysis/sentiment_main.py
+++ /dev/null
@@ -1,115 +0,0 @@
-"""Main function for the sentiment analysis model.
-
-The model makes use of concatenation of two CNN layers with
-different kernel sizes. See `sentiment_model.py`
-for more details about the models.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import argparse
-import os
-
-import tensorflow as tf
-
-from data import dataset
-import sentiment_model
-
-
-
-_DROPOUT_RATE = 0.95
-
-
-def run_model(dataset_name, emb_dim, voc_size, sen_len,
- hid_dim, batch_size, epochs, model_save_dir):
- """Run training loop and an evaluation at the end.
-
- Args:
- dataset_name: Dataset name to be trained and evaluated.
- emb_dim: The dimension of the Embedding layer.
- voc_size: The number of the most frequent tokens
- to be used from the corpus.
- sen_len: The number of words in each sentence.
- Longer sentences get cut, shorter ones padded.
- hid_dim: The dimension of the Embedding layer.
- batch_size: The size of each batch during training.
- epochs: The number of the iteration over the training set for training.
- """
-
- model = sentiment_model.CNN(emb_dim, voc_size, sen_len,
- hid_dim, dataset.get_num_class(dataset_name),
- _DROPOUT_RATE)
- model.summary()
-
- model.compile(loss="categorical_crossentropy",
- optimizer="rmsprop",
- metrics=["accuracy"])
-
- tf.logging.info("Loading the data")
- x_train, y_train, x_test, y_test = dataset.load(
- dataset_name, voc_size, sen_len)
-
- if not os.path.exists(model_save_dir):
- os.makedirs(model_save_dir)
-
- filepath=model_save_dir+"/model-{epoch:02d}.hdf5"
-
- checkpoint_callback = tf.keras.callbacks.ModelCheckpoint(filepath, monitor='val_accuracy',
- verbose=1,save_best_only=True,
- save_weights_only=True,mode='auto')
-
-
- model.fit(x_train, y_train, batch_size=batch_size,
- validation_split=0.4, epochs=epochs, callbacks=[checkpoint_callback])
-
- score = model.evaluate(x_test, y_test, batch_size=batch_size)
-
- model.save(os.path.join(model_save_dir, "full-model.h5"))
-
- tf.logging.info("Score: {}".format(score))
-
-if __name__ == "__main__":
- parser = argparse.ArgumentParser()
- parser.add_argument("-d", "--dataset", help="Dataset to be trained "
- "and evaluated.",
- type=str, choices=["imdb"], default="imdb")
-
- parser.add_argument("-e", "--embedding_dim",
- help="The dimension of the Embedding layer.",
- type=int, default=512)
-
- parser.add_argument("-v", "--vocabulary_size",
- help="The number of the words to be considered "
- "in the dataset corpus.",
- type=int, default=6000)
-
- parser.add_argument("-s", "--sentence_length",
- help="The number of words in a data point."
- "Entries of smaller length are padded.",
- type=int, default=600)
-
- parser.add_argument("-c", "--hidden_dim",
- help="The number of the CNN layer filters.",
- type=int, default=512)
-
- parser.add_argument("-b", "--batch_size",
- help="The size of each batch for training.",
- type=int, default=500)
-
- parser.add_argument("-p", "--epochs",
- help="The number of epochs for training.",
- type=int, default=55)
-
- parser.add_argument("-f", "--folder",
- help="folder/dir to save trained model",
- type=str, default=None)
- args = parser.parse_args()
-
- if args.folder is None:
- parser.error("-f argument folder/dir to save is None,provide path to save model.")
-
- run_model(args.dataset, args.embedding_dim, args.vocabulary_size,
- args.sentence_length, args.hidden_dim,
- args.batch_size, args.epochs, args.folder)
diff --git a/research/sentiment_analysis/sentiment_model.py b/research/sentiment_analysis/sentiment_model.py
deleted file mode 100644
index 586474992ab4521512bbbb5156be0b306f94c3bb..0000000000000000000000000000000000000000
--- a/research/sentiment_analysis/sentiment_model.py
+++ /dev/null
@@ -1,50 +0,0 @@
-"""Model for sentiment analysis.
-
-The model makes use of concatenation of two CNN layers with
-different kernel sizes.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-
-class CNN(tf.keras.models.Model):
- """CNN for sentimental analysis."""
-
- def __init__(self, emb_dim, num_words, sentence_length, hid_dim,
- class_dim, dropout_rate):
- """Initialize CNN model.
-
- Args:
- emb_dim: The dimension of the Embedding layer.
- num_words: The number of the most frequent tokens
- to be used from the corpus.
- sentence_length: The number of words in each sentence.
- Longer sentences get cut, shorter ones padded.
- hid_dim: The dimension of the Embedding layer.
- class_dim: The number of the CNN layer filters.
- dropout_rate: The portion of kept value in the Dropout layer.
- Returns:
- tf.keras.models.Model: A Keras model.
- """
-
- input_layer = tf.keras.layers.Input(shape=(sentence_length,), dtype=tf.int32)
-
- layer = tf.keras.layers.Embedding(num_words, output_dim=emb_dim)(input_layer)
-
- layer_conv3 = tf.keras.layers.Conv1D(hid_dim, 3, activation="relu")(layer)
- layer_conv3 = tf.keras.layers.GlobalMaxPooling1D()(layer_conv3)
-
- layer_conv4 = tf.keras.layers.Conv1D(hid_dim, 2, activation="relu")(layer)
- layer_conv4 = tf.keras.layers.GlobalMaxPooling1D()(layer_conv4)
-
- layer = tf.keras.layers.concatenate([layer_conv4, layer_conv3], axis=1)
- layer = tf.keras.layers.BatchNormalization()(layer)
- layer = tf.keras.layers.Dropout(dropout_rate)(layer)
-
- output = tf.keras.layers.Dense(class_dim, activation="softmax")(layer)
-
- super(CNN, self).__init__(inputs=[input_layer], outputs=output)
diff --git a/research/seq2species/README.md b/research/seq2species/README.md
deleted file mode 100644
index dbe473131d59fe990e1ff344ea69bb5bd05972e4..0000000000000000000000000000000000000000
--- a/research/seq2species/README.md
+++ /dev/null
@@ -1,187 +0,0 @@
-
-
-
-
-# Seq2Species: Neural Network Models for Species Classification
-
-*A deep learning solution for read-level taxonomic classification with 16s.*
-
-Recent improvements in sequencing technology have made possible large, public
-databases of biological sequencing data, bringing about new data richness for
-many important problems in bioinformatics. However, this growing availability of
-data creates a need for analysis methods capable of efficiently handling these
-large sequencing datasets. We on the [Genomics team in Google
-Brain](https://ai.google/research/teams/brain/healthcare-biosciences) are
-particularly interested in the class of problems which can be framed as
-assigning meaningful labels to short biological sequences, and are exploring the
-possiblity of creating a general deep learning solution for solving this class
-of sequence-labeling problems. We are excited to share our initial progress in
-this direction by releasing Seq2Species, an open-source neural network framework
-for [TensorFlow](https://www.tensorflow.org/) for predicting read-level
-taxonomic labels from genomic sequence. Our release includes all the code
-necessary to train new Seq2Species models.
-
-## About Seq2Species
-
-Briefly, Seq2Species provides a framework for training deep neural networks to
-predict database-derived labels directly from short reads of DNA. Thus far, our
-research has focused predominantly on demonstrating the value of this deep
-learning approach on the problem of determining the species of origin of
-next-generation sequencing reads from [16S ribosomal
-DNA](https://en.wikipedia.org/wiki/16S_ribosomal_RNA). We used this
-Seq2Species framework to train depthwise separable convolutional neural networks
-on short subsequences from the 16S genes of more than 13 thousand distinct
-species. The resulting classification model assign species-level probabilities
-to individual 16S reads.
-
-For more information about the use cases we have explored, or for technical
-details describing how Seq2Species work, please see our
-[preprint](https://www.biorxiv.org/content/early/2018/06/22/353474).
-
-## Installation
-
-Training Seq2Species models requires installing the following dependencies:
-
-* python 2.7
-
-* protocol buffers
-
-* numpy
-
-* absl
-
-### Dependencies
-
-Detailed instructions for installing TensorFlow are available on the [Installing
-TensorFlow](https://www.tensorflow.org/install/) website. Please follow the
-full instructions for installing TensorFlow with GPU support. For most
-users, the following command will suffice for continuing with CPU support only:
-```bash
-# For CPU
-pip install --upgrade tensorflow
-```
-
-The TensorFlow installation should also include installation of the numpy and
-absl libraries, which are two of TensorFlow's python dependencies. If
-necessary, instructions for standalone installation are available:
-
-* [numpy](https://scipy.org/install.html)
-
-* [absl](https://github.com/abseil/abseil-py)
-
-Information about protocol buffers, as well as download and installation
-intructions for the protocol buffer (protobuf) compiler, are available on the [Google
-Developers website](https://developers.google.com/protocol-buffers/). A typical
-Ubuntu user can install this library using `apt-get`:
-```bash
-sudo apt-get install protobuf-compiler
-```
-
-### Clone
-
-Now, clone `tensorflow/models` to start working with the code:
-```bash
-git clone https://github.com/tensorflow/models.git
-```
-
-### Protobuf Compilation
-
-Seq2Species uses protobufs to store and save dataset and model metadata. Before
-the framework can be used to build and train models, the protobuf libraries must
-be compiled. This can be accomplished using the following command:
-```bash
-# From tensorflow/models/research
-protoc seq2species/protos/seq2label.proto --python_out=.
-```
-
-### Testing the Installation
-
-One can test that Seq2Species has been installed correctly by running the
-following command:
-```bash
-python seq2species/run_training_test.py
-```
-
-## Usage Information
-
-Input data to Seq2Species models should be [tf.train.Example protocol messages](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/core/example/example.proto) stored in
-[TFRecord format](https://www.tensorflow.org/versions/r1.0/api_guides/python/python_io#tfrecords_format_details).
-Specifically, the input pipeline expects tf.train.Examples with a 'sequence' field
-containing a genomic sequence as an upper-case string, as one field for each
-target label (e.g. 'species'). There should also be an accompanying
-Seq2LabelDatasetInfo text protobuf containing metadata about the input, including
-the possible label values for each target.
-
-Below, we give an example command that could be used to launch training for 1000
-steps, assuming that appropriate data and metadata files are stored at
-`${TFRECORD}` and `${DATASET_INFO}`:
-```bash
-python seq2species/run_training.py --train_files ${TFRECORD}
---metadata_path ${DATASET_INFO} --hparams 'train_steps=1000'
---logdir $HOME/seq2species
-```
-This will output [TensorBoard
-summaries](https://www.tensorflow.org/guide/summaries_and_tensorboard), [TensorFlow
-checkpoints](https://www.tensorflow.org/guide/variables#checkpoint_files), Seq2LabelModelInfo and
-Seq2LabelExperimentMeasures metadata to the logdir `$HOME/seq2species`.
-
-### Preprocessed Seq2Species Data
-
-We have provided preprocessed data based on 16S reference sequences from the
-[NCBI RefSeq Targeted Loci
-Project](https://www.ncbi.nlm.nih.gov/refseq/targetedloci/) in a Seq2Species
-bucket on Google Cloud Storage. After installing the
-[Cloud SDK](https://cloud.google.com/sdk/install),
-one can download those data (roughly 25 GB) to a local directory `${DEST}` using
-the `gsutil` command:
-```bash
-BUCKET=gs://brain-genomics-public/research/seq2species
-mkdir -p ${DEST}
-gsutil -m cp ${BUCKET}/* ${DEST}
-```
-
-To check if the copy has completed successsfully, check the `${DEST}` directory:
-```bash
-ls -1 ${DEST}
-```
-which should produce:
-```bash
-ncbi_100bp_revcomp.dataset_info.pbtxt
-ncbi_100bp_revcomp.tfrecord
-```
-
-The following command can be used to train a copy of one of our best-perfoming
-deep neural network models for 100 base pair (bp) data. This command also
-illustrates how to set hyperparameter values explicitly from the commandline.
-The file `configuration.py` provides a full list of hyperparameters, their descriptions,
-and their default values. Additional flags are described at the top of
-`run_training.py`.
-```bash
-python seq2species/run_training.py \
---num_filters 3 \
---noise_rate 0.04 \
---train_files ${DEST}/ncbi_100bp_revcomp.tfrecord \
---metadata_path ${DEST}/ncbi_100bp_revcomp.dataset_info.pbtxt \
---logdir $HOME/seq2species \
---hparams 'filter_depths=[1,1,1],filter_widths=[5,9,13],grad_clip_norm=20.0,keep_prob=0.94017831318,
-lr_decay=0.0655052811,lr_init=0.000469689635793,lrelu_slope=0.0125376069918,min_read_length=100,num_fc_layers=2,num_fc_units=2828,optimizer=adam,optimizer_hp=0.885769367218,pointwise_depths=[84,58,180],pooling_type=avg,train_steps=3000000,use_depthwise_separable=true,weight_scale=1.18409526348'
-```
-
-### Visualization
-
-[TensorBoard](https://github.com/tensorflow/tensorboard) can be used to
-visualize training curves and other metrics stored in the summary files produced
-by `run_training.py`. Use the following command to launch a TensorBoard instance
-for the example model directory `$HOME/seq2species`:
-```bash
-tensorboard --logdir=$HOME/seq2species
-```
-
-## Contact
-
-Any issues with the Seq2Species framework should be filed with the
-[TensorFlow/models issue tracker](https://github.com/tensorflow/models/issues).
-Questions regarding Seq2Species capabilities can be directed to
-[seq2species-interest@google.com](mailto:seq2species-interest@google.com). This
-code is maintained by [@apbusia](https://github.com/apbusia) and
-[@depristo](https://github.com/depristo).
diff --git a/research/seq2species/build_model.py b/research/seq2species/build_model.py
deleted file mode 100644
index 9f4ae6b2eb2c1b4b4deeba99a0fbcf3be0ca644a..0000000000000000000000000000000000000000
--- a/research/seq2species/build_model.py
+++ /dev/null
@@ -1,506 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Defines convolutional model graph for Seq2Species.
-
-Builds TensorFlow computation graph for predicting the given taxonomic target
-labels from short reads of DNA using convolutional filters, followed by
-fully-connected layers and a softmax output layer.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-import math
-
-import tensorflow as tf
-
-import input as seq2species_input
-import seq2label_utils
-
-
-class ConvolutionalNet(object):
- """Class to build and store the model's computational graph and operations.
-
- Attributes:
- read_length: int; the length in basepairs of the input reads of DNA.
- placeholders: dict; mapping from name to tf.Placeholder.
- global_step: tf.Variable tracking number of training iterations performed.
- train_op: operation to perform one training step by gradient descent.
- summary_op: operation to log model's performance metrics to TF event files.
- accuracy: tf.Variable giving the model's read-level accuracy for the
- current inputs.
- weighted_accuracy: tf.Variable giving the model's read-level weighted
- accuracy for the current inputs.
- loss: tf.Variable giving the model's current cross entropy loss.
- logits: tf.Variable containing the model's logits for the current inputs.
- predictions: tf.Variable containing the model's current predicted
- probability distributions for the current inputs.
- possible_labels: a dict of possible label values (list of strings), keyed by
- target name. Labels in the lists are the order used for integer encoding.
- use_tpu: whether model is to be run on TPU.
- """
-
- def __init__(self, hparams, dataset_info, targets, use_tpu=False):
- """Initializes the ConvolutionalNet according to provided hyperparameters.
-
- Does not build the graph---this is done by calling `build_graph` on the
- constructed object or using `model_fn`.
-
- Args:
- hparams: tf.contrib.training.Hparams object containing the model's
- hyperparamters; see configuration.py for hyperparameter definitions.
- dataset_info: a `Seq2LabelDatasetInfo` message reflecting the dataset
- metadata.
- targets: list of strings: the names of the prediction targets.
- use_tpu: whether we are running on TPU; if True, summaries will be
- disabled.
- """
- self._placeholders = {}
- self._targets = targets
- self._dataset_info = dataset_info
- self._hparams = hparams
- all_label_values = seq2label_utils.get_all_label_values(self.dataset_info)
- self._possible_labels = {
- target: all_label_values[target]
- for target in self.targets
- }
- self._use_tpu = use_tpu
-
- @property
- def hparams(self):
- return self._hparams
-
- @property
- def dataset_info(self):
- return self._dataset_info
-
- @property
- def possible_labels(self):
- return self._possible_labels
-
- @property
- def bases(self):
- return seq2species_input.DNA_BASES
-
- @property
- def n_bases(self):
- return seq2species_input.NUM_DNA_BASES
-
- @property
- def targets(self):
- return self._targets
-
- @property
- def read_length(self):
- return self.dataset_info.read_length
-
- @property
- def placeholders(self):
- return self._placeholders
-
- @property
- def global_step(self):
- return self._global_step
-
- @property
- def train_op(self):
- return self._train_op
-
- @property
- def summary_op(self):
- return self._summary_op
-
- @property
- def accuracy(self):
- return self._accuracy
-
- @property
- def weighted_accuracy(self):
- return self._weighted_accuracy
-
- @property
- def loss(self):
- return self._loss
-
- @property
- def total_loss(self):
- return self._total_loss
-
- @property
- def logits(self):
- return self._logits
-
- @property
- def predictions(self):
- return self._predictions
-
- @property
- def use_tpu(self):
- return self._use_tpu
-
- def _summary_scalar(self, name, scalar):
- """Adds a summary scalar, if the platform supports summaries."""
- if not self.use_tpu:
- return tf.summary.scalar(name, scalar)
- else:
- return None
-
- def _summary_histogram(self, name, values):
- """Adds a summary histogram, if the platform supports summaries."""
- if not self.use_tpu:
- return tf.summary.histogram(name, values)
- else:
- return None
-
- def _init_weights(self, shape, scale=1.0, name='weights'):
- """Randomly initializes a weight Tensor of the given shape.
-
- Args:
- shape: list; desired Tensor dimensions.
- scale: float; standard deviation scale with which to initialize weights.
- name: string name for the variable.
-
- Returns:
- TF Variable contining truncated random Normal initialized weights.
- """
- num_inputs = shape[0] if len(shape) < 3 else shape[0] * shape[1] * shape[2]
- stddev = scale / math.sqrt(num_inputs)
- return tf.get_variable(
- name,
- shape=shape,
- initializer=tf.truncated_normal_initializer(0., stddev))
-
- def _init_bias(self, size):
- """Initializes bias vector of given shape as zeros.
-
- Args:
- size: int; desired size of bias Tensor.
-
- Returns:
- TF Variable containing the initialized biases.
- """
- return tf.get_variable(
- name='b_{}'.format(size),
- shape=[size],
- initializer=tf.zeros_initializer())
-
- def _add_summaries(self, mode, gradient_norm, parameter_norm):
- """Defines TensorFlow operation for logging summaries to event files.
-
- Args:
- mode: the ModeKey string.
- gradient_norm: Tensor; norm of gradients produced during the current
- training operation.
- parameter_norm: Tensor; norm of the model parameters produced during the
- current training operation.
- """
- # Log summaries for TensorBoard.
- if mode == tf.estimator.ModeKeys.TRAIN:
- self._summary_scalar('norm_of_gradients', gradient_norm)
- self._summary_scalar('norm_of_parameters', parameter_norm)
- self._summary_scalar('total_loss', self.total_loss)
- self._summary_scalar('learning_rate', self._learn_rate)
- for target in self.targets:
- self._summary_scalar('per_read_weighted_accuracy/{}'.format(target),
- self.weighted_accuracy[target])
- self._summary_scalar('per_read_accuracy/{}'.format(target),
- self.accuracy[target])
- self._summary_histogram('prediction_frequency/{}'.format(target),
- self._predictions[target])
- self._summary_scalar('cross_entropy_loss/{}'.format(target),
- self._loss[target])
- self._summary_op = tf.summary.merge_all()
- else:
- # Log average performance metrics over many batches using placeholders.
- summaries = []
- for target in self.targets:
- accuracy_ph = tf.placeholder(tf.float32, shape=())
- weighted_accuracy_ph = tf.placeholder(tf.float32, shape=())
- cross_entropy_ph = tf.placeholder(tf.float32, shape=())
- self._placeholders.update({
- 'accuracy/{}'.format(target): accuracy_ph,
- 'weighted_accuracy/{}'.format(target): weighted_accuracy_ph,
- 'cross_entropy/{}'.format(target): cross_entropy_ph,
- })
- summaries += [
- self._summary_scalar('cross_entropy_loss/{}'.format(target),
- cross_entropy_ph),
- self._summary_scalar('per_read_accuracy/{}'.format(target),
- accuracy_ph),
- self._summary_scalar('per_read_weighted_accuracy/{}'.format(target),
- weighted_accuracy_ph)
- ]
-
- self._summary_op = tf.summary.merge(summaries)
-
- def _convolution(self,
- inputs,
- filter_dim,
- pointwise_dim=None,
- scale=1.0,
- padding='SAME'):
- """Applies convolutional filter of given dimensions to given input Tensor.
-
- If a pointwise dimension is specified, a depthwise separable convolution is
- performed.
-
- Args:
- inputs: 4D Tensor of shape (# reads, 1, # basepairs, # bases).
- filter_dim: integer tuple of the form (width, depth).
- pointwise_dim: int; output dimension for pointwise convolution.
- scale: float; standard deviation scale with which to initialize weights.
- padding: string; type of padding to use. One of "SAME" or "VALID".
-
- Returns:
- 4D Tensor result of applying the convolutional filter to the inputs.
- """
- in_channels = inputs.get_shape()[3].value
- filter_width, filter_depth = filter_dim
- filters = self._init_weights([1, filter_width, in_channels, filter_depth],
- scale)
- self._summary_histogram(filters.name.split(':')[0].split('/')[1], filters)
- if pointwise_dim is None:
- return tf.nn.conv2d(
- inputs,
- filters,
- strides=[1, 1, 1, 1],
- padding=padding,
- name='weights')
- pointwise_filters = self._init_weights(
- [1, 1, filter_depth * in_channels, pointwise_dim],
- scale,
- name='pointwise_weights')
- self._summary_histogram(
- pointwise_filters.name.split(':')[0].split('/')[1], pointwise_filters)
- return tf.nn.separable_conv2d(
- inputs,
- filters,
- pointwise_filters,
- strides=[1, 1, 1, 1],
- padding=padding)
-
- def _pool(self, inputs, pooling_type):
- """Performs pooling across width and height of the given inputs.
-
- Args:
- inputs: Tensor shaped (batch, height, width, channels) over which to pool.
- In our case, height is a unitary dimension and width can be thought of
- as the read dimension.
- pooling_type: string; one of "avg" or "max".
-
- Returns:
- Tensor result of performing pooling of the given pooling_type over the
- height and width dimensions of the given inputs.
- """
- if pooling_type == 'max':
- return tf.reduce_max(inputs, axis=[1, 2])
- if pooling_type == 'avg':
- return tf.reduce_sum(
- inputs, axis=[1, 2]) / tf.to_float(tf.shape(inputs)[2])
-
- def _leaky_relu(self, lrelu_slope, inputs):
- """Applies leaky ReLu activation to the given inputs with the given slope.
-
- Args:
- lrelu_slope: float; slope value for the activation function.
- A slope of 0.0 defines a standard ReLu activation, while a positive
- slope defines a leaky ReLu.
- inputs: Tensor upon which to apply the activation function.
-
- Returns:
- Tensor result of applying the activation function to the given inputs.
- """
- with tf.variable_scope('leaky_relu_activation'):
- return tf.maximum(lrelu_slope * inputs, inputs)
-
- def _dropout(self, inputs, keep_prob):
- """Applies dropout to the given inputs.
-
- Args:
- inputs: Tensor upon which to apply dropout.
- keep_prob: float; probability with which to randomly retain values in
- the given input.
-
- Returns:
- Tensor result of applying dropout to the given inputs.
- """
- with tf.variable_scope('dropout'):
- if keep_prob < 1.0:
- return tf.nn.dropout(inputs, keep_prob)
- return inputs
-
- def build_graph(self, features, labels, mode, batch_size):
- """Creates TensorFlow model graph.
-
- Args:
- features: a dict of input features Tensors.
- labels: a dict (by target name) of prediction labels.
- mode: the ModeKey string.
- batch_size: the integer batch size.
-
- Side Effect:
- Adds the following key Tensors and operations as class attributes:
- placeholders, global_step, train_op, summary_op, accuracy,
- weighted_accuracy, loss, logits, and predictions.
- """
- is_train = (mode == tf.estimator.ModeKeys.TRAIN)
- read = features['sequence']
-
- # Add a unitary dimension, so we can use conv2d.
- read = tf.expand_dims(read, 1)
- prev_out = read
-
- filters = zip(self.hparams.filter_widths, self.hparams.filter_depths)
- for i, f in enumerate(filters):
- with tf.variable_scope('convolution_' + str(i)):
- if self.hparams.use_depthwise_separable:
- p = self.hparams.pointwise_depths[i]
- else:
- p = None
- conv_out = self._convolution(
- prev_out, f, pointwise_dim=p, scale=self.hparams.weight_scale)
- conv_act_out = self._leaky_relu(self.hparams.lrelu_slope, conv_out)
- prev_out = (
- self._dropout(conv_act_out, self.hparams.keep_prob)
- if is_train else conv_act_out)
-
- for i in xrange(self.hparams.num_fc_layers):
- with tf.variable_scope('fully_connected_' + str(i)):
- # Create a convolutional layer which is equivalent to a fully-connected
- # layer when reads have length self.hparams.min_read_length.
- # The convolution will tile the layer appropriately for longer reads.
- biases = self._init_bias(self.hparams.num_fc_units)
- if i == 0:
- # Take entire min_read_length segment as input.
- # Output a single value per min_read_length_segment.
- filter_dimensions = (self.hparams.min_read_length,
- self.hparams.num_fc_units)
- else:
- # Take single output value of previous layer as input.
- filter_dimensions = (1, self.hparams.num_fc_units)
- fc_out = biases + self._convolution(
- prev_out,
- filter_dimensions,
- scale=self.hparams.weight_scale,
- padding='VALID')
- self._summary_histogram(biases.name.split(':')[0].split('/')[1], biases)
- fc_act_out = self._leaky_relu(self.hparams.lrelu_slope, fc_out)
- prev_out = (
- self._dropout(fc_act_out, self.hparams.keep_prob)
- if is_train else fc_act_out)
-
- # Pool to collapse tiling for reads longer than hparams.min_read_length.
- with tf.variable_scope('pool'):
- pool_out = self._pool(prev_out, self.hparams.pooling_type)
-
- with tf.variable_scope('output'):
- self._logits = {}
- self._predictions = {}
- self._weighted_accuracy = {}
- self._accuracy = {}
- self._loss = collections.OrderedDict()
-
- for target in self.targets:
- with tf.variable_scope(target):
- label = labels[target]
- possible_labels = self.possible_labels[target]
- weights = self._init_weights(
- [pool_out.get_shape()[1].value,
- len(possible_labels)],
- self.hparams.weight_scale,
- name='weights')
- biases = self._init_bias(len(possible_labels))
- self._summary_histogram(
- weights.name.split(':')[0].split('/')[1], weights)
- self._summary_histogram(
- biases.name.split(':')[0].split('/')[1], biases)
- logits = tf.matmul(pool_out, weights) + biases
- predictions = tf.nn.softmax(logits)
-
- gather_inds = tf.stack([tf.range(batch_size), label], axis=1)
- self._weighted_accuracy[target] = tf.reduce_mean(
- tf.gather_nd(predictions, gather_inds))
- argmax_prediction = tf.cast(tf.argmax(predictions, axis=1), tf.int32)
- self._accuracy[target] = tf.reduce_mean(
- tf.to_float(tf.equal(label, argmax_prediction)))
-
- losses = tf.nn.sparse_softmax_cross_entropy_with_logits(
- labels=label, logits=logits)
- self._loss[target] = tf.reduce_mean(losses)
- self._logits[target] = logits
- self._predictions[target] = predictions
-
- # Compute total loss
- self._total_loss = tf.add_n(self._loss.values())
-
- # Define the optimizer.
-
- # tf.estimator framework builds the global_step for us, but if we aren't
- # using the framework we have to make it ourselves.
- self._global_step = tf.train.get_or_create_global_step()
- if self.hparams.lr_decay < 0:
- self._learn_rate = self.hparams.lr_init
- else:
- self._learn_rate = tf.train.exponential_decay(
- self.hparams.lr_init,
- self._global_step,
- int(self.hparams.train_steps),
- self.hparams.lr_decay,
- staircase=False)
- if self.hparams.optimizer == 'adam':
- opt = tf.train.AdamOptimizer(self._learn_rate, self.hparams.optimizer_hp)
- elif self.hparams.optimizer == 'momentum':
- opt = tf.train.MomentumOptimizer(self._learn_rate,
- self.hparams.optimizer_hp)
- if self.use_tpu:
- opt = tf.contrib.tpu.CrossShardOptimizer(opt)
-
- gradients, variables = zip(*opt.compute_gradients(self._total_loss))
- clipped_gradients, _ = tf.clip_by_global_norm(gradients,
- self.hparams.grad_clip_norm)
- with tf.control_dependencies(tf.get_collection(tf.GraphKeys.UPDATE_OPS)):
- self._train_op = opt.apply_gradients(
- zip(clipped_gradients, variables), global_step=self._global_step)
-
- if not self.use_tpu:
- grad_norm = tf.global_norm(gradients) if is_train else None
- param_norm = tf.global_norm(variables) if is_train else None
- self._add_summaries(mode, grad_norm, param_norm)
-
- def model_fn(self, features, labels, mode, params):
- """Function fulfilling the tf.estimator model_fn interface.
-
- Args:
- features: a dict containing the input features for prediction.
- labels: a dict from target name to Tensor-value prediction.
- mode: the ModeKey string.
- params: a dictionary of parameters for building the model; current params
- are params["batch_size"]: the integer batch size.
-
- Returns:
- A tf.estimator.EstimatorSpec object ready for use in training, inference.
- or evaluation.
- """
- self.build_graph(features, labels, mode, params['batch_size'])
-
- return tf.estimator.EstimatorSpec(
- mode,
- predictions=self.predictions,
- loss=self.total_loss,
- train_op=self.train_op,
- eval_metric_ops={})
diff --git a/research/seq2species/configuration.py b/research/seq2species/configuration.py
deleted file mode 100644
index a4dd626e27246a79292a80d165b199c42a154df5..0000000000000000000000000000000000000000
--- a/research/seq2species/configuration.py
+++ /dev/null
@@ -1,77 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Defines hyperparameter configuration for ConvolutionalNet models.
-
-Specifically, provides methods for defining and initializing TensorFlow
-hyperparameters objects for a convolutional model as defined in:
-seq2species.build_model
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import tensorflow as tf
-
-
-def parse_hparams(hparam_values='', num_filters=1):
- """Initializes TensorFlow hyperparameters object with default values.
-
- In addition, default hyperparameter values are overwritten with the specified
- ones, where necessary.
-
- Args:
- hparam_values: comma-separated string of name=value pairs for setting
- particular hyperparameters.
- num_filters: int; number of filters in the model.
- Must be fixed outside of hyperparameter/study object as Vizier does not
- support having inter-hyperparameter dependencies.
-
- Returns:
- tf.contrib.training.Hparams object containing the model's hyperparameters.
- """
- hparams = tf.contrib.training.HParams()
-
- # Specify model architecture option.
- hparams.add_hparam('use_depthwise_separable', True)
-
- # Specify number of model parameters.
- hparams.add_hparam('filter_widths', [3] * num_filters)
- hparams.add_hparam('filter_depths', [1] * num_filters)
- hparams.add_hparam('pointwise_depths', [64] * num_filters)
- hparams.add_hparam('num_fc_layers', 2)
- hparams.add_hparam('num_fc_units', 455)
- hparams.add_hparam('min_read_length', 100)
- hparams.add_hparam('pooling_type', 'avg')
-
- # Specify activation options.
- hparams.add_hparam('lrelu_slope', 0.0) # Negative slope for leaky relu.
-
- # Specify training options.
- hparams.add_hparam('keep_prob', 1.0)
- hparams.add_hparam('weight_scale', 1.0)
- hparams.add_hparam('grad_clip_norm', 20.0)
- hparams.add_hparam('lr_init', 0.001)
- hparams.add_hparam('lr_decay', 0.1)
- hparams.add_hparam('optimizer', 'adam')
- # optimizer_hp is decay rate for 1st moment estimates for ADAM, and
- # momentum for SGD.
- hparams.add_hparam('optimizer_hp', 0.9)
- hparams.add_hparam('train_steps', 400000)
-
- # Overwrite defaults with specified values.
- hparams.parse(hparam_values)
- return hparams
diff --git a/research/seq2species/input.py b/research/seq2species/input.py
deleted file mode 100644
index f1636c87501175d7a6940693e00ae5713a1780ff..0000000000000000000000000000000000000000
--- a/research/seq2species/input.py
+++ /dev/null
@@ -1,325 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Input pipe for feeding examples to a Seq2Label model graph."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import tensorflow as tf
-from google.protobuf import text_format
-
-from protos import seq2label_pb2
-import seq2label_utils
-
-DNA_BASES = tuple('ACGT')
-NUM_DNA_BASES = len(DNA_BASES)
-# Possible FASTA characters/IUPAC ambiguity codes.
-# See https://en.wikipedia.org/wiki/Nucleic_acid_notation.
-AMBIGUITY_CODES = {
- 'K': 'GT',
- 'M': 'AC',
- 'R': 'AG',
- 'Y': 'CT',
- 'S': 'CG',
- 'W': 'AT',
- 'B': 'CGT',
- 'V': 'ACG',
- 'H': 'ACT',
- 'D': 'AGT',
- 'X': 'ACGT',
- 'N': 'ACGT'
-}
-
-
-def load_dataset_info(dataset_info_path):
- """Load a `Seq2LabelDatasetInfo` from a serialized text proto file."""
- dataset_info = seq2label_pb2.Seq2LabelDatasetInfo()
- with tf.gfile.Open(dataset_info_path, 'r') as f:
- text_format.Parse(f.read(), dataset_info)
- return dataset_info
-
-
-class _InputEncoding(object):
- """A helper class providing the graph operations needed to encode input.
-
- Instantiation of an _InputEncoding will write on the default TF graph, so it
- should only be instantiated inside the `input_fn`.
-
- Attributes:
- mode: `tf.estimator.ModeKeys`; the execution mode {TRAIN, EVAL, INFER}.
- targets: list of strings; the names of the labels of interest (e.g.
- "species").
- dna_bases: a tuple of the recognized DNA alphabet.
- n_bases: the size of the DNA alphabet.
- all_characters: list of recognized alphabet, including ambiguity codes.
- label_values: a tuple of strings, the possible label values of the
- prediction target.
- n_labels: the size of label_values
- fixed_read_length: an integer value of the statically-known read length, or
- None if the read length is to be determined dynamically.
- """
-
- def __init__(self,
- dataset_info,
- mode,
- targets,
- noise_rate=0.0,
- fixed_read_length=None):
- self.mode = mode
- self.targets = targets
- self.dna_bases = DNA_BASES
- self.n_bases = NUM_DNA_BASES
- self.all_characters = list(DNA_BASES) + sorted(AMBIGUITY_CODES.keys())
- self.character_encodings = np.concatenate(
- [[self._character_to_base_distribution(char)]
- for char in self.all_characters],
- axis=0)
- all_legal_label_values = seq2label_utils.get_all_label_values(dataset_info)
- # TF lookup tables.
- self.characters_table = tf.contrib.lookup.index_table_from_tensor(
- mapping=self.all_characters)
- self.label_tables = {
- target: tf.contrib.lookup.index_table_from_tensor(
- all_legal_label_values[target])
- for target in targets
- }
- self.fixed_read_length = fixed_read_length
- self.noise_rate = noise_rate
-
- def _character_to_base_distribution(self, char):
- """Maps the given character to a probability distribution over DNA bases.
-
- Args:
- char: character to be encoded as a probability distribution over bases.
-
- Returns:
- Array of size (self.n_bases,) representing the identity of the given
- character as a distribution over the possible DNA bases, self.dna_bases.
-
- Raises:
- ValueError: if the given character is not contained in the recognized
- alphabet, self.all_characters.
- """
- if char not in self.all_characters:
- raise ValueError(
- 'Base distribution requested for unrecognized character %s.' % char)
- possible_bases = AMBIGUITY_CODES[char] if char in AMBIGUITY_CODES else char
- base_indices = [self.dna_bases.index(base) for base in possible_bases]
- probability_weight = 1.0 / len(possible_bases)
- distribution = np.zeros((self.n_bases))
- distribution[base_indices] = probability_weight
- return distribution
-
- def encode_read(self, string_seq):
- """Converts the input read sequence to one-hot encoding.
-
- Args:
- string_seq: tf.String; input read sequence.
-
- Returns:
- Input read sequence as a one-hot encoded Tensor, with depth and ordering
- of one-hot encoding determined by the given bases. Ambiguous characters
- such as "N" and "S" are encoded as a probability distribution over the
- possible bases they represent.
- """
- with tf.variable_scope('encode_read'):
- read = tf.string_split([string_seq], delimiter='').values
- read = self.characters_table.lookup(read)
- read = tf.cast(tf.gather(self.character_encodings, read), tf.float32)
- if self.fixed_read_length:
- read = tf.reshape(read, (self.fixed_read_length, self.n_bases))
- return read
-
- def encode_label(self, target, string_label):
- """Converts the label value to an integer encoding.
-
- Args:
- target: str; the target name.
- string_label: tf.String; value of the label for the current input read.
-
- Returns:
- Given label value as an index into the possible_target_values.
- """
- with tf.variable_scope('encode_label/{}'.format(target)):
- return tf.cast(self.label_tables[target].lookup(string_label), tf.int32)
-
- def _empty_label(self):
- return tf.constant((), dtype=tf.int32, shape=())
-
- def parse_single_tfexample(self, serialized_example):
- """Parses a tf.train.Example proto to a one-hot encoded read, label pair.
-
- Injects noise into the incoming tf.train.Example's read sequence
- when noise_rate is non-zero.
-
- Args:
- serialized_example: string; the serialized tf.train.Example proto
- containing the read sequence and label value of interest as
- tf.FixedLenFeatures.
-
- Returns:
- Tuple (features, labels) of dicts for the input features and prediction
- targets.
- """
- with tf.variable_scope('parse_single_tfexample'):
- features_spec = {'sequence': tf.FixedLenFeature([], tf.string)}
- for target in self.targets:
- features_spec[target] = tf.FixedLenFeature([], tf.string)
- features = tf.parse_single_example(
- serialized_example, features=features_spec)
- if self.noise_rate > 0.0:
- read_sequence = tf.py_func(seq2label_utils.add_read_noise,
- [features['sequence'], self.noise_rate],
- (tf.string))
- else:
- read_sequence = features['sequence']
- read_sequence = self.encode_read(read_sequence)
- read_features = {'sequence': read_sequence}
- if self.mode in (tf.estimator.ModeKeys.TRAIN, tf.estimator.ModeKeys.EVAL):
- label = {
- target: self.encode_label(target, features[target])
- for target in self.targets
- }
- else:
- label = {target: self._empty_label() for target in self.targets}
- return read_features, label
-
-
-class InputDataset(object):
- """A class providing access to input data for the Seq2Label model.
-
- Attributes:
- mode: `tf.estimator.ModeKeys`; the execution mode {TRAIN, EVAL, INFER}.
- targets: list of strings; the names of the labels of interest (e.g.
- "species").
- dataset_info: a `Seq2LabelDatasetInfo` message reflecting the dataset
- metadata.
- initializer: the TF initializer op for the underlying iterator, which
- will rewind the iterator.
- is_train: Boolean indicating whether or not the execution mode is TRAIN.
- """
-
- def __init__(self,
- mode,
- targets,
- dataset_info,
- train_epochs=None,
- noise_rate=0.0,
- random_seed=None,
- input_tfrecord_files=None,
- fixed_read_length=None,
- ensure_constant_batch_size=False,
- num_parallel_calls=32):
- """Constructor for InputDataset.
-
- Args:
- mode: `tf.estimator.ModeKeys`; the execution mode {TRAIN, EVAL, INFER}.
- targets: list of strings; the names of the labels of interest (e.g.
- "species").
- dataset_info: a `Seq2LabelDatasetInfo` message reflecting the dataset
- metadata.
- train_epochs: the number of training epochs to perform, if mode==TRAIN.
- noise_rate: float [0.0, 1.0] specifying rate at which to inject
- base-flipping noise into the read sequences.
- random_seed: seed to be used for shuffling, if mode==TRAIN.
- input_tfrecord_files: a list of filenames for TFRecords of TF examples.
- fixed_read_length: an integer value of the statically-known read length,
- or None if the read length is to be determined dynamically. The read
- length must be known statically for TPU execution.
- ensure_constant_batch_size: ensure a constant batch size at the expense of
- discarding the last "short" batch. This also gives us a statically
- constant batch size, which is essential for e.g. the TPU platform.
- num_parallel_calls: the number of dataset elements to process in parallel.
- If None, elements will be processed sequentially.
- """
- self.input_tfrecord_files = input_tfrecord_files
- self.mode = mode
- self.targets = targets
- self.dataset_info = dataset_info
- self._train_epochs = train_epochs
- self._noise_rate = noise_rate
- self._random_seed = random_seed
- if random_seed is not None:
- np.random.seed(random_seed)
- self._fixed_read_length = fixed_read_length
- self._ensure_constant_batch_size = ensure_constant_batch_size
- self._num_parallel_calls = num_parallel_calls
-
- @staticmethod
- def from_tfrecord_files(input_tfrecord_files, *args, **kwargs):
- return InputDataset(
- *args, input_tfrecord_files=input_tfrecord_files, **kwargs)
-
- @property
- def is_train(self):
- return self.mode == tf.estimator.ModeKeys.TRAIN
-
- def input_fn(self, params):
- """Supplies input for the model.
-
- This function supplies input to our model as a function of the mode.
-
- Args:
- params: a dictionary, containing:
- - params['batch_size']: the integer batch size.
-
- Returns:
- A tuple of two values as follows:
- 1) the *features* dict, containing a tensor value for keys as follows:
- - "sequence" - the encoded read input sequence.
- 2) the *labels* dict. containing a key for `target`, whose value is:
- - a string Tensor value (in TRAIN/EVAL mode), or
- - a blank Tensor (PREDICT mode).
- """
- randomize_input = self.is_train
- batch_size = params['batch_size']
-
- encoding = _InputEncoding(
- self.dataset_info,
- self.mode,
- self.targets,
- noise_rate=self._noise_rate,
- fixed_read_length=self._fixed_read_length)
-
- dataset = tf.data.TFRecordDataset(self.input_tfrecord_files)
- dataset = dataset.map(
- encoding.parse_single_tfexample,
- num_parallel_calls=self._num_parallel_calls)
-
- dataset = dataset.repeat(self._train_epochs if self.is_train else 1)
- if randomize_input:
- dataset = dataset.shuffle(
- buffer_size=max(1000, batch_size), seed=self._random_seed)
-
- if self._ensure_constant_batch_size:
- # Only take batches of *exactly* size batch_size; then we get a
- # statically knowable batch shape.
- dataset = dataset.batch(batch_size, drop_remainder=True)
- else:
- dataset = dataset.batch(batch_size)
-
- # Prefetch to allow infeed to be in parallel with model computations.
- dataset = dataset.prefetch(2)
-
- # Use initializable iterator to support table lookups.
- iterator = dataset.make_initializable_iterator()
- self.initializer = iterator.initializer
- tf.add_to_collection(tf.GraphKeys.TABLE_INITIALIZERS, iterator.initializer)
-
- features, labels = iterator.get_next()
- return (features, labels)
diff --git a/research/seq2species/protos/BUILD b/research/seq2species/protos/BUILD
deleted file mode 100644
index 5628d4c41a79fc3fb6fb61fc9089f1524c49f175..0000000000000000000000000000000000000000
--- a/research/seq2species/protos/BUILD
+++ /dev/null
@@ -1,16 +0,0 @@
-# Protos for Tensorflow Seq2Species API.
-
-package(
- default_visibility = ["//visibility:public"],
-)
-
-py_proto_library(
- name = "seq2label_py_pb2",
- api_version = 2,
- deps = [":seq2label_proto"],
-)
-
-proto_library(
- name = "seq2label_proto",
- srcs = ["seq2label.proto"],
-)
diff --git a/research/seq2species/protos/__init__.py b/research/seq2species/protos/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/seq2species/protos/seq2label.proto b/research/seq2species/protos/seq2label.proto
deleted file mode 100644
index 531c4ad75e06db119c547cde34323c08f772e7fa..0000000000000000000000000000000000000000
--- a/research/seq2species/protos/seq2label.proto
+++ /dev/null
@@ -1,49 +0,0 @@
-syntax = "proto2";
-
-package seq2species.protos;
-
-// Summarizes metadata information for a dataset that can be used for running
-// training or inference.
-message Seq2LabelDatasetInfo {
- // Summarizes all possible values for a given label in the dataset.
- message LabelInfo {
- optional string name = 1;
- repeated string values = 2;
- // Per-value weights used to normalize the classes in a dataset.
- repeated float weights = 3;
- }
- repeated LabelInfo labels = 3;
- // Length (in basepairs) of the reads in the dataset.
- optional int32 read_length = 4;
- // Stride (in number of basepairs) in the moving window.
- optional int32 read_stride = 7;
- // Total number of examples in the dataset.
- optional int64 num_examples = 5;
- // Full path to the dataset.
- optional string dataset_path = 6;
-}
-
-// Summarizes metadata information about a model trained on a Seq2Label dataset.
-message Seq2LabelModelInfo {
- optional string hparams_string = 1;
- optional string model_type = 2;
- repeated string targets = 3;
- optional int32 num_filters = 4;
- optional int32 batch_size = 5;
- optional string metadata_path = 6;
- optional float training_noise_rate = 7;
-}
-
-// Summarizes resulting measures of modelling experiments.
-message Seq2LabelExperimentMeasures {
- optional string checkpoint_path = 1;
- optional int64 steps = 2;
- optional float wall_time = 3;
- optional bool experiment_infeasible = 4;
-
- message Measure {
- optional string name = 1;
- optional float value = 2;
- }
- repeated Measure measures = 5;
-}
diff --git a/research/seq2species/run_training.py b/research/seq2species/run_training.py
deleted file mode 100644
index f03bb09ecf8b1b65f9899f20cb91e3f0363a2f18..0000000000000000000000000000000000000000
--- a/research/seq2species/run_training.py
+++ /dev/null
@@ -1,293 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Defines training scheme for neural networks for Seq2Species prediction.
-
-Defines and runs the loop for training a (optionally) depthwise separable
-convolutional model for predicting taxonomic labels from short reads of DNA.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import time
-
-from absl import flags
-import numpy as np
-import tensorflow as tf
-from google.protobuf import text_format
-
-import build_model
-import configuration
-import input as seq2species_input
-from protos import seq2label_pb2
-import seq2label_utils
-
-# Define non-tunable parameters.
-flags.DEFINE_integer('num_filters', 1, 'Number of filters for conv model')
-flags.DEFINE_string('hparams', '',
- 'Comma-separated list of name=value hyperparameter '
- "pairs ('hp1=value1,hp2=value2'). Unspecified "
- 'hyperparameters will be filled with defaults.')
-flags.DEFINE_integer('batch_size', 512, 'Size of batches during training.')
-flags.DEFINE_integer('min_train_steps', 1000,
- 'Minimum number of training steps to run.')
-flags.DEFINE_float('max_task_loss', 10.0,
- "Terminate trial if task loss doesn't fall below this "
- 'within --min_train_steps.')
-flags.DEFINE_integer('n_print_progress_every', 1000,
- 'Print training progress every '
- '--n_print_progress_every global steps.')
-flags.DEFINE_list('targets', ['species'],
- 'Names of taxonomic ranks to use as training targets.')
-flags.DEFINE_float(
- 'noise_rate', 0.0, 'Rate [0.0, 1.0] at which to inject '
- 'base-flipping noise into input read sequences.')
-
-# Define paths to logs and data.
-flags.DEFINE_list(
- 'train_files', [], 'Full paths to the TFRecords containing the '
- 'training examples.')
-flags.DEFINE_string(
- 'metadata_path', '', 'Full path of the text proto containing configuration '
- 'information about the set of training examples.')
-flags.DEFINE_string('logdir', '/tmp/seq2species',
- 'Directory to which to write logs.')
-
-# Define supervisor/checkpointing options.
-flags.DEFINE_integer('task', 0, 'Task ID of the replica running the training.')
-flags.DEFINE_string('master', '', 'Name of the TF master to use.')
-flags.DEFINE_integer(
- 'save_model_secs', 900, 'Rate at which to save model parameters. '
- 'Set to 0 to disable checkpointing.')
-flags.DEFINE_integer('recovery_wait_secs', 30,
- 'Wait to recover model from checkpoint '
- 'before timing out.')
-flags.DEFINE_integer('save_summaries_secs', 900,
- 'Rate at which to save Tensorboard summaries.')
-flags.DEFINE_integer('ps_tasks', 0,
- 'Number of tasks in the ps job; 0 if no ps is used.')
-
-FLAGS = flags.FLAGS
-RANDOM_SEED = 42
-
-
-def wait_until(time_sec):
- """Stalls execution until a given time.
-
- Args:
- time_sec: time, in seconds, until which to loop idly.
- """
- while time.time() < time_sec:
- pass
-
-
-def update_measures(measures, new_measures, loss_val, max_loss=None):
- """Updates tracking of experimental measures and infeasibilty.
-
- Args:
- measures: dict; mapping from measure name to measure value.
- new_measures: dict; mapping from measure name to new measure values.
- loss_val: float; value of loss metric by which to determine fesibility.
- max_loss: float; maximum value at which to consider the loss feasible.
-
- Side Effects:
- Updates the given mapping of measures and values based on the current
- experimental metrics stored in new_measures, and determines current
- feasibility of the experiment based on the provided loss value.
- """
- max_loss = max_loss if max_loss else np.finfo('f').max
- measures['is_infeasible'] = (
- loss_val >= max_loss or not np.isfinite(loss_val))
- measures.update(new_measures)
-
-
-def run_training(model, hparams, training_dataset, logdir, batch_size):
- """Trains the given model on random mini-batches of reads.
-
- Args:
- model: ConvolutionalNet instance containing the model graph and operations.
- hparams: tf.contrib.training.Hparams object containing the model's
- hyperparamters; see configuration.py for hyperparameter definitions.
- training_dataset: an `InputDataset` that can feed labelled examples.
- logdir: string; full path of directory to which to save checkpoints.
- batch_size: integer batch size.
-
- Yields:
- Tuple comprising a dictionary of experimental measures and the save path
- for train checkpoints and summaries.
- """
- input_params = dict(batch_size=batch_size)
- features, labels = training_dataset.input_fn(input_params)
- model.build_graph(features, labels, tf.estimator.ModeKeys.TRAIN, batch_size)
-
- is_chief = FLAGS.task == 0
- scaffold = tf.train.Scaffold(
- saver=tf.train.Saver(
- tf.global_variables(),
- max_to_keep=5,
- keep_checkpoint_every_n_hours=1.0),
- init_op=tf.global_variables_initializer(),
- summary_op=model.summary_op)
- with tf.train.MonitoredTrainingSession(
- master=FLAGS.master,
- checkpoint_dir=logdir,
- is_chief=is_chief,
- scaffold=scaffold,
- save_summaries_secs=FLAGS.save_summaries_secs,
- save_checkpoint_secs=FLAGS.save_model_secs,
- max_wait_secs=FLAGS.recovery_wait_secs) as sess:
- global_step = sess.run(model.global_step)
- print('Initialized model at global step ', global_step)
- init_time = time.time()
- measures = {'is_infeasible': False}
-
- if is_chief:
- model_info = seq2label_utils.construct_seq2label_model_info(
- hparams, 'conv', FLAGS.targets, FLAGS.metadata_path, FLAGS.batch_size,
- FLAGS.num_filters, FLAGS.noise_rate)
- write_message(model_info, os.path.join(logdir, 'model_info.pbtxt'))
-
- ops = [
- model.accuracy, model.weighted_accuracy, model.total_loss,
- model.global_step, model.train_op
- ]
-
- while not sess.should_stop() and global_step < hparams.train_steps:
- accuracy, weighted_accuracy, loss, global_step, _ = sess.run(ops)
-
- def gather_measures():
- """Updates the measures dictionary from this batch."""
- new_measures = {'train_loss': loss, 'global_step': global_step}
- for target in FLAGS.targets:
- new_measures.update({
- ('train_accuracy/%s' % target): accuracy[target],
- ('train_weighted_accuracy/%s' % target): weighted_accuracy[target]
- })
- update_measures(
- measures, new_measures, loss, max_loss=FLAGS.max_task_loss)
-
- # Periodically track measures according to current mini-batch performance.
-
- # Log a message.
- if global_step % FLAGS.n_print_progress_every == 0:
- log_message = ('\tstep: %d (%d sec), loss: %f' %
- (global_step, time.time() - init_time, loss))
- for target in FLAGS.targets:
- log_message += (', accuracy/%s: %f ' % (target, accuracy[target]))
- log_message += (', weighted_accuracy/%s: %f ' %
- (target, weighted_accuracy[target]))
- print(log_message)
-
- # Gather new measures and update the measures dictionary.
- gather_measures()
- yield measures, scaffold.saver.last_checkpoints[-1]
-
- # Check for additional stopping criteria.
- if not np.isfinite(loss) or (loss >= FLAGS.max_task_loss and
- global_step > FLAGS.min_train_steps):
- break
-
- # Always yield once at the end.
- gather_measures()
- yield measures, scaffold.saver.last_checkpoints[-1]
-
-
-def write_message(message, filename):
- """Writes contents of the given message to the given filename as a text proto.
-
- Args:
- message: the proto message to save.
- filename: full path of file to which to save the text proto.
-
- Side Effects:
- Outputs a text proto file to the given filename.
- """
- message_string = text_format.MessageToString(message)
- with tf.gfile.GFile(filename, 'w') as f:
- f.write(message_string)
-
-
-def write_measures(measures, checkpoint_file, init_time):
- """Writes performance measures to file.
-
- Args:
- measures: dict; mapping from measure name to measure value.
- checkpoint_file: string; full save path for checkpoints and summaries.
- init_time: int; start time for work on the current experiment.
-
- Side Effects:
- Writes given dictionary of performance measures for the current experiment
- to a 'measures.pbtxt' file in the checkpoint directory.
- """
- # Save experiment measures.
- print('global_step: ', measures['global_step'])
- experiment_measures = seq2label_pb2.Seq2LabelExperimentMeasures(
- checkpoint_path=checkpoint_file,
- steps=measures['global_step'],
- experiment_infeasible=measures['is_infeasible'],
- wall_time=time.time() - init_time) # Inaccurate for restarts.
- for name, value in measures.iteritems():
- if name not in ['is_infeasible', 'global_step']:
- experiment_measures.measures.add(name=name, value=value)
- measures_file = os.path.join(
- os.path.dirname(checkpoint_file), 'measures.pbtxt')
- write_message(experiment_measures, measures_file)
- print('Wrote ', measures_file,
- ' containing the following experiment measures:\n', experiment_measures)
-
-
-def main(unused_argv):
- dataset_info = seq2species_input.load_dataset_info(FLAGS.metadata_path)
-
- init_time = time.time()
-
- # Determine model hyperparameters.
- hparams = configuration.parse_hparams(FLAGS.hparams, FLAGS.num_filters)
- print('Current Hyperparameters:')
- for hp_name, hp_val in hparams.values().items():
- print('\t', hp_name, ': ', hp_val)
-
- # Initialize the model graph.
- print('Constructing TensorFlow Graph.')
- tf.reset_default_graph()
-
- input_dataset = seq2species_input.InputDataset.from_tfrecord_files(
- FLAGS.train_files,
- 'train',
- FLAGS.targets,
- dataset_info,
- noise_rate=FLAGS.noise_rate,
- random_seed=RANDOM_SEED)
-
- with tf.device(tf.train.replica_device_setter(FLAGS.ps_tasks)):
- model = build_model.ConvolutionalNet(
- hparams, dataset_info, targets=FLAGS.targets)
-
- # Run the experiment.
- measures, checkpoint_file = None, None
- print('Starting model training.')
- for cur_measures, cur_file in run_training(
- model, hparams, input_dataset, FLAGS.logdir, batch_size=FLAGS.batch_size):
- measures, checkpoint_file = cur_measures, cur_file
-
- # Save experiment results.
- write_measures(measures, checkpoint_file, init_time)
-
-
-if __name__ == '__main__':
- tf.app.run(main)
diff --git a/research/seq2species/run_training_test.py b/research/seq2species/run_training_test.py
deleted file mode 100644
index 754d2e0174e730f57309a52ab2b80d1e84e7ab15..0000000000000000000000000000000000000000
--- a/research/seq2species/run_training_test.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Tests for run_training."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import time
-
-from absl import flags
-from absl.testing import absltest
-from absl.testing import flagsaver
-from absl.testing import parameterized
-import numpy as np
-import tensorflow as tf
-from google.protobuf import text_format
-
-import run_training
-from protos import seq2label_pb2
-import test_utils
-
-FLAGS = flags.FLAGS
-
-
-class RunTrainingTest(parameterized.TestCase):
-
- @parameterized.parameters(2, 4, 7)
- def test_wait_until(self, wait_sec):
- end_time = time.time() + wait_sec
- run_training.wait_until(end_time)
- self.assertEqual(round(time.time() - end_time), 0)
-
- @parameterized.parameters(
- ({}, {'a': 0.7, 'b': 12.3}, 12.3, None,
- {'a': 0.7, 'b': 12.3, 'is_infeasible': False}),
- ({'a': 0.42}, {'b': 24.5}, 24.5, 32.0,
- {'a': 0.42, 'b': 24.5, 'is_infeasible': False}),
- ({'a': 0.503}, {'a': 0.82, 'b': 7.2}, 7.2, 0.1,
- {'a': 0.82, 'b': 7.2, 'is_infeasible': True}),
- ({}, {'a': 0.7, 'b': 12.3}, float('Inf'), None,
- {'a': 0.7, 'b': 12.3, 'is_infeasible': True})
- )
- def test_update_measures(self, measures, new_measures, loss, max_loss,
- expected):
- run_training.update_measures(measures, new_measures, loss, max_loss)
- self.assertEqual(measures, expected)
-
- def test_write_measures(self):
- init_time = time.time()
- measures = {
- 'global_step': 311448,
- 'train_loss': np.float32(18.36),
- 'train_weighted_accuracy': np.float32(0.3295),
- 'train_accuracy': 0.8243,
- 'is_infeasible': False
- }
- tmp_path = os.path.join(FLAGS.test_tmpdir, 'measures.pbtxt')
- run_training.write_measures(measures, tmp_path, init_time)
- experiment_measures = seq2label_pb2.Seq2LabelExperimentMeasures()
- with tf.gfile.Open(tmp_path) as f:
- text_format.Parse(f.read(), experiment_measures)
- self.assertEqual(experiment_measures.checkpoint_path, tmp_path)
- self.assertFalse(experiment_measures.experiment_infeasible)
- self.assertEqual(experiment_measures.steps, measures['global_step'])
- self.assertGreater(experiment_measures.wall_time, 0)
- self.assertEqual(len(experiment_measures.measures), 3)
- for measure in experiment_measures.measures:
- self.assertAlmostEqual(measure.value, measures[measure.name])
-
- @parameterized.parameters((test_utils.TEST_TARGETS[:1],),
- (test_utils.TEST_TARGETS,))
- def test_run_training(self, targets):
- """Tests whether the training loop can be run successfully.
-
- Generates test input files and runs the main driving code.
-
- Args:
- targets: the targets to train on.
- """
- # Create test input and metadata files.
- num_examples, read_len = 20, 5
- train_file = test_utils.create_tmp_train_file(num_examples, read_len)
- metadata_path = test_utils.create_tmp_metadata(num_examples, read_len)
-
- # Check that the training loop runs as expected.
- logdir = os.path.join(FLAGS.test_tmpdir, 'train:{}'.format(len(targets)))
- with flagsaver.flagsaver(
- train_files=train_file,
- metadata_path=metadata_path,
- targets=targets,
- logdir=logdir,
- hparams='train_steps=10,min_read_length=5',
- batch_size=10):
- run_training.main(FLAGS)
- # Check training loop ran by confirming existence of a checkpoint file.
- self.assertIsNotNone(tf.train.latest_checkpoint(FLAGS.logdir))
- # Check training loop ran by confiming existence of a measures file.
- self.assertTrue(
- os.path.exists(os.path.join(FLAGS.logdir, 'measures.pbtxt')))
-
-
-if __name__ == '__main__':
- absltest.main()
diff --git a/research/seq2species/seq2label_utils.py b/research/seq2species/seq2label_utils.py
deleted file mode 100644
index b975b7f17d0dfd4798ed798509e7b3d3447cfd6b..0000000000000000000000000000000000000000
--- a/research/seq2species/seq2label_utils.py
+++ /dev/null
@@ -1,95 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Utilities for working with Seq2Label datasets and models.
-
-This library provides utilities for parsing and generating Seq2Label protos.
-"""
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-
-from protos import seq2label_pb2
-
-
-def get_all_label_values(dataset_info):
- """Retrieves possible values for modeled labels from a `Seq2LabelDatasetInfo`.
-
- Args:
- dataset_info: a `Seq2LabelDatasetInfo` message.
-
- Returns:
- A dictionary mapping each label name to a tuple of its permissible values.
- """
- return {
- label_info.name: tuple(label_info.values)
- for label_info in dataset_info.labels
- }
-
-
-def construct_seq2label_model_info(hparams, model_type, targets, metadata_path,
- batch_size, num_filters,
- training_noise_rate):
- """Constructs a Seq2LabelModelInfo proto with the given properties.
-
- Args:
- hparams: initialized tf.contrib.training.Hparams object.
- model_type: string; descriptive tag indicating type of model, ie. "conv".
- targets: list of names of the targets the model is trained to predict.
- metadata_path: string; full path to Seq2LabelDatasetInfo text proto used
- to initialize the model.
- batch_size: int; number of reads per mini-batch.
- num_filters: int; number of filters for convolutional model.
- training_noise_rate: float; rate [0.0, 1.0] of base-flipping noise injected
- into input read sequenced at training time.
-
- Returns:
- The Seq2LabelModelInfo proto with the hparams, model_type, targets,
- num_filters, batch_size, metadata_path, and training_noise_rate fields
- set to the given values.
- """
- return seq2label_pb2.Seq2LabelModelInfo(
- hparams_string=hparams.to_json(),
- model_type=model_type,
- targets=sorted(targets),
- num_filters=num_filters,
- batch_size=batch_size,
- metadata_path=metadata_path,
- training_noise_rate=training_noise_rate)
-
-
-def add_read_noise(read, base_flip_probability=0.01):
- """Adds base-flipping noise to the given read sequence.
-
- Args:
- read: string; the read sequence to which to add noise.
- base_flip_probability: float; probability of a base flip at each position.
-
- Returns:
- The given read with base-flipping noise added at the provided
- base_flip_probability rate.
- """
- base_flips = np.random.binomial(1, base_flip_probability, len(read))
- if sum(base_flips) == 0:
- return read
-
- read = np.array(list(read))
- possible_mutations = np.char.replace(['ACTG'] * sum(base_flips),
- read[base_flips == 1], '')
- mutations = map(np.random.choice, map(list, possible_mutations))
- read[base_flips == 1] = mutations
- return ''.join(read)
diff --git a/research/seq2species/test_utils.py b/research/seq2species/test_utils.py
deleted file mode 100644
index f02798fb533c99c8545e3a51f56de31b629ca2f4..0000000000000000000000000000000000000000
--- a/research/seq2species/test_utils.py
+++ /dev/null
@@ -1,106 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Utility methods for accessing and operating on test data."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-from absl import flags
-import tensorflow as tf
-from google.protobuf import text_format
-
-import input as seq2species_input
-from protos import seq2label_pb2
-
-FLAGS = flags.FLAGS
-
-# Target names included in the example inputs.
-TEST_TARGETS = ['test_target_1', 'test_target_2']
-
-
-def _as_bytes_feature(in_string):
- """Converts the given string to a tf.train.BytesList feature.
-
- Args:
- in_string: string to be converted to BytesList Feature.
-
- Returns:
- The TF BytesList Feature representing the given string.
- """
- return tf.train.Feature(bytes_list=tf.train.BytesList(value=[in_string]))
-
-
-def create_tmp_train_file(num_examples,
- read_len,
- characters=seq2species_input.DNA_BASES,
- name='test.tfrecord'):
- """Write a test TFRecord of input examples to temporary test directory.
-
- The generated input examples are test tf.train.Example protos, each comprised
- of a toy sequence of length read_len and non-meaningful labels for targets in
- TEST_TARGETS.
-
- Args:
- num_examples: int; number of examples to write to test input file.
- read_len: int; length of test read sequences.
- characters: string; set of characters from which to construct test reads.
- Defaults to canonical DNA bases.
- name: string; filename for the test input file.
-
- Returns:
- Full path to the generated temporary test input file.
- """
- tmp_path = os.path.join(FLAGS.test_tmpdir, name)
- with tf.python_io.TFRecordWriter(tmp_path) as writer:
- for i in xrange(num_examples):
- char = characters[i % len(characters)]
- features_dict = {'sequence': _as_bytes_feature(char * read_len)}
- for target_name in TEST_TARGETS:
- nonsense_label = _as_bytes_feature(str(i))
- features_dict[target_name] = nonsense_label
- tf_features = tf.train.Features(feature=features_dict)
- example = tf.train.Example(features=tf_features)
- writer.write(example.SerializeToString())
- return tmp_path
-
-
-def create_tmp_metadata(num_examples, read_len):
- """Write a test Seq2LabelDatasetInfo test proto to temporary test directory.
-
- Args:
- num_examples: int; number of example labels to write into test metadata.
- read_len: int; length of test read sequences.
-
- Returns:
- Full path to the generated temporary test file containing the
- Seq2LabelDatasetInfo text proto.
- """
- dataset_info = seq2label_pb2.Seq2LabelDatasetInfo(
- read_length=read_len,
- num_examples=num_examples,
- read_stride=1,
- dataset_path='test.tfrecord')
-
- for target in TEST_TARGETS:
- dataset_info.labels.add(
- name=target, values=[str(i) for i in xrange(num_examples)])
-
- tmp_path = os.path.join(FLAGS.test_tmpdir, 'test.pbtxt')
- with tf.gfile.GFile(tmp_path, 'w') as f:
- f.write(text_format.MessageToString(dataset_info))
- return tmp_path
diff --git a/research/skip_thoughts/.gitignore b/research/skip_thoughts/.gitignore
deleted file mode 100644
index 91cb861a9c87147ac86eda5434e4af270ea7b1dc..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-/bazel-bin
-/bazel-ci_build-cache
-/bazel-genfiles
-/bazel-out
-/bazel-skip_thoughts
-/bazel-testlogs
-/bazel-tf
-*.pyc
diff --git a/research/skip_thoughts/README.md b/research/skip_thoughts/README.md
deleted file mode 100644
index b3a1de73fabfc055ad7a0741d9466b5409168dce..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/README.md
+++ /dev/null
@@ -1,479 +0,0 @@
-
-
-
-
-# Skip-Thought Vectors
-
-This is a TensorFlow implementation of the model described in:
-
-Jamie Ryan Kiros, Yukun Zhu, Ruslan Salakhutdinov, Richard S. Zemel,
-Antonio Torralba, Raquel Urtasun, Sanja Fidler.
-[Skip-Thought Vectors](https://papers.nips.cc/paper/5950-skip-thought-vectors.pdf).
-*In NIPS, 2015.*
-
-
-## Contact
-***Code author:*** Chris Shallue
-
-***Pull requests and issues:*** @cshallue
-
-## Contents
-* [Model Overview](#model-overview)
-* [Getting Started](#getting-started)
- * [Install Required Packages](#install-required-packages)
- * [Download Pretrained Models (Optional)](#download-pretrained-models-optional)
-* [Training a Model](#training-a-model)
- * [Prepare the Training Data](#prepare-the-training-data)
- * [Run the Training Script](#run-the-training-script)
- * [Track Training Progress](#track-training-progress)
-* [Expanding the Vocabulary](#expanding-the-vocabulary)
- * [Overview](#overview)
- * [Preparation](#preparation)
- * [Run the Vocabulary Expansion Script](#run-the-vocabulary-expansion-script)
-* [Evaluating a Model](#evaluating-a-model)
- * [Overview](#overview-1)
- * [Preparation](#preparation-1)
- * [Run the Evaluation Tasks](#run-the-evaluation-tasks)
-* [Encoding Sentences](#encoding-sentences)
-
-## Model overview
-
-The *Skip-Thoughts* model is a sentence encoder. It learns to encode input
-sentences into a fixed-dimensional vector representation that is useful for many
-tasks, for example to detect paraphrases or to classify whether a product review
-is positive or negative. See the
-[Skip-Thought Vectors](https://papers.nips.cc/paper/5950-skip-thought-vectors.pdf)
-paper for details of the model architecture and more example applications.
-
-A trained *Skip-Thoughts* model will encode similar sentences nearby each other
-in the embedding vector space. The following examples show the nearest neighbor by
-cosine similarity of some sentences from the
-[movie review dataset](https://www.cs.cornell.edu/people/pabo/movie-review-data/).
-
-
-| Input sentence | Nearest Neighbor |
-|----------------|------------------|
-| Simplistic, silly and tedious. | Trite, banal, cliched, mostly inoffensive. |
-| Not so much farcical as sour. | Not only unfunny, but downright repellent. |
-| A sensitive and astute first feature by Anne-Sophie Birot. | Absorbing character study by André Turpin . |
-| An enthralling, entertaining feature. | A slick, engrossing melodrama. |
-
-## Getting Started
-
-### Install Required Packages
-First ensure that you have installed the following required packages:
-
-* **Bazel** ([instructions](http://bazel.build/docs/install.html))
-* **TensorFlow** ([instructions](https://www.tensorflow.org/install/))
-* **NumPy** ([instructions](http://www.scipy.org/install.html))
-* **scikit-learn** ([instructions](http://scikit-learn.org/stable/install.html))
-* **Natural Language Toolkit (NLTK)**
- * First install NLTK ([instructions](http://www.nltk.org/install.html))
- * Then install the NLTK data ([instructions](http://www.nltk.org/data.html))
-* **gensim** ([instructions](https://radimrehurek.com/gensim/install.html))
- * Only required if you will be expanding your vocabulary with the [word2vec](https://code.google.com/archive/p/word2vec/) model.
-
-
-### Download Pretrained Models (Optional)
-
-You can download model checkpoints pretrained on the
-[BookCorpus](http://yknzhu.wixsite.com/mbweb) dataset in the following
-configurations:
-
-* Unidirectional RNN encoder ("uni-skip" in the paper)
-* Bidirectional RNN encoder ("bi-skip" in the paper)
-
-```shell
-# Directory to download the pretrained models to.
-PRETRAINED_MODELS_DIR="${HOME}/skip_thoughts/pretrained/"
-
-mkdir -p ${PRETRAINED_MODELS_DIR}
-cd ${PRETRAINED_MODELS_DIR}
-
-# Download and extract the unidirectional model.
-wget "http://download.tensorflow.org/models/skip_thoughts_uni_2017_02_02.tar.gz"
-tar -xvf skip_thoughts_uni_2017_02_02.tar.gz
-rm skip_thoughts_uni_2017_02_02.tar.gz
-
-# Download and extract the bidirectional model.
-wget "http://download.tensorflow.org/models/skip_thoughts_bi_2017_02_16.tar.gz"
-tar -xvf skip_thoughts_bi_2017_02_16.tar.gz
-rm skip_thoughts_bi_2017_02_16.tar.gz
-```
-
-You can now skip to the sections [Evaluating a Model](#evaluating-a-model) and
-[Encoding Sentences](#encoding-sentences).
-
-
-## Training a Model
-
-### Prepare the Training Data
-
-To train a model you will need to provide training data in TFRecord format. The
-TFRecord format consists of a set of sharded files containing serialized
-`tf.Example` protocol buffers. Each `tf.Example` proto contains three
-sentences:
-
- * `encode`: The sentence to encode.
- * `decode_pre`: The sentence preceding `encode` in the original text.
- * `decode_post`: The sentence following `encode` in the original text.
-
-Each sentence is a list of words. During preprocessing, a dictionary is created
-that assigns each word in the vocabulary to an integer-valued id. Each sentence
-is encoded as a list of integer word ids in the `tf.Example` protos.
-
-We have provided a script to preprocess any set of text-files into this format.
-You may wish to use the [BookCorpus](http://yknzhu.wixsite.com/mbweb) dataset.
-Note that the preprocessing script may take **12 hours** or more to complete
-on this large dataset.
-
-```shell
-# Comma-separated list of globs matching the input input files. The format of
-# the input files is assumed to be a list of newline-separated sentences, where
-# each sentence is already tokenized.
-INPUT_FILES="${HOME}/skip_thoughts/bookcorpus/*.txt"
-
-# Location to save the preprocessed training and validation data.
-DATA_DIR="${HOME}/skip_thoughts/data"
-
-# Build the preprocessing script.
-cd tensorflow-models/skip_thoughts
-bazel build -c opt //skip_thoughts/data:preprocess_dataset
-
-# Run the preprocessing script.
-bazel-bin/skip_thoughts/data/preprocess_dataset \
- --input_files=${INPUT_FILES} \
- --output_dir=${DATA_DIR}
-```
-
-When the script finishes you will find 100 training files and 1 validation file
-in `DATA_DIR`. The files will match the patterns `train-?????-of-00100` and
-`validation-00000-of-00001` respectively.
-
-The script will also produce a file named `vocab.txt`. The format of this file
-is a list of newline-separated words where the word id is the corresponding 0-
-based line index. Words are sorted by descending order of frequency in the input
-data. Only the top 20,000 words are assigned unique ids; all other words are
-assigned the "unknown id" of 1 in the processed data.
-
-### Run the Training Script
-
-Execute the following commands to start the training script. By default it will
-run for 500k steps (around 9 days on a GeForce GTX 1080 GPU).
-
-```shell
-# Directory containing the preprocessed data.
-DATA_DIR="${HOME}/skip_thoughts/data"
-
-# Directory to save the model.
-MODEL_DIR="${HOME}/skip_thoughts/model"
-
-# Build the model.
-cd tensorflow-models/skip_thoughts
-bazel build -c opt //skip_thoughts/...
-
-# Run the training script.
-bazel-bin/skip_thoughts/train \
- --input_file_pattern="${DATA_DIR}/train-?????-of-00100" \
- --train_dir="${MODEL_DIR}/train"
-```
-
-### Track Training Progress
-
-Optionally, you can run the `track_perplexity` script in a separate process.
-This will log per-word perplexity on the validation set which allows training
-progress to be monitored on
-[TensorBoard](https://www.tensorflow.org/get_started/summaries_and_tensorboard).
-
-Note that you may run out of memory if you run the this script on the same GPU
-as the training script. You can set the environment variable
-`CUDA_VISIBLE_DEVICES=""` to force the script to run on CPU. If it runs too
-slowly on CPU, you can decrease the value of `--num_eval_examples`.
-
-```shell
-DATA_DIR="${HOME}/skip_thoughts/data"
-MODEL_DIR="${HOME}/skip_thoughts/model"
-
-# Ignore GPU devices (only necessary if your GPU is currently memory
-# constrained, for example, by running the training script).
-export CUDA_VISIBLE_DEVICES=""
-
-# Run the evaluation script. This will run in a loop, periodically loading the
-# latest model checkpoint file and computing evaluation metrics.
-bazel-bin/skip_thoughts/track_perplexity \
- --input_file_pattern="${DATA_DIR}/validation-?????-of-00001" \
- --checkpoint_dir="${MODEL_DIR}/train" \
- --eval_dir="${MODEL_DIR}/val" \
- --num_eval_examples=50000
-```
-
-If you started the `track_perplexity` script, run a
-[TensorBoard](https://www.tensorflow.org/get_started/summaries_and_tensorboard)
-server in a separate process for real-time monitoring of training summaries and
-validation perplexity.
-
-```shell
-MODEL_DIR="${HOME}/skip_thoughts/model"
-
-# Run a TensorBoard server.
-tensorboard --logdir="${MODEL_DIR}"
-```
-
-## Expanding the Vocabulary
-
-### Overview
-
-The vocabulary generated by the preprocessing script contains only 20,000 words
-which is insufficient for many tasks. For example, a sentence from Wikipedia
-might contain nouns that do not appear in this vocabulary.
-
-A solution to this problem described in the
-[Skip-Thought Vectors](https://papers.nips.cc/paper/5950-skip-thought-vectors.pdf)
-paper is to learn a mapping that transfers word representations from one model to
-another. This idea is based on the "Translation Matrix" method from the paper
-[Exploiting Similarities Among Languages for Machine Translation](https://arxiv.org/abs/1309.4168).
-
-
-Specifically, we will load the word embeddings from a trained *Skip-Thoughts*
-model and from a trained [word2vec model](https://arxiv.org/pdf/1301.3781.pdf)
-(which has a much larger vocabulary). We will train a linear regression model
-without regularization to learn a linear mapping from the word2vec embedding
-space to the *Skip-Thoughts* embedding space. We will then apply the linear
-model to all words in the word2vec vocabulary, yielding vectors in the *Skip-
-Thoughts* word embedding space for the union of the two vocabularies.
-
-The linear regression task is to learn a parameter matrix *W* to minimize
-*|| X - Y \* W ||2*, where *X* is a matrix of *Skip-Thoughts*
-embeddings of shape `[num_words, dim1]`, *Y* is a matrix of word2vec embeddings
-of shape `[num_words, dim2]`, and *W* is a matrix of shape `[dim2, dim1]`.
-
-### Preparation
-
-First you will need to download and unpack a pretrained
-[word2vec model](https://arxiv.org/pdf/1301.3781.pdf) from
-[this website](https://code.google.com/archive/p/word2vec/)
-([direct download link](https://drive.google.com/file/d/0B7XkCwpI5KDYNlNUTTlSS21pQmM/edit?usp=sharing)).
-This model was trained on the Google News dataset (about 100 billion words).
-
-
-Also ensure that you have already [installed gensim](https://radimrehurek.com/gensim/install.html).
-
-### Run the Vocabulary Expansion Script
-
-```shell
-# Path to checkpoint file or a directory containing checkpoint files (the script
-# will select the most recent).
-CHECKPOINT_PATH="${HOME}/skip_thoughts/model/train"
-
-# Vocabulary file generated by the preprocessing script.
-SKIP_THOUGHTS_VOCAB="${HOME}/skip_thoughts/data/vocab.txt"
-
-# Path to downloaded word2vec model.
-WORD2VEC_MODEL="${HOME}/skip_thoughts/googlenews/GoogleNews-vectors-negative300.bin"
-
-# Output directory.
-EXP_VOCAB_DIR="${HOME}/skip_thoughts/exp_vocab"
-
-# Build the vocabulary expansion script.
-cd tensorflow-models/skip_thoughts
-bazel build -c opt //skip_thoughts:vocabulary_expansion
-
-# Run the vocabulary expansion script.
-bazel-bin/skip_thoughts/vocabulary_expansion \
- --skip_thoughts_model=${CHECKPOINT_PATH} \
- --skip_thoughts_vocab=${SKIP_THOUGHTS_VOCAB} \
- --word2vec_model=${WORD2VEC_MODEL} \
- --output_dir=${EXP_VOCAB_DIR}
-```
-
-## Evaluating a Model
-
-### Overview
-
-The model can be evaluated using the benchmark tasks described in the
-[Skip-Thought Vectors](https://papers.nips.cc/paper/5950-skip-thought-vectors.pdf)
-paper. The following tasks are supported (refer to the paper for full details):
-
- * **SICK** semantic relatedness task.
- * **MSRP** (Microsoft Research Paraphrase Corpus) paraphrase detection task.
- * Binary classification tasks:
- * **MR** movie review sentiment task.
- * **CR** customer product review task.
- * **SUBJ** subjectivity/objectivity task.
- * **MPQA** opinion polarity task.
- * **TREC** question-type classification task.
-
-### Preparation
-
-You will need to clone or download the
-[skip-thoughts GitHub repository](https://github.com/ryankiros/skip-thoughts) by
-[ryankiros](https://github.com/ryankiros) (the first author of the Skip-Thoughts
-paper):
-
-```shell
-# Folder to clone the repository to.
-ST_KIROS_DIR="${HOME}/skip_thoughts/skipthoughts_kiros"
-
-# Clone the repository.
-git clone git@github.com:ryankiros/skip-thoughts.git "${ST_KIROS_DIR}/skipthoughts"
-
-# Make the package importable.
-export PYTHONPATH="${ST_KIROS_DIR}/:${PYTHONPATH}"
-```
-
-You will also need to download the data needed for each evaluation task. See the
-instructions [here](https://github.com/ryankiros/skip-thoughts).
-
-For example, the CR (customer review) dataset is found [here](http://nlp.stanford.edu/~sidaw/home/projects:nbsvm). For this task we want the
-files `custrev.pos` and `custrev.neg`.
-
-### Run the Evaluation Tasks
-
-In the following example we will evaluate a unidirectional model ("uni-skip" in
-the paper) on the CR task. To use a bidirectional model ("bi-skip" in the
-paper), simply pass the flags `--bi_vocab_file`, `--bi_embeddings_file` and
-`--bi_checkpoint_path` instead. To use the "combine-skip" model described in the
-paper you will need to pass both the unidirectional and bidirectional flags.
-
-```shell
-# Path to checkpoint file or a directory containing checkpoint files (the script
-# will select the most recent).
-CHECKPOINT_PATH="${HOME}/skip_thoughts/model/train"
-
-# Vocabulary file generated by the vocabulary expansion script.
-VOCAB_FILE="${HOME}/skip_thoughts/exp_vocab/vocab.txt"
-
-# Embeddings file generated by the vocabulary expansion script.
-EMBEDDINGS_FILE="${HOME}/skip_thoughts/exp_vocab/embeddings.npy"
-
-# Directory containing files custrev.pos and custrev.neg.
-EVAL_DATA_DIR="${HOME}/skip_thoughts/eval_data"
-
-# Build the evaluation script.
-cd tensorflow-models/skip_thoughts
-bazel build -c opt //skip_thoughts:evaluate
-
-# Run the evaluation script.
-bazel-bin/skip_thoughts/evaluate \
- --eval_task=CR \
- --data_dir=${EVAL_DATA_DIR} \
- --uni_vocab_file=${VOCAB_FILE} \
- --uni_embeddings_file=${EMBEDDINGS_FILE} \
- --uni_checkpoint_path=${CHECKPOINT_PATH}
-```
-
-Output:
-
-```python
-[0.82539682539682535, 0.84084880636604775, 0.83023872679045096,
- 0.86206896551724133, 0.83554376657824936, 0.85676392572944293,
- 0.84084880636604775, 0.83023872679045096, 0.85145888594164454,
- 0.82758620689655171]
-```
-
-The output is a list of accuracies of 10 cross-validation classification models.
-To get a single number, simply take the average:
-
-```python
-ipython # Launch iPython.
-
-In [0]:
-import numpy as np
-np.mean([0.82539682539682535, 0.84084880636604775, 0.83023872679045096,
- 0.86206896551724133, 0.83554376657824936, 0.85676392572944293,
- 0.84084880636604775, 0.83023872679045096, 0.85145888594164454,
- 0.82758620689655171])
-
-Out [0]: 0.84009936423729525
-```
-
-## Encoding Sentences
-
-In this example we will encode data from the
-[movie review dataset](https://www.cs.cornell.edu/people/pabo/movie-review-data/)
-(specifically the [sentence polarity dataset v1.0](https://www.cs.cornell.edu/people/pabo/movie-review-data/rt-polaritydata.tar.gz)).
-
-```python
-ipython # Launch iPython.
-
-In [0]:
-
-# Imports.
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-import numpy as np
-import os.path
-import scipy.spatial.distance as sd
-from skip_thoughts import configuration
-from skip_thoughts import encoder_manager
-
-In [1]:
-# Set paths to the model.
-VOCAB_FILE = "/path/to/vocab.txt"
-EMBEDDING_MATRIX_FILE = "/path/to/embeddings.npy"
-CHECKPOINT_PATH = "/path/to/model.ckpt-9999"
-# The following directory should contain files rt-polarity.neg and
-# rt-polarity.pos.
-MR_DATA_DIR = "/dir/containing/mr/data"
-
-In [2]:
-# Set up the encoder. Here we are using a single unidirectional model.
-# To use a bidirectional model as well, call load_model() again with
-# configuration.model_config(bidirectional_encoder=True) and paths to the
-# bidirectional model's files. The encoder will use the concatenation of
-# all loaded models.
-encoder = encoder_manager.EncoderManager()
-encoder.load_model(configuration.model_config(),
- vocabulary_file=VOCAB_FILE,
- embedding_matrix_file=EMBEDDING_MATRIX_FILE,
- checkpoint_path=CHECKPOINT_PATH)
-
-In [3]:
-# Load the movie review dataset.
-data = []
-with open(os.path.join(MR_DATA_DIR, 'rt-polarity.neg'), 'rb') as f:
- data.extend([line.decode('latin-1').strip() for line in f])
-with open(os.path.join(MR_DATA_DIR, 'rt-polarity.pos'), 'rb') as f:
- data.extend([line.decode('latin-1').strip() for line in f])
-
-In [4]:
-# Generate Skip-Thought Vectors for each sentence in the dataset.
-encodings = encoder.encode(data)
-
-In [5]:
-# Define a helper function to generate nearest neighbors.
-def get_nn(ind, num=10):
- encoding = encodings[ind]
- scores = sd.cdist([encoding], encodings, "cosine")[0]
- sorted_ids = np.argsort(scores)
- print("Sentence:")
- print("", data[ind])
- print("\nNearest neighbors:")
- for i in range(1, num + 1):
- print(" %d. %s (%.3f)" %
- (i, data[sorted_ids[i]], scores[sorted_ids[i]]))
-
-In [6]:
-# Compute nearest neighbors of the first sentence in the dataset.
-get_nn(0)
-```
-
-Output:
-
-```
-Sentence:
- simplistic , silly and tedious .
-
-Nearest neighbors:
- 1. trite , banal , cliched , mostly inoffensive . (0.247)
- 2. banal and predictable . (0.253)
- 3. witless , pointless , tasteless and idiotic . (0.272)
- 4. loud , silly , stupid and pointless . (0.295)
- 5. grating and tedious . (0.299)
- 6. idiotic and ugly . (0.330)
- 7. black-and-white and unrealistic . (0.335)
- 8. hopelessly inane , humorless and under-inspired . (0.335)
- 9. shallow , noisy and pretentious . (0.340)
- 10. . . . unlikable , uninteresting , unfunny , and completely , utterly inept . (0.346)
-```
diff --git a/research/skip_thoughts/WORKSPACE b/research/skip_thoughts/WORKSPACE
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/skip_thoughts/skip_thoughts/BUILD b/research/skip_thoughts/skip_thoughts/BUILD
deleted file mode 100644
index 3ab642cace448b46f6ebe6e3d8a93b9f260bb08f..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/skip_thoughts/BUILD
+++ /dev/null
@@ -1,87 +0,0 @@
-package(default_visibility = ["//visibility:public"])
-
-licenses(["notice"]) # Apache 2.0
-
-exports_files(["LICENSE"])
-
-py_library(
- name = "configuration",
- srcs = ["configuration.py"],
- srcs_version = "PY2AND3",
-)
-
-py_library(
- name = "skip_thoughts_model",
- srcs = ["skip_thoughts_model.py"],
- srcs_version = "PY2AND3",
- deps = [
- "//skip_thoughts/ops:gru_cell",
- "//skip_thoughts/ops:input_ops",
- ],
-)
-
-py_test(
- name = "skip_thoughts_model_test",
- size = "large",
- srcs = ["skip_thoughts_model_test.py"],
- deps = [
- ":configuration",
- ":skip_thoughts_model",
- ],
-)
-
-py_binary(
- name = "train",
- srcs = ["train.py"],
- srcs_version = "PY2AND3",
- deps = [
- ":configuration",
- ":skip_thoughts_model",
- ],
-)
-
-py_binary(
- name = "track_perplexity",
- srcs = ["track_perplexity.py"],
- srcs_version = "PY2AND3",
- deps = [
- ":configuration",
- ":skip_thoughts_model",
- ],
-)
-
-py_binary(
- name = "vocabulary_expansion",
- srcs = ["vocabulary_expansion.py"],
- srcs_version = "PY2AND3",
-)
-
-py_library(
- name = "skip_thoughts_encoder",
- srcs = ["skip_thoughts_encoder.py"],
- srcs_version = "PY2AND3",
- deps = [
- ":skip_thoughts_model",
- "//skip_thoughts/data:special_words",
- ],
-)
-
-py_library(
- name = "encoder_manager",
- srcs = ["encoder_manager.py"],
- srcs_version = "PY2AND3",
- deps = [
- ":skip_thoughts_encoder",
- ],
-)
-
-py_binary(
- name = "evaluate",
- srcs = ["evaluate.py"],
- srcs_version = "PY2AND3",
- deps = [
- ":encoder_manager",
- "//skip_thoughts:configuration",
- ],
-)
-
diff --git a/research/skip_thoughts/skip_thoughts/__init__.py b/research/skip_thoughts/skip_thoughts/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/skip_thoughts/skip_thoughts/configuration.py b/research/skip_thoughts/skip_thoughts/configuration.py
deleted file mode 100644
index bc04d57983584a7026df890d472ff326891e1136..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/skip_thoughts/configuration.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Default configuration for model architecture and training."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-class _HParams(object):
- """Wrapper for configuration parameters."""
- pass
-
-
-def model_config(input_file_pattern=None,
- input_queue_capacity=640000,
- num_input_reader_threads=1,
- shuffle_input_data=True,
- uniform_init_scale=0.1,
- vocab_size=20000,
- batch_size=128,
- word_embedding_dim=620,
- bidirectional_encoder=False,
- encoder_dim=2400):
- """Creates a model configuration object.
-
- Args:
- input_file_pattern: File pattern of sharded TFRecord files containing
- tf.Example protobufs.
- input_queue_capacity: Number of examples to keep in the input queue.
- num_input_reader_threads: Number of threads for prefetching input
- tf.Examples.
- shuffle_input_data: Whether to shuffle the input data.
- uniform_init_scale: Scale of random uniform initializer.
- vocab_size: Number of unique words in the vocab.
- batch_size: Batch size (training and evaluation only).
- word_embedding_dim: Word embedding dimension.
- bidirectional_encoder: Whether to use a bidirectional or unidirectional
- encoder RNN.
- encoder_dim: Number of output dimensions of the sentence encoder.
-
- Returns:
- An object containing model configuration parameters.
- """
- config = _HParams()
- config.input_file_pattern = input_file_pattern
- config.input_queue_capacity = input_queue_capacity
- config.num_input_reader_threads = num_input_reader_threads
- config.shuffle_input_data = shuffle_input_data
- config.uniform_init_scale = uniform_init_scale
- config.vocab_size = vocab_size
- config.batch_size = batch_size
- config.word_embedding_dim = word_embedding_dim
- config.bidirectional_encoder = bidirectional_encoder
- config.encoder_dim = encoder_dim
- return config
-
-
-def training_config(learning_rate=0.0008,
- learning_rate_decay_factor=0.5,
- learning_rate_decay_steps=400000,
- number_of_steps=500000,
- clip_gradient_norm=5.0,
- save_model_secs=600,
- save_summaries_secs=600):
- """Creates a training configuration object.
-
- Args:
- learning_rate: Initial learning rate.
- learning_rate_decay_factor: If > 0, the learning rate decay factor.
- learning_rate_decay_steps: The number of steps before the learning rate
- decays by learning_rate_decay_factor.
- number_of_steps: The total number of training steps to run. Passing None
- will cause the training script to run indefinitely.
- clip_gradient_norm: If not None, then clip gradients to this value.
- save_model_secs: How often (in seconds) to save model checkpoints.
- save_summaries_secs: How often (in seconds) to save model summaries.
-
- Returns:
- An object containing training configuration parameters.
-
- Raises:
- ValueError: If learning_rate_decay_factor is set and
- learning_rate_decay_steps is unset.
- """
- if learning_rate_decay_factor and not learning_rate_decay_steps:
- raise ValueError(
- "learning_rate_decay_factor requires learning_rate_decay_steps.")
-
- config = _HParams()
- config.learning_rate = learning_rate
- config.learning_rate_decay_factor = learning_rate_decay_factor
- config.learning_rate_decay_steps = learning_rate_decay_steps
- config.number_of_steps = number_of_steps
- config.clip_gradient_norm = clip_gradient_norm
- config.save_model_secs = save_model_secs
- config.save_summaries_secs = save_summaries_secs
- return config
diff --git a/research/skip_thoughts/skip_thoughts/data/BUILD b/research/skip_thoughts/skip_thoughts/data/BUILD
deleted file mode 100644
index a8b61bfdc88431b699d08df58813c13b3ddd3ff4..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/skip_thoughts/data/BUILD
+++ /dev/null
@@ -1,23 +0,0 @@
-package(default_visibility = ["//visibility:public"])
-
-licenses(["notice"]) # Apache 2.0
-
-exports_files(["LICENSE"])
-
-py_library(
- name = "special_words",
- srcs = ["special_words.py"],
- srcs_version = "PY2AND3",
- deps = [],
-)
-
-py_binary(
- name = "preprocess_dataset",
- srcs = [
- "preprocess_dataset.py",
- ],
- srcs_version = "PY2AND3",
- deps = [
- ":special_words",
- ],
-)
diff --git a/research/skip_thoughts/skip_thoughts/data/__init__.py b/research/skip_thoughts/skip_thoughts/data/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/skip_thoughts/skip_thoughts/data/preprocess_dataset.py b/research/skip_thoughts/skip_thoughts/data/preprocess_dataset.py
deleted file mode 100644
index b6f304f5301808177ae0f8ee59fb466d285b9217..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/skip_thoughts/data/preprocess_dataset.py
+++ /dev/null
@@ -1,301 +0,0 @@
-# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Converts a set of text files to TFRecord format with Example protos.
-
-Each Example proto in the output contains the following fields:
-
- decode_pre: list of int64 ids corresponding to the "previous" sentence.
- encode: list of int64 ids corresponding to the "current" sentence.
- decode_post: list of int64 ids corresponding to the "post" sentence.
-
-In addition, the following files are generated:
-
- vocab.txt: List of " " pairs, where is the integer
- encoding of in the Example protos.
- word_counts.txt: List of " " pairs, where is the number
- of occurrences of in the input files.
-
-The vocabulary of word ids is constructed from the top --num_words by word
-count. All other words get the word id.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-import os
-
-
-import numpy as np
-import tensorflow as tf
-
-from skip_thoughts.data import special_words
-
-FLAGS = tf.flags.FLAGS
-
-tf.flags.DEFINE_string("input_files", None,
- "Comma-separated list of globs matching the input "
- "files. The format of the input files is assumed to be "
- "a list of newline-separated sentences, where each "
- "sentence is already tokenized.")
-
-tf.flags.DEFINE_string("vocab_file", "",
- "(Optional) existing vocab file. Otherwise, a new vocab "
- "file is created and written to the output directory. "
- "The file format is a list of newline-separated words, "
- "where the word id is the corresponding 0-based index "
- "in the file.")
-
-tf.flags.DEFINE_string("output_dir", None, "Output directory.")
-
-tf.flags.DEFINE_integer("train_output_shards", 100,
- "Number of output shards for the training set.")
-
-tf.flags.DEFINE_integer("validation_output_shards", 1,
- "Number of output shards for the validation set.")
-
-tf.flags.DEFINE_integer("num_validation_sentences", 50000,
- "Number of output shards for the validation set.")
-
-tf.flags.DEFINE_integer("num_words", 20000,
- "Number of words to include in the output.")
-
-tf.flags.DEFINE_integer("max_sentences", 0,
- "If > 0, the maximum number of sentences to output.")
-
-tf.flags.DEFINE_integer("max_sentence_length", 30,
- "If > 0, exclude sentences whose encode, decode_pre OR"
- "decode_post sentence exceeds this length.")
-
-tf.flags.DEFINE_boolean("add_eos", True,
- "Whether to add end-of-sentence ids to the output.")
-
-tf.logging.set_verbosity(tf.logging.INFO)
-
-
-def _build_vocabulary(input_files):
- """Loads or builds the model vocabulary.
-
- Args:
- input_files: List of pre-tokenized input .txt files.
-
- Returns:
- vocab: A dictionary of word to id.
- """
- if FLAGS.vocab_file:
- tf.logging.info("Loading existing vocab file.")
- vocab = collections.OrderedDict()
- with tf.gfile.GFile(FLAGS.vocab_file, mode="r") as f:
- for i, line in enumerate(f):
- word = line.decode("utf-8").strip()
- assert word not in vocab, "Attempting to add word twice: %s" % word
- vocab[word] = i
- tf.logging.info("Read vocab of size %d from %s",
- len(vocab), FLAGS.vocab_file)
- return vocab
-
- tf.logging.info("Creating vocabulary.")
- num = 0
- wordcount = collections.Counter()
- for input_file in input_files:
- tf.logging.info("Processing file: %s", input_file)
- for sentence in tf.gfile.FastGFile(input_file):
- wordcount.update(sentence.split())
-
- num += 1
- if num % 1000000 == 0:
- tf.logging.info("Processed %d sentences", num)
-
- tf.logging.info("Processed %d sentences total", num)
-
- words = list(wordcount)
- freqs = list(wordcount.values())
- sorted_indices = np.argsort(freqs)[::-1]
-
- vocab = collections.OrderedDict()
- vocab[special_words.EOS] = special_words.EOS_ID
- vocab[special_words.UNK] = special_words.UNK_ID
- for w_id, w_index in enumerate(sorted_indices[0:FLAGS.num_words - 2]):
- vocab[words[w_index]] = w_id + 2 # 0: EOS, 1: UNK.
-
- tf.logging.info("Created vocab with %d words", len(vocab))
-
- vocab_file = os.path.join(FLAGS.output_dir, "vocab.txt")
- with tf.gfile.FastGFile(vocab_file, "w") as f:
- f.write("\n".join(vocab.keys()))
- tf.logging.info("Wrote vocab file to %s", vocab_file)
-
- word_counts_file = os.path.join(FLAGS.output_dir, "word_counts.txt")
- with tf.gfile.FastGFile(word_counts_file, "w") as f:
- for i in sorted_indices:
- f.write("%s %d\n" % (words[i], freqs[i]))
- tf.logging.info("Wrote word counts file to %s", word_counts_file)
-
- return vocab
-
-
-def _int64_feature(value):
- """Helper for creating an Int64 Feature."""
- return tf.train.Feature(int64_list=tf.train.Int64List(
- value=[int(v) for v in value]))
-
-
-def _sentence_to_ids(sentence, vocab):
- """Helper for converting a sentence (list of words) to a list of ids."""
- ids = [vocab.get(w, special_words.UNK_ID) for w in sentence]
- if FLAGS.add_eos:
- ids.append(special_words.EOS_ID)
- return ids
-
-
-def _create_serialized_example(predecessor, current, successor, vocab):
- """Helper for creating a serialized Example proto."""
- example = tf.train.Example(features=tf.train.Features(feature={
- "decode_pre": _int64_feature(_sentence_to_ids(predecessor, vocab)),
- "encode": _int64_feature(_sentence_to_ids(current, vocab)),
- "decode_post": _int64_feature(_sentence_to_ids(successor, vocab)),
- }))
-
- return example.SerializeToString()
-
-
-def _process_input_file(filename, vocab, stats):
- """Processes the sentences in an input file.
-
- Args:
- filename: Path to a pre-tokenized input .txt file.
- vocab: A dictionary of word to id.
- stats: A Counter object for statistics.
-
- Returns:
- processed: A list of serialized Example protos
- """
- tf.logging.info("Processing input file: %s", filename)
- processed = []
-
- predecessor = None # Predecessor sentence (list of words).
- current = None # Current sentence (list of words).
- successor = None # Successor sentence (list of words).
-
- for successor_str in tf.gfile.FastGFile(filename):
- stats.update(["sentences_seen"])
- successor = successor_str.split()
-
- # The first 2 sentences per file will be skipped.
- if predecessor and current and successor:
- stats.update(["sentences_considered"])
-
- # Note that we are going to insert later, so we only allow
- # sentences with strictly less than max_sentence_length to pass.
- if FLAGS.max_sentence_length and (
- len(predecessor) >= FLAGS.max_sentence_length or len(current) >=
- FLAGS.max_sentence_length or len(successor) >=
- FLAGS.max_sentence_length):
- stats.update(["sentences_too_long"])
- else:
- serialized = _create_serialized_example(predecessor, current, successor,
- vocab)
- processed.append(serialized)
- stats.update(["sentences_output"])
-
- predecessor = current
- current = successor
-
- sentences_seen = stats["sentences_seen"]
- sentences_output = stats["sentences_output"]
- if sentences_seen and sentences_seen % 100000 == 0:
- tf.logging.info("Processed %d sentences (%d output)", sentences_seen,
- sentences_output)
- if FLAGS.max_sentences and sentences_output >= FLAGS.max_sentences:
- break
-
- tf.logging.info("Completed processing file %s", filename)
- return processed
-
-
-def _write_shard(filename, dataset, indices):
- """Writes a TFRecord shard."""
- with tf.python_io.TFRecordWriter(filename) as writer:
- for j in indices:
- writer.write(dataset[j])
-
-
-def _write_dataset(name, dataset, indices, num_shards):
- """Writes a sharded TFRecord dataset.
-
- Args:
- name: Name of the dataset (e.g. "train").
- dataset: List of serialized Example protos.
- indices: List of indices of 'dataset' to be written.
- num_shards: The number of output shards.
- """
- tf.logging.info("Writing dataset %s", name)
- borders = np.int32(np.linspace(0, len(indices), num_shards + 1))
- for i in range(num_shards):
- filename = os.path.join(FLAGS.output_dir, "%s-%.5d-of-%.5d" % (name, i,
- num_shards))
- shard_indices = indices[borders[i]:borders[i + 1]]
- _write_shard(filename, dataset, shard_indices)
- tf.logging.info("Wrote dataset indices [%d, %d) to output shard %s",
- borders[i], borders[i + 1], filename)
- tf.logging.info("Finished writing %d sentences in dataset %s.",
- len(indices), name)
-
-
-def main(unused_argv):
- if not FLAGS.input_files:
- raise ValueError("--input_files is required.")
- if not FLAGS.output_dir:
- raise ValueError("--output_dir is required.")
-
- if not tf.gfile.IsDirectory(FLAGS.output_dir):
- tf.gfile.MakeDirs(FLAGS.output_dir)
-
- input_files = []
- for pattern in FLAGS.input_files.split(","):
- match = tf.gfile.Glob(FLAGS.input_files)
- if not match:
- raise ValueError("Found no files matching %s" % pattern)
- input_files.extend(match)
- tf.logging.info("Found %d input files.", len(input_files))
-
- vocab = _build_vocabulary(input_files)
-
- tf.logging.info("Generating dataset.")
- stats = collections.Counter()
- dataset = []
- for filename in input_files:
- dataset.extend(_process_input_file(filename, vocab, stats))
- if FLAGS.max_sentences and stats["sentences_output"] >= FLAGS.max_sentences:
- break
-
- tf.logging.info("Generated dataset with %d sentences.", len(dataset))
- for k, v in stats.items():
- tf.logging.info("%s: %d", k, v)
-
- tf.logging.info("Shuffling dataset.")
- np.random.seed(123)
- shuffled_indices = np.random.permutation(len(dataset))
- val_indices = shuffled_indices[:FLAGS.num_validation_sentences]
- train_indices = shuffled_indices[FLAGS.num_validation_sentences:]
-
- _write_dataset("train", dataset, train_indices, FLAGS.train_output_shards)
- _write_dataset("validation", dataset, val_indices,
- FLAGS.validation_output_shards)
-
-
-if __name__ == "__main__":
- tf.app.run()
diff --git a/research/skip_thoughts/skip_thoughts/data/special_words.py b/research/skip_thoughts/skip_thoughts/data/special_words.py
deleted file mode 100644
index fb76b7a94d1655f49f6906aa42fb2913ba8eceb9..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/skip_thoughts/data/special_words.py
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Special word constants.
-
-NOTE: The ids of the EOS and UNK constants should not be modified. It is assumed
-that these always occupy the first two ids.
-"""
-
-# End of sentence.
-EOS = ""
-EOS_ID = 0
-
-# Unknown.
-UNK = ""
-UNK_ID = 1
diff --git a/research/skip_thoughts/skip_thoughts/encoder_manager.py b/research/skip_thoughts/skip_thoughts/encoder_manager.py
deleted file mode 100644
index 00b220245ab30d7c408a9becd146f8ff44c2e054..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/skip_thoughts/encoder_manager.py
+++ /dev/null
@@ -1,134 +0,0 @@
-# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Manager class for loading and encoding with multiple skip-thoughts models.
-
-If multiple models are loaded at once then the encode() function returns the
-concatenation of the outputs of each model.
-
-Example usage:
- manager = EncoderManager()
- manager.load_model(model_config_1, vocabulary_file_1, embedding_matrix_file_1,
- checkpoint_path_1)
- manager.load_model(model_config_2, vocabulary_file_2, embedding_matrix_file_2,
- checkpoint_path_2)
- encodings = manager.encode(data)
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-
-
-import numpy as np
-import tensorflow as tf
-
-from skip_thoughts import skip_thoughts_encoder
-
-
-class EncoderManager(object):
- """Manager class for loading and encoding with skip-thoughts models."""
-
- def __init__(self):
- self.encoders = []
- self.sessions = []
-
- def load_model(self, model_config, vocabulary_file, embedding_matrix_file,
- checkpoint_path):
- """Loads a skip-thoughts model.
-
- Args:
- model_config: Object containing parameters for building the model.
- vocabulary_file: Path to vocabulary file containing a list of newline-
- separated words where the word id is the corresponding 0-based index in
- the file.
- embedding_matrix_file: Path to a serialized numpy array of shape
- [vocab_size, embedding_dim].
- checkpoint_path: SkipThoughtsModel checkpoint file or a directory
- containing a checkpoint file.
- """
- tf.logging.info("Reading vocabulary from %s", vocabulary_file)
- with tf.gfile.GFile(vocabulary_file, mode="rb") as f:
- lines = list(f.readlines())
- reverse_vocab = [line.decode("utf-8").strip() for line in lines]
-
- tf.logging.info("Loaded vocabulary with %d words.", len(reverse_vocab))
-
- tf.logging.info("Loading embedding matrix from %s", embedding_matrix_file)
- # Note: tf.gfile.GFile doesn't work here because np.load() calls f.seek()
- # with 3 arguments.
- embedding_matrix = np.load(embedding_matrix_file)
- tf.logging.info("Loaded embedding matrix with shape %s",
- embedding_matrix.shape)
-
- word_embeddings = collections.OrderedDict(
- zip(reverse_vocab, embedding_matrix))
-
- g = tf.Graph()
- with g.as_default():
- encoder = skip_thoughts_encoder.SkipThoughtsEncoder(word_embeddings)
- restore_model = encoder.build_graph_from_config(model_config,
- checkpoint_path)
-
- sess = tf.Session(graph=g)
- restore_model(sess)
-
- self.encoders.append(encoder)
- self.sessions.append(sess)
-
- def encode(self,
- data,
- use_norm=True,
- verbose=False,
- batch_size=128,
- use_eos=False):
- """Encodes a sequence of sentences as skip-thought vectors.
-
- Args:
- data: A list of input strings.
- use_norm: If True, normalize output skip-thought vectors to unit L2 norm.
- verbose: Whether to log every batch.
- batch_size: Batch size for the RNN encoders.
- use_eos: If True, append the end-of-sentence word to each input sentence.
-
- Returns:
- thought_vectors: A list of numpy arrays corresponding to 'data'.
-
- Raises:
- ValueError: If called before calling load_encoder.
- """
- if not self.encoders:
- raise ValueError(
- "Must call load_model at least once before calling encode.")
-
- encoded = []
- for encoder, sess in zip(self.encoders, self.sessions):
- encoded.append(
- np.array(
- encoder.encode(
- sess,
- data,
- use_norm=use_norm,
- verbose=verbose,
- batch_size=batch_size,
- use_eos=use_eos)))
-
- return np.concatenate(encoded, axis=1)
-
- def close(self):
- """Closes the active TensorFlow Sessions."""
- for sess in self.sessions:
- sess.close()
diff --git a/research/skip_thoughts/skip_thoughts/evaluate.py b/research/skip_thoughts/skip_thoughts/evaluate.py
deleted file mode 100644
index e840d9da9f5c2e7e223669388ef0f43ed4f63398..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/skip_thoughts/evaluate.py
+++ /dev/null
@@ -1,117 +0,0 @@
-# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Script to evaluate a skip-thoughts model.
-
-This script can evaluate a model with a unidirectional encoder ("uni-skip" in
-the paper); or a model with a bidirectional encoder ("bi-skip"); or the
-combination of a model with a unidirectional encoder and a model with a
-bidirectional encoder ("combine-skip").
-
-The uni-skip model (if it exists) is specified by the flags
---uni_vocab_file, --uni_embeddings_file, --uni_checkpoint_path.
-
-The bi-skip model (if it exists) is specified by the flags
---bi_vocab_file, --bi_embeddings_path, --bi_checkpoint_path.
-
-The evaluation tasks have different running times. SICK may take 5-10 minutes.
-MSRP, TREC and CR may take 20-60 minutes. SUBJ, MPQA and MR may take 2+ hours.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-from skipthoughts import eval_classification
-from skipthoughts import eval_msrp
-from skipthoughts import eval_sick
-from skipthoughts import eval_trec
-import tensorflow as tf
-
-from skip_thoughts import configuration
-from skip_thoughts import encoder_manager
-
-FLAGS = tf.flags.FLAGS
-
-tf.flags.DEFINE_string("eval_task", "CR",
- "Name of the evaluation task to run. Available tasks: "
- "MR, CR, SUBJ, MPQA, SICK, MSRP, TREC.")
-
-tf.flags.DEFINE_string("data_dir", None, "Directory containing training data.")
-
-tf.flags.DEFINE_string("uni_vocab_file", None,
- "Path to vocabulary file containing a list of newline-"
- "separated words where the word id is the "
- "corresponding 0-based index in the file.")
-tf.flags.DEFINE_string("bi_vocab_file", None,
- "Path to vocabulary file containing a list of newline-"
- "separated words where the word id is the "
- "corresponding 0-based index in the file.")
-
-tf.flags.DEFINE_string("uni_embeddings_file", None,
- "Path to serialized numpy array of shape "
- "[vocab_size, embedding_dim].")
-tf.flags.DEFINE_string("bi_embeddings_file", None,
- "Path to serialized numpy array of shape "
- "[vocab_size, embedding_dim].")
-
-tf.flags.DEFINE_string("uni_checkpoint_path", None,
- "Checkpoint file or directory containing a checkpoint "
- "file.")
-tf.flags.DEFINE_string("bi_checkpoint_path", None,
- "Checkpoint file or directory containing a checkpoint "
- "file.")
-
-tf.logging.set_verbosity(tf.logging.INFO)
-
-
-def main(unused_argv):
- if not FLAGS.data_dir:
- raise ValueError("--data_dir is required.")
-
- encoder = encoder_manager.EncoderManager()
-
- # Maybe load unidirectional encoder.
- if FLAGS.uni_checkpoint_path:
- print("Loading unidirectional model...")
- uni_config = configuration.model_config()
- encoder.load_model(uni_config, FLAGS.uni_vocab_file,
- FLAGS.uni_embeddings_file, FLAGS.uni_checkpoint_path)
-
- # Maybe load bidirectional encoder.
- if FLAGS.bi_checkpoint_path:
- print("Loading bidirectional model...")
- bi_config = configuration.model_config(bidirectional_encoder=True)
- encoder.load_model(bi_config, FLAGS.bi_vocab_file, FLAGS.bi_embeddings_file,
- FLAGS.bi_checkpoint_path)
-
- if FLAGS.eval_task in ["MR", "CR", "SUBJ", "MPQA"]:
- eval_classification.eval_nested_kfold(
- encoder, FLAGS.eval_task, FLAGS.data_dir, use_nb=False)
- elif FLAGS.eval_task == "SICK":
- eval_sick.evaluate(encoder, evaltest=True, loc=FLAGS.data_dir)
- elif FLAGS.eval_task == "MSRP":
- eval_msrp.evaluate(
- encoder, evalcv=True, evaltest=True, use_feats=True, loc=FLAGS.data_dir)
- elif FLAGS.eval_task == "TREC":
- eval_trec.evaluate(encoder, evalcv=True, evaltest=True, loc=FLAGS.data_dir)
- else:
- raise ValueError("Unrecognized eval_task: %s" % FLAGS.eval_task)
-
- encoder.close()
-
-
-if __name__ == "__main__":
- tf.app.run()
diff --git a/research/skip_thoughts/skip_thoughts/ops/BUILD b/research/skip_thoughts/skip_thoughts/ops/BUILD
deleted file mode 100644
index 896d54db76e743008dcd50fc7a5b44aabb61d251..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/skip_thoughts/ops/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-package(default_visibility = ["//visibility:public"])
-
-licenses(["notice"]) # Apache 2.0
-
-exports_files(["LICENSE"])
-
-py_library(
- name = "input_ops",
- srcs = ["input_ops.py"],
- srcs_version = "PY2AND3",
-)
-
-py_library(
- name = "gru_cell",
- srcs = ["gru_cell.py"],
- srcs_version = "PY2AND3",
-)
diff --git a/research/skip_thoughts/skip_thoughts/ops/__init__.py b/research/skip_thoughts/skip_thoughts/ops/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/research/skip_thoughts/skip_thoughts/ops/gru_cell.py b/research/skip_thoughts/skip_thoughts/ops/gru_cell.py
deleted file mode 100644
index c4bee46d3a9f5faf1ec060a3b21f66b4fe51d0c9..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/skip_thoughts/ops/gru_cell.py
+++ /dev/null
@@ -1,134 +0,0 @@
-# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""GRU cell implementation for the skip-thought vectors model."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import tensorflow as tf
-
-_layer_norm = tf.contrib.layers.layer_norm
-
-
-class LayerNormGRUCell(tf.contrib.rnn.RNNCell):
- """GRU cell with layer normalization.
-
- The layer normalization implementation is based on:
-
- https://arxiv.org/abs/1607.06450.
-
- "Layer Normalization"
- Jimmy Lei Ba, Jamie Ryan Kiros, Geoffrey E. Hinton
- """
-
- def __init__(self,
- num_units,
- w_initializer,
- u_initializer,
- b_initializer,
- activation=tf.nn.tanh):
- """Initializes the cell.
-
- Args:
- num_units: Number of cell units.
- w_initializer: Initializer for the "W" (input) parameter matrices.
- u_initializer: Initializer for the "U" (recurrent) parameter matrices.
- b_initializer: Initializer for the "b" (bias) parameter vectors.
- activation: Cell activation function.
- """
- self._num_units = num_units
- self._w_initializer = w_initializer
- self._u_initializer = u_initializer
- self._b_initializer = b_initializer
- self._activation = activation
-
- @property
- def state_size(self):
- return self._num_units
-
- @property
- def output_size(self):
- return self._num_units
-
- def _w_h_initializer(self):
- """Returns an initializer for the "W_h" parameter matrix.
-
- See equation (23) in the paper. The "W_h" parameter matrix is the
- concatenation of two parameter submatrices. The matrix returned is
- [U_z, U_r].
-
- Returns:
- A Tensor with shape [num_units, 2 * num_units] as described above.
- """
-
- def _initializer(shape, dtype=tf.float32, partition_info=None):
- num_units = self._num_units
- assert shape == [num_units, 2 * num_units]
- u_z = self._u_initializer([num_units, num_units], dtype, partition_info)
- u_r = self._u_initializer([num_units, num_units], dtype, partition_info)
- return tf.concat([u_z, u_r], 1)
-
- return _initializer
-
- def _w_x_initializer(self, input_dim):
- """Returns an initializer for the "W_x" parameter matrix.
-
- See equation (23) in the paper. The "W_x" parameter matrix is the
- concatenation of two parameter submatrices. The matrix returned is
- [W_z, W_r].
-
- Args:
- input_dim: The dimension of the cell inputs.
-
- Returns:
- A Tensor with shape [input_dim, 2 * num_units] as described above.
- """
-
- def _initializer(shape, dtype=tf.float32, partition_info=None):
- num_units = self._num_units
- assert shape == [input_dim, 2 * num_units]
- w_z = self._w_initializer([input_dim, num_units], dtype, partition_info)
- w_r = self._w_initializer([input_dim, num_units], dtype, partition_info)
- return tf.concat([w_z, w_r], 1)
-
- return _initializer
-
- def __call__(self, inputs, state, scope=None):
- """GRU cell with layer normalization."""
- input_dim = inputs.get_shape().as_list()[1]
- num_units = self._num_units
-
- with tf.variable_scope(scope or "gru_cell"):
- with tf.variable_scope("gates"):
- w_h = tf.get_variable(
- "w_h", [num_units, 2 * num_units],
- initializer=self._w_h_initializer())
- w_x = tf.get_variable(
- "w_x", [input_dim, 2 * num_units],
- initializer=self._w_x_initializer(input_dim))
- z_and_r = (_layer_norm(tf.matmul(state, w_h), scope="layer_norm/w_h") +
- _layer_norm(tf.matmul(inputs, w_x), scope="layer_norm/w_x"))
- z, r = tf.split(tf.sigmoid(z_and_r), 2, 1)
- with tf.variable_scope("candidate"):
- w = tf.get_variable(
- "w", [input_dim, num_units], initializer=self._w_initializer)
- u = tf.get_variable(
- "u", [num_units, num_units], initializer=self._u_initializer)
- h_hat = (r * _layer_norm(tf.matmul(state, u), scope="layer_norm/u") +
- _layer_norm(tf.matmul(inputs, w), scope="layer_norm/w"))
- new_h = (1 - z) * state + z * self._activation(h_hat)
- return new_h, new_h
diff --git a/research/skip_thoughts/skip_thoughts/ops/input_ops.py b/research/skip_thoughts/skip_thoughts/ops/input_ops.py
deleted file mode 100644
index 51b03fc5da335b78977d5c1b9234160f1c240e53..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/skip_thoughts/ops/input_ops.py
+++ /dev/null
@@ -1,118 +0,0 @@
-# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Input ops."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-
-
-import tensorflow as tf
-
-# A SentenceBatch is a pair of Tensors:
-# ids: Batch of input sentences represented as sequences of word ids: an int64
-# Tensor with shape [batch_size, padded_length].
-# mask: Boolean mask distinguishing real words (1) from padded words (0): an
-# int32 Tensor with shape [batch_size, padded_length].
-SentenceBatch = collections.namedtuple("SentenceBatch", ("ids", "mask"))
-
-
-def parse_example_batch(serialized):
- """Parses a batch of tf.Example protos.
-
- Args:
- serialized: A 1-D string Tensor; a batch of serialized tf.Example protos.
- Returns:
- encode: A SentenceBatch of encode sentences.
- decode_pre: A SentenceBatch of "previous" sentences to decode.
- decode_post: A SentenceBatch of "post" sentences to decode.
- """
- features = tf.parse_example(
- serialized,
- features={
- "encode": tf.VarLenFeature(dtype=tf.int64),
- "decode_pre": tf.VarLenFeature(dtype=tf.int64),
- "decode_post": tf.VarLenFeature(dtype=tf.int64),
- })
-
- def _sparse_to_batch(sparse):
- ids = tf.sparse_tensor_to_dense(sparse) # Padding with zeroes.
- mask = tf.sparse_to_dense(sparse.indices, sparse.dense_shape,
- tf.ones_like(sparse.values, dtype=tf.int32))
- return SentenceBatch(ids=ids, mask=mask)
-
- output_names = ("encode", "decode_pre", "decode_post")
- return tuple(_sparse_to_batch(features[x]) for x in output_names)
-
-
-def prefetch_input_data(reader,
- file_pattern,
- shuffle,
- capacity,
- num_reader_threads=1):
- """Prefetches string values from disk into an input queue.
-
- Args:
- reader: Instance of tf.ReaderBase.
- file_pattern: Comma-separated list of file patterns (e.g.
- "/tmp/train_data-?????-of-00100", where '?' acts as a wildcard that
- matches any character).
- shuffle: Boolean; whether to randomly shuffle the input data.
- capacity: Queue capacity (number of records).
- num_reader_threads: Number of reader threads feeding into the queue.
-
- Returns:
- A Queue containing prefetched string values.
- """
- data_files = []
- for pattern in file_pattern.split(","):
- data_files.extend(tf.gfile.Glob(pattern))
- if not data_files:
- tf.logging.fatal("Found no input files matching %s", file_pattern)
- else:
- tf.logging.info("Prefetching values from %d files matching %s",
- len(data_files), file_pattern)
-
- filename_queue = tf.train.string_input_producer(
- data_files, shuffle=shuffle, capacity=16, name="filename_queue")
-
- if shuffle:
- min_after_dequeue = int(0.6 * capacity)
- values_queue = tf.RandomShuffleQueue(
- capacity=capacity,
- min_after_dequeue=min_after_dequeue,
- dtypes=[tf.string],
- shapes=[[]],
- name="random_input_queue")
- else:
- values_queue = tf.FIFOQueue(
- capacity=capacity,
- dtypes=[tf.string],
- shapes=[[]],
- name="fifo_input_queue")
-
- enqueue_ops = []
- for _ in range(num_reader_threads):
- _, value = reader.read(filename_queue)
- enqueue_ops.append(values_queue.enqueue([value]))
- tf.train.queue_runner.add_queue_runner(
- tf.train.queue_runner.QueueRunner(values_queue, enqueue_ops))
- tf.summary.scalar("queue/%s/fraction_of_%d_full" % (values_queue.name,
- capacity),
- tf.cast(values_queue.size(), tf.float32) * (1.0 / capacity))
-
- return values_queue
diff --git a/research/skip_thoughts/skip_thoughts/skip_thoughts_encoder.py b/research/skip_thoughts/skip_thoughts/skip_thoughts_encoder.py
deleted file mode 100644
index 79c47c58813feb72f1b9bdb5c2f7bd7956f015c8..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/skip_thoughts/skip_thoughts_encoder.py
+++ /dev/null
@@ -1,258 +0,0 @@
-# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Class for encoding text using a trained SkipThoughtsModel.
-
-Example usage:
- g = tf.Graph()
- with g.as_default():
- encoder = SkipThoughtsEncoder(embeddings)
- restore_fn = encoder.build_graph_from_config(model_config, checkpoint_path)
-
- with tf.Session(graph=g) as sess:
- restore_fn(sess)
- skip_thought_vectors = encoder.encode(sess, data)
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os.path
-
-
-import nltk
-import nltk.tokenize
-import numpy as np
-import tensorflow as tf
-
-from skip_thoughts import skip_thoughts_model
-from skip_thoughts.data import special_words
-
-
-def _pad(seq, target_len):
- """Pads a sequence of word embeddings up to the target length.
-
- Args:
- seq: Sequence of word embeddings.
- target_len: Desired padded sequence length.
-
- Returns:
- embeddings: Input sequence padded with zero embeddings up to the target
- length.
- mask: A 0/1 vector with zeros corresponding to padded embeddings.
-
- Raises:
- ValueError: If len(seq) is not in the interval (0, target_len].
- """
- seq_len = len(seq)
- if seq_len <= 0 or seq_len > target_len:
- raise ValueError("Expected 0 < len(seq) <= %d, got %d" % (target_len,
- seq_len))
-
- emb_dim = seq[0].shape[0]
- padded_seq = np.zeros(shape=(target_len, emb_dim), dtype=seq[0].dtype)
- mask = np.zeros(shape=(target_len,), dtype=np.int8)
- for i in range(seq_len):
- padded_seq[i] = seq[i]
- mask[i] = 1
- return padded_seq, mask
-
-
-def _batch_and_pad(sequences):
- """Batches and pads sequences of word embeddings into a 2D array.
-
- Args:
- sequences: A list of batch_size sequences of word embeddings.
-
- Returns:
- embeddings: A numpy array with shape [batch_size, padded_length, emb_dim].
- mask: A numpy 0/1 array with shape [batch_size, padded_length] with zeros
- corresponding to padded elements.
- """
- batch_embeddings = []
- batch_mask = []
- batch_len = max([len(seq) for seq in sequences])
- for seq in sequences:
- embeddings, mask = _pad(seq, batch_len)
- batch_embeddings.append(embeddings)
- batch_mask.append(mask)
- return np.array(batch_embeddings), np.array(batch_mask)
-
-
-class SkipThoughtsEncoder(object):
- """Skip-thoughts sentence encoder."""
-
- def __init__(self, embeddings):
- """Initializes the encoder.
-
- Args:
- embeddings: Dictionary of word to embedding vector (1D numpy array).
- """
- self._sentence_detector = nltk.data.load("tokenizers/punkt/english.pickle")
- self._embeddings = embeddings
-
- def _create_restore_fn(self, checkpoint_path, saver):
- """Creates a function that restores a model from checkpoint.
-
- Args:
- checkpoint_path: Checkpoint file or a directory containing a checkpoint
- file.
- saver: Saver for restoring variables from the checkpoint file.
-
- Returns:
- restore_fn: A function such that restore_fn(sess) loads model variables
- from the checkpoint file.
-
- Raises:
- ValueError: If checkpoint_path does not refer to a checkpoint file or a
- directory containing a checkpoint file.
- """
- if tf.gfile.IsDirectory(checkpoint_path):
- latest_checkpoint = tf.train.latest_checkpoint(checkpoint_path)
- if not latest_checkpoint:
- raise ValueError("No checkpoint file found in: %s" % checkpoint_path)
- checkpoint_path = latest_checkpoint
-
- def _restore_fn(sess):
- tf.logging.info("Loading model from checkpoint: %s", checkpoint_path)
- saver.restore(sess, checkpoint_path)
- tf.logging.info("Successfully loaded checkpoint: %s",
- os.path.basename(checkpoint_path))
-
- return _restore_fn
-
- def build_graph_from_config(self, model_config, checkpoint_path):
- """Builds the inference graph from a configuration object.
-
- Args:
- model_config: Object containing configuration for building the model.
- checkpoint_path: Checkpoint file or a directory containing a checkpoint
- file.
-
- Returns:
- restore_fn: A function such that restore_fn(sess) loads model variables
- from the checkpoint file.
- """
- tf.logging.info("Building model.")
- model = skip_thoughts_model.SkipThoughtsModel(model_config, mode="encode")
- model.build()
- saver = tf.train.Saver()
-
- return self._create_restore_fn(checkpoint_path, saver)
-
- def build_graph_from_proto(self, graph_def_file, saver_def_file,
- checkpoint_path):
- """Builds the inference graph from serialized GraphDef and SaverDef protos.
-
- Args:
- graph_def_file: File containing a serialized GraphDef proto.
- saver_def_file: File containing a serialized SaverDef proto.
- checkpoint_path: Checkpoint file or a directory containing a checkpoint
- file.
-
- Returns:
- restore_fn: A function such that restore_fn(sess) loads model variables
- from the checkpoint file.
- """
- # Load the Graph.
- tf.logging.info("Loading GraphDef from file: %s", graph_def_file)
- graph_def = tf.GraphDef()
- with tf.gfile.FastGFile(graph_def_file, "rb") as f:
- graph_def.ParseFromString(f.read())
- tf.import_graph_def(graph_def, name="")
-
- # Load the Saver.
- tf.logging.info("Loading SaverDef from file: %s", saver_def_file)
- saver_def = tf.train.SaverDef()
- with tf.gfile.FastGFile(saver_def_file, "rb") as f:
- saver_def.ParseFromString(f.read())
- saver = tf.train.Saver(saver_def=saver_def)
-
- return self._create_restore_fn(checkpoint_path, saver)
-
- def _tokenize(self, item):
- """Tokenizes an input string into a list of words."""
- tokenized = []
- for s in self._sentence_detector.tokenize(item):
- tokenized.extend(nltk.tokenize.word_tokenize(s))
-
- return tokenized
-
- def _word_to_embedding(self, w):
- """Returns the embedding of a word."""
- return self._embeddings.get(w, self._embeddings[special_words.UNK])
-
- def _preprocess(self, data, use_eos):
- """Preprocesses text for the encoder.
-
- Args:
- data: A list of input strings.
- use_eos: Whether to append the end-of-sentence word to each sentence.
-
- Returns:
- embeddings: A list of word embedding sequences corresponding to the input
- strings.
- """
- preprocessed_data = []
- for item in data:
- tokenized = self._tokenize(item)
- if use_eos:
- tokenized.append(special_words.EOS)
- preprocessed_data.append([self._word_to_embedding(w) for w in tokenized])
- return preprocessed_data
-
- def encode(self,
- sess,
- data,
- use_norm=True,
- verbose=True,
- batch_size=128,
- use_eos=False):
- """Encodes a sequence of sentences as skip-thought vectors.
-
- Args:
- sess: TensorFlow Session.
- data: A list of input strings.
- use_norm: Whether to normalize skip-thought vectors to unit L2 norm.
- verbose: Whether to log every batch.
- batch_size: Batch size for the encoder.
- use_eos: Whether to append the end-of-sentence word to each input
- sentence.
-
- Returns:
- thought_vectors: A list of numpy arrays corresponding to the skip-thought
- encodings of sentences in 'data'.
- """
- data = self._preprocess(data, use_eos)
- thought_vectors = []
-
- batch_indices = np.arange(0, len(data), batch_size)
- for batch, start_index in enumerate(batch_indices):
- if verbose:
- tf.logging.info("Batch %d / %d.", batch, len(batch_indices))
-
- embeddings, mask = _batch_and_pad(
- data[start_index:start_index + batch_size])
- feed_dict = {
- "encode_emb:0": embeddings,
- "encode_mask:0": mask,
- }
- thought_vectors.extend(
- sess.run("encoder/thought_vectors:0", feed_dict=feed_dict))
-
- if use_norm:
- thought_vectors = [v / np.linalg.norm(v) for v in thought_vectors]
-
- return thought_vectors
diff --git a/research/skip_thoughts/skip_thoughts/skip_thoughts_model.py b/research/skip_thoughts/skip_thoughts/skip_thoughts_model.py
deleted file mode 100644
index 9a9a43a4fed0dbbb03affd26ffa1c635c386aa55..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/skip_thoughts/skip_thoughts_model.py
+++ /dev/null
@@ -1,369 +0,0 @@
-# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Skip-Thoughts model for learning sentence vectors.
-
-The model is based on the paper:
-
- "Skip-Thought Vectors"
- Ryan Kiros, Yukun Zhu, Ruslan Salakhutdinov, Richard S. Zemel,
- Antonio Torralba, Raquel Urtasun, Sanja Fidler.
- https://papers.nips.cc/paper/5950-skip-thought-vectors.pdf
-
-Layer normalization is applied based on the paper:
-
- "Layer Normalization"
- Jimmy Lei Ba, Jamie Ryan Kiros, Geoffrey E. Hinton
- https://arxiv.org/abs/1607.06450
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import tensorflow as tf
-
-from skip_thoughts.ops import gru_cell
-from skip_thoughts.ops import input_ops
-
-
-def random_orthonormal_initializer(shape, dtype=tf.float32,
- partition_info=None): # pylint: disable=unused-argument
- """Variable initializer that produces a random orthonormal matrix."""
- if len(shape) != 2 or shape[0] != shape[1]:
- raise ValueError("Expecting square shape, got %s" % shape)
- _, u, _ = tf.svd(tf.random_normal(shape, dtype=dtype), full_matrices=True)
- return u
-
-
-class SkipThoughtsModel(object):
- """Skip-thoughts model."""
-
- def __init__(self, config, mode="train", input_reader=None):
- """Basic setup. The actual TensorFlow graph is constructed in build().
-
- Args:
- config: Object containing configuration parameters.
- mode: "train", "eval" or "encode".
- input_reader: Subclass of tf.ReaderBase for reading the input serialized
- tf.Example protocol buffers. Defaults to TFRecordReader.
-
- Raises:
- ValueError: If mode is invalid.
- """
- if mode not in ["train", "eval", "encode"]:
- raise ValueError("Unrecognized mode: %s" % mode)
-
- self.config = config
- self.mode = mode
- self.reader = input_reader if input_reader else tf.TFRecordReader()
-
- # Initializer used for non-recurrent weights.
- self.uniform_initializer = tf.random_uniform_initializer(
- minval=-self.config.uniform_init_scale,
- maxval=self.config.uniform_init_scale)
-
- # Input sentences represented as sequences of word ids. "encode" is the
- # source sentence, "decode_pre" is the previous sentence and "decode_post"
- # is the next sentence.
- # Each is an int64 Tensor with shape [batch_size, padded_length].
- self.encode_ids = None
- self.decode_pre_ids = None
- self.decode_post_ids = None
-
- # Boolean masks distinguishing real words (1) from padded words (0).
- # Each is an int32 Tensor with shape [batch_size, padded_length].
- self.encode_mask = None
- self.decode_pre_mask = None
- self.decode_post_mask = None
-
- # Input sentences represented as sequences of word embeddings.
- # Each is a float32 Tensor with shape [batch_size, padded_length, emb_dim].
- self.encode_emb = None
- self.decode_pre_emb = None
- self.decode_post_emb = None
-
- # The output from the sentence encoder.
- # A float32 Tensor with shape [batch_size, num_gru_units].
- self.thought_vectors = None
-
- # The cross entropy losses and corresponding weights of the decoders. Used
- # for evaluation.
- self.target_cross_entropy_losses = []
- self.target_cross_entropy_loss_weights = []
-
- # The total loss to optimize.
- self.total_loss = None
-
- def build_inputs(self):
- """Builds the ops for reading input data.
-
- Outputs:
- self.encode_ids
- self.decode_pre_ids
- self.decode_post_ids
- self.encode_mask
- self.decode_pre_mask
- self.decode_post_mask
- """
- if self.mode == "encode":
- # Word embeddings are fed from an external vocabulary which has possibly
- # been expanded (see vocabulary_expansion.py).
- encode_ids = None
- decode_pre_ids = None
- decode_post_ids = None
- encode_mask = tf.placeholder(tf.int8, (None, None), name="encode_mask")
- decode_pre_mask = None
- decode_post_mask = None
- else:
- # Prefetch serialized tf.Example protos.
- input_queue = input_ops.prefetch_input_data(
- self.reader,
- self.config.input_file_pattern,
- shuffle=self.config.shuffle_input_data,
- capacity=self.config.input_queue_capacity,
- num_reader_threads=self.config.num_input_reader_threads)
-
- # Deserialize a batch.
- serialized = input_queue.dequeue_many(self.config.batch_size)
- encode, decode_pre, decode_post = input_ops.parse_example_batch(
- serialized)
-
- encode_ids = encode.ids
- decode_pre_ids = decode_pre.ids
- decode_post_ids = decode_post.ids
-
- encode_mask = encode.mask
- decode_pre_mask = decode_pre.mask
- decode_post_mask = decode_post.mask
-
- self.encode_ids = encode_ids
- self.decode_pre_ids = decode_pre_ids
- self.decode_post_ids = decode_post_ids
-
- self.encode_mask = encode_mask
- self.decode_pre_mask = decode_pre_mask
- self.decode_post_mask = decode_post_mask
-
- def build_word_embeddings(self):
- """Builds the word embeddings.
-
- Inputs:
- self.encode_ids
- self.decode_pre_ids
- self.decode_post_ids
-
- Outputs:
- self.encode_emb
- self.decode_pre_emb
- self.decode_post_emb
- """
- if self.mode == "encode":
- # Word embeddings are fed from an external vocabulary which has possibly
- # been expanded (see vocabulary_expansion.py).
- encode_emb = tf.placeholder(tf.float32, (
- None, None, self.config.word_embedding_dim), "encode_emb")
- # No sequences to decode.
- decode_pre_emb = None
- decode_post_emb = None
- else:
- word_emb = tf.get_variable(
- name="word_embedding",
- shape=[self.config.vocab_size, self.config.word_embedding_dim],
- initializer=self.uniform_initializer)
-
- encode_emb = tf.nn.embedding_lookup(word_emb, self.encode_ids)
- decode_pre_emb = tf.nn.embedding_lookup(word_emb, self.decode_pre_ids)
- decode_post_emb = tf.nn.embedding_lookup(word_emb, self.decode_post_ids)
-
- self.encode_emb = encode_emb
- self.decode_pre_emb = decode_pre_emb
- self.decode_post_emb = decode_post_emb
-
- def _initialize_gru_cell(self, num_units):
- """Initializes a GRU cell.
-
- The Variables of the GRU cell are initialized in a way that exactly matches
- the skip-thoughts paper: recurrent weights are initialized from random
- orthonormal matrices and non-recurrent weights are initialized from random
- uniform matrices.
-
- Args:
- num_units: Number of output units.
-
- Returns:
- cell: An instance of RNNCell with variable initializers that match the
- skip-thoughts paper.
- """
- return gru_cell.LayerNormGRUCell(
- num_units,
- w_initializer=self.uniform_initializer,
- u_initializer=random_orthonormal_initializer,
- b_initializer=tf.constant_initializer(0.0))
-
- def build_encoder(self):
- """Builds the sentence encoder.
-
- Inputs:
- self.encode_emb
- self.encode_mask
-
- Outputs:
- self.thought_vectors
-
- Raises:
- ValueError: if config.bidirectional_encoder is True and config.encoder_dim
- is odd.
- """
- with tf.variable_scope("encoder") as scope:
- length = tf.to_int32(tf.reduce_sum(self.encode_mask, 1), name="length")
-
- if self.config.bidirectional_encoder:
- if self.config.encoder_dim % 2:
- raise ValueError(
- "encoder_dim must be even when using a bidirectional encoder.")
- num_units = self.config.encoder_dim // 2
- cell_fw = self._initialize_gru_cell(num_units) # Forward encoder
- cell_bw = self._initialize_gru_cell(num_units) # Backward encoder
- _, states = tf.nn.bidirectional_dynamic_rnn(
- cell_fw=cell_fw,
- cell_bw=cell_bw,
- inputs=self.encode_emb,
- sequence_length=length,
- dtype=tf.float32,
- scope=scope)
- thought_vectors = tf.concat(states, 1, name="thought_vectors")
- else:
- cell = self._initialize_gru_cell(self.config.encoder_dim)
- _, state = tf.nn.dynamic_rnn(
- cell=cell,
- inputs=self.encode_emb,
- sequence_length=length,
- dtype=tf.float32,
- scope=scope)
- # Use an identity operation to name the Tensor in the Graph.
- thought_vectors = tf.identity(state, name="thought_vectors")
-
- self.thought_vectors = thought_vectors
-
- def _build_decoder(self, name, embeddings, targets, mask, initial_state,
- reuse_logits):
- """Builds a sentence decoder.
-
- Args:
- name: Decoder name.
- embeddings: Batch of sentences to decode; a float32 Tensor with shape
- [batch_size, padded_length, emb_dim].
- targets: Batch of target word ids; an int64 Tensor with shape
- [batch_size, padded_length].
- mask: A 0/1 Tensor with shape [batch_size, padded_length].
- initial_state: Initial state of the GRU. A float32 Tensor with shape
- [batch_size, num_gru_cells].
- reuse_logits: Whether to reuse the logits weights.
- """
- # Decoder RNN.
- cell = self._initialize_gru_cell(self.config.encoder_dim)
- with tf.variable_scope(name) as scope:
- # Add a padding word at the start of each sentence (to correspond to the
- # prediction of the first word) and remove the last word.
- decoder_input = tf.pad(
- embeddings[:, :-1, :], [[0, 0], [1, 0], [0, 0]], name="input")
- length = tf.reduce_sum(mask, 1, name="length")
- decoder_output, _ = tf.nn.dynamic_rnn(
- cell=cell,
- inputs=decoder_input,
- sequence_length=length,
- initial_state=initial_state,
- scope=scope)
-
- # Stack batch vertically.
- decoder_output = tf.reshape(decoder_output, [-1, self.config.encoder_dim])
- targets = tf.reshape(targets, [-1])
- weights = tf.to_float(tf.reshape(mask, [-1]))
-
- # Logits.
- with tf.variable_scope("logits", reuse=reuse_logits) as scope:
- logits = tf.contrib.layers.fully_connected(
- inputs=decoder_output,
- num_outputs=self.config.vocab_size,
- activation_fn=None,
- weights_initializer=self.uniform_initializer,
- scope=scope)
-
- losses = tf.nn.sparse_softmax_cross_entropy_with_logits(
- labels=targets, logits=logits)
- batch_loss = tf.reduce_sum(losses * weights)
- tf.losses.add_loss(batch_loss)
-
- tf.summary.scalar("losses/" + name, batch_loss)
-
- self.target_cross_entropy_losses.append(losses)
- self.target_cross_entropy_loss_weights.append(weights)
-
- def build_decoders(self):
- """Builds the sentence decoders.
-
- Inputs:
- self.decode_pre_emb
- self.decode_post_emb
- self.decode_pre_ids
- self.decode_post_ids
- self.decode_pre_mask
- self.decode_post_mask
- self.thought_vectors
-
- Outputs:
- self.target_cross_entropy_losses
- self.target_cross_entropy_loss_weights
- """
- if self.mode != "encode":
- # Pre-sentence decoder.
- self._build_decoder("decoder_pre", self.decode_pre_emb,
- self.decode_pre_ids, self.decode_pre_mask,
- self.thought_vectors, False)
-
- # Post-sentence decoder. Logits weights are reused.
- self._build_decoder("decoder_post", self.decode_post_emb,
- self.decode_post_ids, self.decode_post_mask,
- self.thought_vectors, True)
-
- def build_loss(self):
- """Builds the loss Tensor.
-
- Outputs:
- self.total_loss
- """
- if self.mode != "encode":
- total_loss = tf.losses.get_total_loss()
- tf.summary.scalar("losses/total", total_loss)
-
- self.total_loss = total_loss
-
- def build_global_step(self):
- """Builds the global step Tensor.
-
- Outputs:
- self.global_step
- """
- self.global_step = tf.contrib.framework.create_global_step()
-
- def build(self):
- """Creates all ops for training, evaluation or encoding."""
- self.build_inputs()
- self.build_word_embeddings()
- self.build_encoder()
- self.build_decoders()
- self.build_loss()
- self.build_global_step()
diff --git a/research/skip_thoughts/skip_thoughts/skip_thoughts_model_test.py b/research/skip_thoughts/skip_thoughts/skip_thoughts_model_test.py
deleted file mode 100644
index 7bd64326d9d9cdcaae11d74ac8831adac915dfe2..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/skip_thoughts/skip_thoughts_model_test.py
+++ /dev/null
@@ -1,191 +0,0 @@
-# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tests for tensorflow_models.skip_thoughts.skip_thoughts_model."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import numpy as np
-import tensorflow as tf
-
-from skip_thoughts import configuration
-from skip_thoughts import skip_thoughts_model
-
-
-class SkipThoughtsModel(skip_thoughts_model.SkipThoughtsModel):
- """Subclass of SkipThoughtsModel without the disk I/O."""
-
- def build_inputs(self):
- if self.mode == "encode":
- # Encode mode doesn't read from disk, so defer to parent.
- return super(SkipThoughtsModel, self).build_inputs()
- else:
- # Replace disk I/O with random Tensors.
- self.encode_ids = tf.random_uniform(
- [self.config.batch_size, 15],
- minval=0,
- maxval=self.config.vocab_size,
- dtype=tf.int64)
- self.decode_pre_ids = tf.random_uniform(
- [self.config.batch_size, 15],
- minval=0,
- maxval=self.config.vocab_size,
- dtype=tf.int64)
- self.decode_post_ids = tf.random_uniform(
- [self.config.batch_size, 15],
- minval=0,
- maxval=self.config.vocab_size,
- dtype=tf.int64)
- self.encode_mask = tf.ones_like(self.encode_ids)
- self.decode_pre_mask = tf.ones_like(self.decode_pre_ids)
- self.decode_post_mask = tf.ones_like(self.decode_post_ids)
-
-
-class SkipThoughtsModelTest(tf.test.TestCase):
-
- def setUp(self):
- super(SkipThoughtsModelTest, self).setUp()
- self._model_config = configuration.model_config()
-
- def _countModelParameters(self):
- """Counts the number of parameters in the model at top level scope."""
- counter = {}
- for v in tf.global_variables():
- name = v.op.name.split("/")[0]
- num_params = v.get_shape().num_elements()
- if not num_params:
- self.fail("Could not infer num_elements from Variable %s" % v.op.name)
- counter[name] = counter.get(name, 0) + num_params
- return counter
-
- def _checkModelParameters(self):
- """Verifies the number of parameters in the model."""
- param_counts = self._countModelParameters()
- expected_param_counts = {
- # vocab_size * embedding_size
- "word_embedding": 12400000,
- # GRU Cells
- "encoder": 21772800,
- "decoder_pre": 21772800,
- "decoder_post": 21772800,
- # (encoder_dim + 1) * vocab_size
- "logits": 48020000,
- "global_step": 1,
- }
- self.assertDictEqual(expected_param_counts, param_counts)
-
- def _checkOutputs(self, expected_shapes, feed_dict=None):
- """Verifies that the model produces expected outputs.
-
- Args:
- expected_shapes: A dict mapping Tensor or Tensor name to expected output
- shape.
- feed_dict: Values of Tensors to feed into Session.run().
- """
- fetches = expected_shapes.keys()
-
- with self.test_session() as sess:
- sess.run(tf.global_variables_initializer())
- outputs = sess.run(fetches, feed_dict)
-
- for index, output in enumerate(outputs):
- tensor = fetches[index]
- expected = expected_shapes[tensor]
- actual = output.shape
- if expected != actual:
- self.fail("Tensor %s has shape %s (expected %s)." % (tensor, actual,
- expected))
-
- def testBuildForTraining(self):
- model = SkipThoughtsModel(self._model_config, mode="train")
- model.build()
-
- self._checkModelParameters()
-
- expected_shapes = {
- # [batch_size, length]
- model.encode_ids: (128, 15),
- model.decode_pre_ids: (128, 15),
- model.decode_post_ids: (128, 15),
- model.encode_mask: (128, 15),
- model.decode_pre_mask: (128, 15),
- model.decode_post_mask: (128, 15),
- # [batch_size, length, word_embedding_dim]
- model.encode_emb: (128, 15, 620),
- model.decode_pre_emb: (128, 15, 620),
- model.decode_post_emb: (128, 15, 620),
- # [batch_size, encoder_dim]
- model.thought_vectors: (128, 2400),
- # [batch_size * length]
- model.target_cross_entropy_losses[0]: (1920,),
- model.target_cross_entropy_losses[1]: (1920,),
- # [batch_size * length]
- model.target_cross_entropy_loss_weights[0]: (1920,),
- model.target_cross_entropy_loss_weights[1]: (1920,),
- # Scalar
- model.total_loss: (),
- }
- self._checkOutputs(expected_shapes)
-
- def testBuildForEval(self):
- model = SkipThoughtsModel(self._model_config, mode="eval")
- model.build()
-
- self._checkModelParameters()
-
- expected_shapes = {
- # [batch_size, length]
- model.encode_ids: (128, 15),
- model.decode_pre_ids: (128, 15),
- model.decode_post_ids: (128, 15),
- model.encode_mask: (128, 15),
- model.decode_pre_mask: (128, 15),
- model.decode_post_mask: (128, 15),
- # [batch_size, length, word_embedding_dim]
- model.encode_emb: (128, 15, 620),
- model.decode_pre_emb: (128, 15, 620),
- model.decode_post_emb: (128, 15, 620),
- # [batch_size, encoder_dim]
- model.thought_vectors: (128, 2400),
- # [batch_size * length]
- model.target_cross_entropy_losses[0]: (1920,),
- model.target_cross_entropy_losses[1]: (1920,),
- # [batch_size * length]
- model.target_cross_entropy_loss_weights[0]: (1920,),
- model.target_cross_entropy_loss_weights[1]: (1920,),
- # Scalar
- model.total_loss: (),
- }
- self._checkOutputs(expected_shapes)
-
- def testBuildForEncode(self):
- model = SkipThoughtsModel(self._model_config, mode="encode")
- model.build()
-
- # Test feeding a batch of word embeddings to get skip thought vectors.
- encode_emb = np.random.rand(64, 15, 620)
- encode_mask = np.ones((64, 15), dtype=np.int64)
- feed_dict = {model.encode_emb: encode_emb, model.encode_mask: encode_mask}
- expected_shapes = {
- # [batch_size, encoder_dim]
- model.thought_vectors: (64, 2400),
- }
- self._checkOutputs(expected_shapes, feed_dict)
-
-
-if __name__ == "__main__":
- tf.test.main()
diff --git a/research/skip_thoughts/skip_thoughts/track_perplexity.py b/research/skip_thoughts/skip_thoughts/track_perplexity.py
deleted file mode 100644
index 637eaf2c07b5ea705441f146f020887392d9faf3..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/skip_thoughts/track_perplexity.py
+++ /dev/null
@@ -1,201 +0,0 @@
-# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tracks training progress via per-word perplexity.
-
-This script should be run concurrently with training so that summaries show up
-in TensorBoard.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from six.moves import range
-
-import math
-import os.path
-import time
-
-
-import numpy as np
-import tensorflow as tf
-
-from skip_thoughts import configuration
-from skip_thoughts import skip_thoughts_model
-
-FLAGS = tf.flags.FLAGS
-
-tf.flags.DEFINE_string("input_file_pattern", None,
- "File pattern of sharded TFRecord input files.")
-tf.flags.DEFINE_string("checkpoint_dir", None,
- "Directory containing model checkpoints.")
-tf.flags.DEFINE_string("eval_dir", None, "Directory to write event logs to.")
-
-tf.flags.DEFINE_integer("eval_interval_secs", 600,
- "Interval between evaluation runs.")
-tf.flags.DEFINE_integer("num_eval_examples", 50000,
- "Number of examples for evaluation.")
-
-tf.flags.DEFINE_integer("min_global_step", 100,
- "Minimum global step to run evaluation.")
-
-tf.logging.set_verbosity(tf.logging.INFO)
-
-
-def evaluate_model(sess, losses, weights, num_batches, global_step,
- summary_writer, summary_op):
- """Computes perplexity-per-word over the evaluation dataset.
-
- Summaries and perplexity-per-word are written out to the eval directory.
-
- Args:
- sess: Session object.
- losses: A Tensor of any shape; the target cross entropy losses for the
- current batch.
- weights: A Tensor of weights corresponding to losses.
- num_batches: Integer; the number of evaluation batches.
- global_step: Integer; global step of the model checkpoint.
- summary_writer: Instance of SummaryWriter.
- summary_op: Op for generating model summaries.
- """
- # Log model summaries on a single batch.
- summary_str = sess.run(summary_op)
- summary_writer.add_summary(summary_str, global_step)
-
- start_time = time.time()
- sum_losses = 0.0
- sum_weights = 0.0
- for i in range(num_batches):
- batch_losses, batch_weights = sess.run([losses, weights])
- sum_losses += np.sum(batch_losses * batch_weights)
- sum_weights += np.sum(batch_weights)
- if not i % 100:
- tf.logging.info("Computed losses for %d of %d batches.", i + 1,
- num_batches)
- eval_time = time.time() - start_time
-
- perplexity = math.exp(sum_losses / sum_weights)
- tf.logging.info("Perplexity = %f (%.2f sec)", perplexity, eval_time)
-
- # Log perplexity to the SummaryWriter.
- summary = tf.Summary()
- value = summary.value.add()
- value.simple_value = perplexity
- value.tag = "perplexity"
- summary_writer.add_summary(summary, global_step)
-
- # Write the Events file to the eval directory.
- summary_writer.flush()
- tf.logging.info("Finished processing evaluation at global step %d.",
- global_step)
-
-
-def run_once(model, losses, weights, saver, summary_writer, summary_op):
- """Evaluates the latest model checkpoint.
-
- Args:
- model: Instance of SkipThoughtsModel; the model to evaluate.
- losses: Tensor; the target cross entropy losses for the current batch.
- weights: A Tensor of weights corresponding to losses.
- saver: Instance of tf.train.Saver for restoring model Variables.
- summary_writer: Instance of FileWriter.
- summary_op: Op for generating model summaries.
- """
- model_path = tf.train.latest_checkpoint(FLAGS.checkpoint_dir)
- if not model_path:
- tf.logging.info("Skipping evaluation. No checkpoint found in: %s",
- FLAGS.checkpoint_dir)
- return
-
- with tf.Session() as sess:
- # Load model from checkpoint.
- tf.logging.info("Loading model from checkpoint: %s", model_path)
- saver.restore(sess, model_path)
- global_step = tf.train.global_step(sess, model.global_step.name)
- tf.logging.info("Successfully loaded %s at global step = %d.",
- os.path.basename(model_path), global_step)
- if global_step < FLAGS.min_global_step:
- tf.logging.info("Skipping evaluation. Global step = %d < %d", global_step,
- FLAGS.min_global_step)
- return
-
- # Start the queue runners.
- coord = tf.train.Coordinator()
- threads = tf.train.start_queue_runners(coord=coord)
-
- num_eval_batches = int(
- math.ceil(FLAGS.num_eval_examples / model.config.batch_size))
-
- # Run evaluation on the latest checkpoint.
- try:
- evaluate_model(sess, losses, weights, num_eval_batches, global_step,
- summary_writer, summary_op)
- except tf.InvalidArgumentError:
- tf.logging.error(
- "Evaluation raised InvalidArgumentError (e.g. due to Nans).")
- finally:
- coord.request_stop()
- coord.join(threads, stop_grace_period_secs=10)
-
-
-def main(unused_argv):
- if not FLAGS.input_file_pattern:
- raise ValueError("--input_file_pattern is required.")
- if not FLAGS.checkpoint_dir:
- raise ValueError("--checkpoint_dir is required.")
- if not FLAGS.eval_dir:
- raise ValueError("--eval_dir is required.")
-
- # Create the evaluation directory if it doesn't exist.
- eval_dir = FLAGS.eval_dir
- if not tf.gfile.IsDirectory(eval_dir):
- tf.logging.info("Creating eval directory: %s", eval_dir)
- tf.gfile.MakeDirs(eval_dir)
-
- g = tf.Graph()
- with g.as_default():
- # Build the model for evaluation.
- model_config = configuration.model_config(
- input_file_pattern=FLAGS.input_file_pattern,
- input_queue_capacity=FLAGS.num_eval_examples,
- shuffle_input_data=False)
- model = skip_thoughts_model.SkipThoughtsModel(model_config, mode="eval")
- model.build()
-
- losses = tf.concat(model.target_cross_entropy_losses, 0)
- weights = tf.concat(model.target_cross_entropy_loss_weights, 0)
-
- # Create the Saver to restore model Variables.
- saver = tf.train.Saver()
-
- # Create the summary operation and the summary writer.
- summary_op = tf.summary.merge_all()
- summary_writer = tf.summary.FileWriter(eval_dir)
-
- g.finalize()
-
- # Run a new evaluation run every eval_interval_secs.
- while True:
- start = time.time()
- tf.logging.info("Starting evaluation at " + time.strftime(
- "%Y-%m-%d-%H:%M:%S", time.localtime()))
- run_once(model, losses, weights, saver, summary_writer, summary_op)
- time_to_next_eval = start + FLAGS.eval_interval_secs - time.time()
- if time_to_next_eval > 0:
- time.sleep(time_to_next_eval)
-
-
-if __name__ == "__main__":
- tf.app.run()
diff --git a/research/skip_thoughts/skip_thoughts/train.py b/research/skip_thoughts/skip_thoughts/train.py
deleted file mode 100644
index 445f31c5a8fe9d1c6084ccacb2109449839f1bd5..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/skip_thoughts/train.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Train the skip-thoughts model."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-
-import tensorflow as tf
-
-from skip_thoughts import configuration
-from skip_thoughts import skip_thoughts_model
-
-FLAGS = tf.flags.FLAGS
-
-tf.flags.DEFINE_string("input_file_pattern", None,
- "File pattern of sharded TFRecord files containing "
- "tf.Example protos.")
-tf.flags.DEFINE_string("train_dir", None,
- "Directory for saving and loading checkpoints.")
-
-tf.logging.set_verbosity(tf.logging.INFO)
-
-
-def _setup_learning_rate(config, global_step):
- """Sets up the learning rate with optional exponential decay.
-
- Args:
- config: Object containing learning rate configuration parameters.
- global_step: Tensor; the global step.
-
- Returns:
- learning_rate: Tensor; the learning rate with exponential decay.
- """
- if config.learning_rate_decay_factor > 0:
- learning_rate = tf.train.exponential_decay(
- learning_rate=float(config.learning_rate),
- global_step=global_step,
- decay_steps=config.learning_rate_decay_steps,
- decay_rate=config.learning_rate_decay_factor,
- staircase=False)
- else:
- learning_rate = tf.constant(config.learning_rate)
- return learning_rate
-
-
-def main(unused_argv):
- if not FLAGS.input_file_pattern:
- raise ValueError("--input_file_pattern is required.")
- if not FLAGS.train_dir:
- raise ValueError("--train_dir is required.")
-
- model_config = configuration.model_config(
- input_file_pattern=FLAGS.input_file_pattern)
- training_config = configuration.training_config()
-
- tf.logging.info("Building training graph.")
- g = tf.Graph()
- with g.as_default():
- model = skip_thoughts_model.SkipThoughtsModel(model_config, mode="train")
- model.build()
-
- learning_rate = _setup_learning_rate(training_config, model.global_step)
- optimizer = tf.train.AdamOptimizer(learning_rate)
-
- train_tensor = tf.contrib.slim.learning.create_train_op(
- total_loss=model.total_loss,
- optimizer=optimizer,
- global_step=model.global_step,
- clip_gradient_norm=training_config.clip_gradient_norm)
-
- saver = tf.train.Saver()
-
- tf.contrib.slim.learning.train(
- train_op=train_tensor,
- logdir=FLAGS.train_dir,
- graph=g,
- global_step=model.global_step,
- number_of_steps=training_config.number_of_steps,
- save_summaries_secs=training_config.save_summaries_secs,
- saver=saver,
- save_interval_secs=training_config.save_model_secs)
-
-
-if __name__ == "__main__":
- tf.app.run()
diff --git a/research/skip_thoughts/skip_thoughts/vocabulary_expansion.py b/research/skip_thoughts/skip_thoughts/vocabulary_expansion.py
deleted file mode 100644
index 0d6c8e2bc227c4dd86e73fe9b00daafeffd4c2a5..0000000000000000000000000000000000000000
--- a/research/skip_thoughts/skip_thoughts/vocabulary_expansion.py
+++ /dev/null
@@ -1,203 +0,0 @@
-# Copyright 2017 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Compute an expanded vocabulary of embeddings using a word2vec model.
-
-This script loads the word embeddings from a trained skip-thoughts model and
-from a trained word2vec model (typically with a larger vocabulary). It trains a
-linear regression model without regularization to learn a linear mapping from
-the word2vec embedding space to the skip-thoughts embedding space. The model is
-then applied to all words in the word2vec vocabulary, yielding vectors in the
-skip-thoughts word embedding space for the union of the two vocabularies.
-
-The linear regression task is to learn a parameter matrix W to minimize
- || X - Y * W ||^2,
-where X is a matrix of skip-thoughts embeddings of shape [num_words, dim1],
-Y is a matrix of word2vec embeddings of shape [num_words, dim2], and W is a
-matrix of shape [dim2, dim1].
-
-This is based on the "Translation Matrix" method from the paper:
-
- "Exploiting Similarities among Languages for Machine Translation"
- Tomas Mikolov, Quoc V. Le, Ilya Sutskever
- https://arxiv.org/abs/1309.4168
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import collections
-import os.path
-
-
-import gensim.models
-import numpy as np
-import sklearn.linear_model
-import tensorflow as tf
-
-FLAGS = tf.flags.FLAGS
-
-tf.flags.DEFINE_string("skip_thoughts_model", None,
- "Checkpoint file or directory containing a checkpoint "
- "file.")
-
-tf.flags.DEFINE_string("skip_thoughts_vocab", None,
- "Path to vocabulary file containing a list of newline-"
- "separated words where the word id is the "
- "corresponding 0-based index in the file.")
-
-tf.flags.DEFINE_string("word2vec_model", None,
- "File containing a word2vec model in binary format.")
-
-tf.flags.DEFINE_string("output_dir", None, "Output directory.")
-
-tf.logging.set_verbosity(tf.logging.INFO)
-
-
-def _load_skip_thoughts_embeddings(checkpoint_path):
- """Loads the embedding matrix from a skip-thoughts model checkpoint.
-
- Args:
- checkpoint_path: Model checkpoint file or directory containing a checkpoint
- file.
-
- Returns:
- word_embedding: A numpy array of shape [vocab_size, embedding_dim].
-
- Raises:
- ValueError: If no checkpoint file matches checkpoint_path.
- """
- if tf.gfile.IsDirectory(checkpoint_path):
- checkpoint_file = tf.train.latest_checkpoint(checkpoint_path)
- if not checkpoint_file:
- raise ValueError("No checkpoint file found in %s" % checkpoint_path)
- else:
- checkpoint_file = checkpoint_path
-
- tf.logging.info("Loading skip-thoughts embedding matrix from %s",
- checkpoint_file)
- reader = tf.train.NewCheckpointReader(checkpoint_file)
- word_embedding = reader.get_tensor("word_embedding")
- tf.logging.info("Loaded skip-thoughts embedding matrix of shape %s",
- word_embedding.shape)
-
- return word_embedding
-
-
-def _load_vocabulary(filename):
- """Loads a vocabulary file.
-
- Args:
- filename: Path to text file containing newline-separated words.
-
- Returns:
- vocab: A dictionary mapping word to word id.
- """
- tf.logging.info("Reading vocabulary from %s", filename)
- vocab = collections.OrderedDict()
- with tf.gfile.GFile(filename, mode="rb") as f:
- for i, line in enumerate(f):
- word = line.decode("utf-8").strip()
- assert word not in vocab, "Attempting to add word twice: %s" % word
- vocab[word] = i
- tf.logging.info("Read vocabulary of size %d", len(vocab))
- return vocab
-
-
-def _expand_vocabulary(skip_thoughts_emb, skip_thoughts_vocab, word2vec):
- """Runs vocabulary expansion on a skip-thoughts model using a word2vec model.
-
- Args:
- skip_thoughts_emb: A numpy array of shape [skip_thoughts_vocab_size,
- skip_thoughts_embedding_dim].
- skip_thoughts_vocab: A dictionary of word to id.
- word2vec: An instance of gensim.models.Word2Vec.
-
- Returns:
- combined_emb: A dictionary mapping words to embedding vectors.
- """
- # Find words shared between the two vocabularies.
- tf.logging.info("Finding shared words")
- shared_words = [w for w in word2vec.vocab if w in skip_thoughts_vocab]
-
- # Select embedding vectors for shared words.
- tf.logging.info("Selecting embeddings for %d shared words", len(shared_words))
- shared_st_emb = skip_thoughts_emb[[
- skip_thoughts_vocab[w] for w in shared_words
- ]]
- shared_w2v_emb = word2vec[shared_words]
-
- # Train a linear regression model on the shared embedding vectors.
- tf.logging.info("Training linear regression model")
- model = sklearn.linear_model.LinearRegression()
- model.fit(shared_w2v_emb, shared_st_emb)
-
- # Create the expanded vocabulary.
- tf.logging.info("Creating embeddings for expanded vocabuary")
- combined_emb = collections.OrderedDict()
- for w in word2vec.vocab:
- # Ignore words with underscores (spaces).
- if "_" not in w:
- w_emb = model.predict(word2vec[w].reshape(1, -1))
- combined_emb[w] = w_emb.reshape(-1)
-
- for w in skip_thoughts_vocab:
- combined_emb[w] = skip_thoughts_emb[skip_thoughts_vocab[w]]
-
- tf.logging.info("Created expanded vocabulary of %d words", len(combined_emb))
-
- return combined_emb
-
-
-def main(unused_argv):
- if not FLAGS.skip_thoughts_model:
- raise ValueError("--skip_thoughts_model is required.")
- if not FLAGS.skip_thoughts_vocab:
- raise ValueError("--skip_thoughts_vocab is required.")
- if not FLAGS.word2vec_model:
- raise ValueError("--word2vec_model is required.")
- if not FLAGS.output_dir:
- raise ValueError("--output_dir is required.")
-
- if not tf.gfile.IsDirectory(FLAGS.output_dir):
- tf.gfile.MakeDirs(FLAGS.output_dir)
-
- # Load the skip-thoughts embeddings and vocabulary.
- skip_thoughts_emb = _load_skip_thoughts_embeddings(FLAGS.skip_thoughts_model)
- skip_thoughts_vocab = _load_vocabulary(FLAGS.skip_thoughts_vocab)
-
- # Load the Word2Vec model.
- word2vec = gensim.models.KeyedVectors.load_word2vec_format(
- FLAGS.word2vec_model, binary=True)
-
- # Run vocabulary expansion.
- embedding_map = _expand_vocabulary(skip_thoughts_emb, skip_thoughts_vocab,
- word2vec)
-
- # Save the output.
- vocab = embedding_map.keys()
- vocab_file = os.path.join(FLAGS.output_dir, "vocab.txt")
- with tf.gfile.GFile(vocab_file, "w") as f:
- f.write("\n".join(vocab))
- tf.logging.info("Wrote vocabulary file to %s", vocab_file)
-
- embeddings = np.array(embedding_map.values())
- embeddings_file = os.path.join(FLAGS.output_dir, "embeddings.npy")
- np.save(embeddings_file, embeddings)
- tf.logging.info("Wrote embeddings file to %s", embeddings_file)
-
-
-if __name__ == "__main__":
- tf.app.run()
diff --git a/research/steve/README.md b/research/steve/README.md
deleted file mode 100644
index 363be719efe76ac9b70913252ec949cf83bfd906..0000000000000000000000000000000000000000
--- a/research/steve/README.md
+++ /dev/null
@@ -1,94 +0,0 @@
-
-
-
-
-# Stochastic Ensemble Value Expansion
-
-*A hybrid model-based/model-free reinforcement learning algorithm for sample-efficient continuous control.*
-
-This is the code repository accompanying the paper Sample-Efficient Reinforcement Learning with
-Stochastic Ensemble Value Expansion, by Buckman et al. (2018).
-
-#### Abstract:
-Merging model-free and model-based approaches in reinforcement learning has the potential to achieve
-the high performance of model-free algorithms with low sample complexity. This is difficult because
-an imperfect dynamics model can degrade the performance of the learning algorithm, and in sufficiently
-complex environments, the dynamics model will always be imperfect. As a result, a key challenge is to
-combine model-based approaches with model-free learning in such a way that errors in the model do not
-degrade performance. We propose *stochastic ensemble value expansion* (STEVE), a novel model-based
-technique that addresses this issue. By dynamically interpolating between model rollouts of various horizon
-lengths for each individual example, STEVE ensures that the model is only utilized when doing so does not
-introduce significant errors. Our approach outperforms model-free baselines on challenging continuous
-control benchmarks with an order-of-magnitude increase in sample efficiency, and in contrast to previous
-model-based approaches, performance does not degrade as the environment gets more complex.
-
-## Installation
-This code is compatible with Ubuntu 16.04 and Python 2.7. There are several prerequisites:
-* Numpy, Scipy, and Portalocker: `pip install numpy scipy portalocker`
-* TensorFlow 1.6 or above. Instructions can be found on the official TensorFlow page:
- [https://www.tensorflow.org/install/install_linux](https://www.tensorflow.org/install/install_linux).
- We suggest installing the GPU version of TensorFlow to speed up training.
-* OpenAI Gym version 0.9.4. Instructions can be found in the OpenAI Gym repository:
- [https://github.com/openai/gym#installation](https://github.com/openai/gym#installation).
- Note that you need to replace "pip install gym[all]" with "pip install gym[all]==0.9.4", which
- will ensure that you get the correct version of Gym. (The current version of Gym has deprecated
- the -v1 MuJoCo environments, which are the environments studied in this paper.)
-* MuJoCo version 1.31, which can be downloaded here: [https://www.roboti.us/download/mjpro131_linux.zip](https://www.roboti.us/download/mjpro131_linux.zip).
- Simply run: ```
- cd ~; mkdir -p .mujoco; cd .mujoco/; wget https://www.roboti.us/download/mjpro131_linux.zip; unzip mjpro131_linux.zip```
- You also need to get a license, and put the license key in ~/.mujoco/ as well.
-* Optionally, Roboschool version 1.1. This is needed only to replicate the Roboschool experiments.
- Instructions can be found in the OpenAI Roboschool repository:
- [https://github.com/openai/roboschool#installation](https://github.com/openai/roboschool#installation).
-* Optionally, MoviePy to render trained agents. Instructions on the MoviePy homepage:
- [https://zulko.github.io/moviepy/install.html](https://zulko.github.io/moviepy/install.html).
-
-## Running Experiments
-To run an experiment, run master.py and pass in a config file and GPU ID. For example: ```
-python master.py config/experiments/speedruns/humanoid/speedy_steve0.json 0```
-The `config/experiments/`
-directory contains configuration files for all of the experiments run in the paper.
-
-The GPU ID specifies the GPU that should be used to learn the policy. For model-based approaches, the
-next GPU (i.e. GPU_ID+1) is used to learn the worldmodel in parallel.
-
-To resume an experiment that was interrupted, use the same config file and pass the `--resume` flag: ```
-python master.py config/experiments/speedruns/humanoid/speedy_steve0.json 0 --resume```
-
-## Output
-For each experiment, two folders are created in the output directory: `//log`
-and `//checkpoints`. The log directory contains the following:
-
-* `hps.json` contains the accumulated hyperparameters of the config file used to generate these results
-* `valuerl.log` and `worldmodel.log` contain the log output of the learners. `worldmodel.log` will not
- exist if you are not learning a worldmodel.
-* `.greedy.csv` records all of the scores of our evaluators. The four columns contain time (hours),
- epochs, frames, and score.
-
-The checkpoints directory contains the most recent versions of the policy and worldmodel, as well as checkpoints
-of the policy, worldmodel, and their respective replay buffers at various points throughout training.
-
-## Code Organization
-`master.py` launches four types of processes: a ValueRlLearner to learn the policy, a WorldmodelLearner
-to learn the dynamics model, several Interactors to gather data from the environment to train on, and
-a few Evaluators to run the greedy policy in the environment and record the score.
-
-`learner.py` contains a general framework for models which learn from a replay buffer. This is where
-most of the code for the overall training loop is located. `valuerl_learner.py` and `worldmodel_learner.py`
-contain a small amount of model-specific training loop code.
-
-`valuerl.py` implements the core model for all value-function-based policy learning techniques studied
-in the paper, including DDPG, MVE, STEVE, etc. Similarly, `worldmodel.py` contains the core model for
-our dynamics model and reward function.
-
-`replay.py` contains the code for the replay buffer. `nn.py`, `envwrap.py`, `config.py`, and `util.py`
-each contain various helper functions.
-
-`toy_demo.py` is a self-contained demo, written in numpy, that was used to generate the results for the
-toy examples in the first segment of the paper.
-
-`visualizer.py` is a utility script for loading trained policies and inspecting them. In addition to a
-config file and a GPU, it takes the filename of the model to load as a mandatory third argument.
-
-## Contact
-Please contact GitHub user buckman-google (jacobbuckman@gmail.com) with any questions.
diff --git a/research/steve/agent.py b/research/steve/agent.py
deleted file mode 100644
index 25069e29be1659fdd0f3a19e1a37bc41c9668b8b..0000000000000000000000000000000000000000
--- a/research/steve/agent.py
+++ /dev/null
@@ -1,143 +0,0 @@
-from __future__ import print_function
-from builtins import zip
-from builtins import range
-from builtins import object
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import numpy as np
-import tensorflow as tf
-import time, os, traceback, multiprocessing, portalocker
-
-import envwrap
-import valuerl
-import util
-from config import config
-
-
-def run_env(pipe):
- env = envwrap.get_env(config["env"]["name"])
- reset = True
- while True:
- if reset is True: pipe.send(env.reset())
- action = pipe.recv()
- obs, reward, done, reset = env.step(action)
- pipe.send((obs, reward, done, reset))
-
-class AgentManager(object):
- """
- Interact with the environment according to the learned policy,
- """
- def __init__(self, proc_num, evaluation, policy_lock, batch_size, config):
- self.evaluation = evaluation
- self.policy_lock = policy_lock
- self.batch_size = batch_size
- self.config = config
-
- self.log_path = util.create_directory("%s/%s/%s/%s" % (config["output_root"], config["env"]["name"], config["name"], config["log_path"])) + "/%s" % config["name"]
- self.load_path = util.create_directory("%s/%s/%s/%s" % (config["output_root"], config["env"]["name"], config["name"], config["save_model_path"]))
-
- ## placeholders for intermediate states (basis for rollout)
- self.obs_loader = tf.placeholder(tf.float32, [self.batch_size, np.prod(self.config["env"]["obs_dims"])])
-
- ## build model
- self.valuerl = valuerl.ValueRL(self.config["name"], self.config["env"], self.config["policy_config"])
- self.policy_actions = self.valuerl.build_evalution_graph(self.obs_loader, mode="exploit" if self.evaluation else "explore")
-
- # interactors
- self.agent_pipes, self.agent_child_pipes = list(zip(*[multiprocessing.Pipe() for _ in range(self.batch_size)]))
- self.agents = [multiprocessing.Process(target=run_env, args=(self.agent_child_pipes[i],)) for i in range(self.batch_size)]
- for agent in self.agents: agent.start()
- self.obs = [pipe.recv() for pipe in self.agent_pipes]
- self.total_rewards = [0. for _ in self.agent_pipes]
- self.loaded_policy = False
-
- self.sess = tf.Session()
- self.sess.run(tf.global_variables_initializer())
-
- self.rollout_i = 0
- self.proc_num = proc_num
- self.epoch = -1
- self.frame_total = 0
- self.hours = 0.
-
- self.first = True
-
- def get_action(self, obs):
- if self.loaded_policy:
- all_actions = self.sess.run(self.policy_actions, feed_dict={self.obs_loader: obs})
- all_actions = np.clip(all_actions, -1., 1.)
- return all_actions[:self.batch_size]
- else:
- return [self.get_random_action() for _ in range(obs.shape[0])]
-
- def get_random_action(self, *args, **kwargs):
- return np.random.random(self.config["env"]["action_dim"]) * 2 - 1
-
- def step(self):
- actions = self.get_action(np.stack(self.obs))
- self.first = False
- [pipe.send(action) for pipe, action in zip(self.agent_pipes, actions)]
- next_obs, rewards, dones, resets = list(zip(*[pipe.recv() for pipe in self.agent_pipes]))
-
- frames = list(zip(self.obs, next_obs, actions, rewards, dones))
-
- self.obs = [o if resets[i] is False else self.agent_pipes[i].recv() for i, o in enumerate(next_obs)]
-
- for i, (t,r,reset) in enumerate(zip(self.total_rewards, rewards, resets)):
- if reset:
- self.total_rewards[i] = 0.
- if self.evaluation and self.loaded_policy:
- with portalocker.Lock(self.log_path+'.greedy.csv', mode="a") as f: f.write("%2f,%d,%d,%2f\n" % (self.hours, self.epoch, self.frame_total, t+r))
-
- else:
- self.total_rewards[i] = t + r
-
- if self.evaluation and np.any(resets): self.reload()
-
- self.rollout_i += 1
- return frames
-
- def reload(self):
- if not os.path.exists("%s/%s.params.index" % (self.load_path ,self.valuerl.saveid)): return False
- with self.policy_lock:
- self.valuerl.load(self.sess, self.load_path)
- self.epoch, self.frame_total, self.hours = self.sess.run([self.valuerl.epoch_n, self.valuerl.frame_n, self.valuerl.hours])
- self.loaded_policy = True
- self.first = True
- return True
-
-def main(proc_num, evaluation, policy_replay_frame_queue, model_replay_frame_queue, policy_lock, config):
- try:
- np.random.seed((proc_num * int(time.time())) % (2 ** 32 - 1))
- agentmanager = AgentManager(proc_num, evaluation, policy_lock, config["evaluator_config"]["batch_size"] if evaluation else config["agent_config"]["batch_size"], config)
- frame_i = 0
- while True:
- new_frames = agentmanager.step()
- if not evaluation:
- policy_replay_frame_queue.put(new_frames)
- if model_replay_frame_queue is not None: model_replay_frame_queue.put(new_frames)
- if frame_i % config["agent_config"]["reload_every_n"] == 0: agentmanager.reload()
- frame_i += len(new_frames)
-
- except Exception as e:
- print('Caught exception in agent process %d' % proc_num)
- traceback.print_exc()
- print()
- try:
- for i in agentmanager.agents: i.join()
- except:
- pass
- raise e
diff --git a/research/steve/config.py b/research/steve/config.py
deleted file mode 100644
index 4a6da98c375e9e78e2f4ffd63c70c66b09ad1631..0000000000000000000000000000000000000000
--- a/research/steve/config.py
+++ /dev/null
@@ -1,38 +0,0 @@
-from __future__ import print_function
-from builtins import str
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import argparse, json, util, traceback
-
-parser = argparse.ArgumentParser()
-parser.add_argument("config")
-parser.add_argument("root_gpu", type=int)
-parser.add_argument("--resume", action="store_true")
-args = parser.parse_args()
-
-config_loc = args.config
-config = util.ConfigDict(config_loc)
-
-config["name"] = config_loc.split("/")[-1][:-5]
-config["resume"] = args.resume
-
-cstr = str(config)
-
-def log_config():
- HPS_PATH = util.create_directory("output/" + config["env"]["name"] + "/" + config["name"] + "/" + config["log_path"]) + "/hps.json"
- print("ROOT GPU: " + str(args.root_gpu) + "\n" + str(cstr))
- with open(HPS_PATH, "w") as f:
- f.write("ROOT GPU: " + str(args.root_gpu) + "\n" + str(cstr))
\ No newline at end of file
diff --git a/research/steve/config/algos/ddpg.json b/research/steve/config/algos/ddpg.json
deleted file mode 100644
index e76c106986dc46b1fb37697eafff0965390e2061..0000000000000000000000000000000000000000
--- a/research/steve/config/algos/ddpg.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "inherits": ["config/core/basic.json"]
-}
\ No newline at end of file
diff --git a/research/steve/config/algos/mve_mean.json b/research/steve/config/algos/mve_mean.json
deleted file mode 100644
index 729bccc62efe4549041af8bdf13df17c1cebe78e..0000000000000000000000000000000000000000
--- a/research/steve/config/algos/mve_mean.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "inherits": [
- "config/core/basic.json",
- "config/core/model.json"
- ],
- "updates":{
- "policy_config": {
- "value_expansion": {
- "rollout_len": 3,
- "mean_k_return": true
- }
- }
- }
-}
\ No newline at end of file
diff --git a/research/steve/config/algos/mve_tdk.json b/research/steve/config/algos/mve_tdk.json
deleted file mode 100644
index 222fd40c3c928c4a26d0082797e9337e6edf45d2..0000000000000000000000000000000000000000
--- a/research/steve/config/algos/mve_tdk.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "inherits": [
- "config/core/basic.json",
- "config/core/model.json"
- ],
- "updates":{
- "policy_config": {
- "value_expansion": {
- "rollout_len": 3,
- "tdk_trick": true
- }
- }
- }
-}
\ No newline at end of file
diff --git a/research/steve/config/algos/mve_tdlambda.json b/research/steve/config/algos/mve_tdlambda.json
deleted file mode 100644
index 3414dda5d00aedce9673643e4b3d9911facde24d..0000000000000000000000000000000000000000
--- a/research/steve/config/algos/mve_tdlambda.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "inherits": [
- "config/core/basic.json",
- "config/core/model.json"
- ],
- "updates":{
- "policy_config": {
- "value_expansion": {
- "rollout_len": 3,
- "lambda_return": 0.25
- }
- }
- }
-}
\ No newline at end of file
diff --git a/research/steve/config/algos/steve.json b/research/steve/config/algos/steve.json
deleted file mode 100644
index ca2bc0395f98eda6ce2460fc79014492bb771589..0000000000000000000000000000000000000000
--- a/research/steve/config/algos/steve.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
- "inherits": [
- "config/core/basic.json",
- "config/core/model.json",
- "config/core/bayesian.json"
- ],
- "updates":{
- "policy_config": {
- "value_expansion": {
- "rollout_len": 3,
- "steve_reweight": true
- }
- }
- }
-}
\ No newline at end of file
diff --git a/research/steve/config/algos/steve_cov.json b/research/steve/config/algos/steve_cov.json
deleted file mode 100644
index 4dbf46e19c13f479af4a2ea132b4019a991144a7..0000000000000000000000000000000000000000
--- a/research/steve/config/algos/steve_cov.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "inherits": [
- "config/core/basic.json",
- "config/core/model.json",
- "config/core/bayesian.json"
- ],
- "updates":{
- "policy_config": {
- "value_expansion": {
- "rollout_len": 3,
- "steve_reweight": true,
- "covariances": true
- }
- }
- }
-}
\ No newline at end of file
diff --git a/research/steve/config/core/basic.json b/research/steve/config/core/basic.json
deleted file mode 100644
index 411e7b65e5303bf28c1a99b9dd0442575b6be74c..0000000000000000000000000000000000000000
--- a/research/steve/config/core/basic.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "updates": {
- "output_root": "output",
- "save_model_path": "checkpoints",
- "log_path": "log",
-
- "agent_config": {
- "count": 1,
- "batch_size": 8,
- "reload_every_n": 1,
- "full_random_n": 10000
- },
-
- "evaluator_config": {
- "count": 2,
- "batch_size": 1
- },
-
- "policy_config": {
- "algo": "ddpg",
- "hidden_dim": 128,
- "explore_chance": 0.05,
- "batch_size": 512,
- "replay_size": 1000000,
- "frames_before_learning": 10000,
- "log_every_n": 500,
- "epoch_every_n": 500,
- "backup_every_n": 2500000,
- "frames_per_update": 0.25
- }
- }
-}
\ No newline at end of file
diff --git a/research/steve/config/core/bayesian.json b/research/steve/config/core/bayesian.json
deleted file mode 100644
index ea7d955434c51c91376325ad7791836f59931086..0000000000000000000000000000000000000000
--- a/research/steve/config/core/bayesian.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "updates": {
- "policy_config": {
- "bayesian": {
- "ensemble_size": 4,
- "train_sample_count": 4,
- "eval_sample_count": 4
- }
- },
-
- "*model_config": {
- "bayesian": {
- "transition": {
- "ensemble_size": 4,
- "train_sample_count": 4,
- "eval_sample_count": 4
- },
- "reward": {
- "ensemble_size": 4,
- "train_sample_count": 4,
- "eval_sample_count": 4
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/research/steve/config/core/model.json b/research/steve/config/core/model.json
deleted file mode 100644
index 485146ab0242fde093796b8c920a33aed0baaf48..0000000000000000000000000000000000000000
--- a/research/steve/config/core/model.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
- "updates": {
- "model_config": {
- "transition_hidden_dim": 512,
- "aux_hidden_dim": 128,
- "batch_size": 512,
- "replay_size": 1000000,
- "frames_before_learning": 10000,
- "log_every_n": 500,
- "epoch_every_n": 500,
- "backup_every_n": 2500000,
- "pretrain_n": 10000,
- "frames_per_update": 0.25
- }
- }
-}
\ No newline at end of file
diff --git a/research/steve/config/envs/flagrun.json b/research/steve/config/envs/flagrun.json
deleted file mode 100644
index 09ecc7cdeb893dbe5e1ee1d264848768689b60e0..0000000000000000000000000000000000000000
--- a/research/steve/config/envs/flagrun.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "updates": {
- "env": {
- "name": "RoboschoolHumanoidFlagrun-v1",
- "obs_dims": [44],
- "action_dim": 17,
- "reward_scale":1.0,
- "discount":0.99,
- "max_frames": 1000
- }
- }
-}
\ No newline at end of file
diff --git a/research/steve/config/envs/halfcheetah.json b/research/steve/config/envs/halfcheetah.json
deleted file mode 100644
index e0c9b38971d49b27071d8fd875f40ba391e77fbf..0000000000000000000000000000000000000000
--- a/research/steve/config/envs/halfcheetah.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "updates": {
- "env": {
- "name": "HalfCheetah-v1",
- "obs_dims": [17],
- "action_dim": 6,
- "reward_scale":1.0,
- "discount":0.99,
- "max_frames": 1000
- }
- }
-}
\ No newline at end of file
diff --git a/research/steve/config/envs/hardcore.json b/research/steve/config/envs/hardcore.json
deleted file mode 100644
index af372b28b689422e7ff0e2ccd1d3809f4712cb08..0000000000000000000000000000000000000000
--- a/research/steve/config/envs/hardcore.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "updates": {
- "env": {
- "name": "BipedalWalkerHardcore-v2",
- "obs_dims": [24],
- "action_dim": 4,
- "reward_scale":1.0,
- "discount":0.99,
- "max_frames": 1000
- }
- }
-}
\ No newline at end of file
diff --git a/research/steve/config/envs/hopper.json b/research/steve/config/envs/hopper.json
deleted file mode 100644
index 012def18593b98bdc7978e532d758d59cc3dbb4d..0000000000000000000000000000000000000000
--- a/research/steve/config/envs/hopper.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "updates": {
- "env": {
- "name": "Hopper-v1",
- "obs_dims": [11],
- "action_dim": 3,
- "reward_scale":1.0,
- "discount":0.99,
- "max_frames": 1000
- }
- }
-}
\ No newline at end of file
diff --git a/research/steve/config/envs/humanoid.json b/research/steve/config/envs/humanoid.json
deleted file mode 100644
index 39aeeb29517a255b9c241c9b7fd37e6870b85bba..0000000000000000000000000000000000000000
--- a/research/steve/config/envs/humanoid.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "updates": {
- "env": {
- "name": "Humanoid-v1",
- "obs_dims": [376],
- "action_dim": 17,
- "reward_scale":1.0,
- "discount":0.99,
- "max_frames": 1000
- }
- }
-}
\ No newline at end of file
diff --git a/research/steve/config/envs/rshum.json b/research/steve/config/envs/rshum.json
deleted file mode 100644
index 0ad54b2bfc3087643156b2b855eb5dbd5202ef77..0000000000000000000000000000000000000000
--- a/research/steve/config/envs/rshum.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "updates": {
- "env": {
- "name": "RoboschoolHumanoid-v1",
- "obs_dims": [44],
- "action_dim": 17,
- "reward_scale":1.0,
- "discount":0.99,
- "max_frames": 1000
- }
- }
-}
\ No newline at end of file
diff --git a/research/steve/config/envs/swimmer.json b/research/steve/config/envs/swimmer.json
deleted file mode 100644
index 0fcf2f32e793dbbb61981b5a9bdd0b4636fcd636..0000000000000000000000000000000000000000
--- a/research/steve/config/envs/swimmer.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "updates": {
- "env": {
- "name": "Swimmer-v1",
- "obs_dims": [8],
- "action_dim": 2,
- "reward_scale":1.0,
- "discount":0.99,
- "max_frames": 1000
- }
- }
-}
\ No newline at end of file
diff --git a/research/steve/config/envs/walker2d.json b/research/steve/config/envs/walker2d.json
deleted file mode 100644
index 03ed94f7466069f7c7ec1f1fc2e5c8f1be3b398b..0000000000000000000000000000000000000000
--- a/research/steve/config/envs/walker2d.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "updates": {
- "env": {
- "name": "Walker2d-v1",
- "obs_dims": [17],
- "action_dim": 6,
- "reward_scale":1.0,
- "discount":0.99,
- "max_frames": 1000
- }
- }
-}
\ No newline at end of file
diff --git a/research/steve/config/experimental_setups/speedrun.json b/research/steve/config/experimental_setups/speedrun.json
deleted file mode 100644
index b34a9b706f919bffb58edc3345995112905d7ef3..0000000000000000000000000000000000000000
--- a/research/steve/config/experimental_setups/speedrun.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "updates": {
- "policy_config": {
- "frames_per_update": false
- },
- "*model_config":{
- "frames_per_update": false,
- "pretrain_n": false
- }
- }
-}
\ No newline at end of file
diff --git a/research/steve/config/experiments/ablations/baselines/ensemble_mve_tdk0.json b/research/steve/config/experiments/ablations/baselines/ensemble_mve_tdk0.json
deleted file mode 100644
index da54f6310d2d3920b5b7dc2b121c5b81dee5fd99..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/baselines/ensemble_mve_tdk0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/core/bayesian", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/ablations/baselines/ensemble_mve_tdk1.json b/research/steve/config/experiments/ablations/baselines/ensemble_mve_tdk1.json
deleted file mode 100644
index da54f6310d2d3920b5b7dc2b121c5b81dee5fd99..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/baselines/ensemble_mve_tdk1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/core/bayesian", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/ablations/baselines/ensemble_mve_tdk2.json b/research/steve/config/experiments/ablations/baselines/ensemble_mve_tdk2.json
deleted file mode 100644
index da54f6310d2d3920b5b7dc2b121c5b81dee5fd99..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/baselines/ensemble_mve_tdk2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/core/bayesian", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/ablations/baselines/mve_25tdlambda0.json b/research/steve/config/experiments/ablations/baselines/mve_25tdlambda0.json
deleted file mode 100644
index b9e3dcd4bcecddaac7f11c1547e522dae720fe0e..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/baselines/mve_25tdlambda0.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "inherits": ["config/algos/mve_tdlambda.json", "config/envs/humanoid.json"],
- "updates":{
- "policy_config": {
- "value_expansion": {
- "lambda_return": 0.25
- }
- }
- }
-}
diff --git a/research/steve/config/experiments/ablations/baselines/mve_25tdlambda1.json b/research/steve/config/experiments/ablations/baselines/mve_25tdlambda1.json
deleted file mode 100644
index b9e3dcd4bcecddaac7f11c1547e522dae720fe0e..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/baselines/mve_25tdlambda1.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "inherits": ["config/algos/mve_tdlambda.json", "config/envs/humanoid.json"],
- "updates":{
- "policy_config": {
- "value_expansion": {
- "lambda_return": 0.25
- }
- }
- }
-}
diff --git a/research/steve/config/experiments/ablations/baselines/mve_25tdlambda2.json b/research/steve/config/experiments/ablations/baselines/mve_25tdlambda2.json
deleted file mode 100644
index b9e3dcd4bcecddaac7f11c1547e522dae720fe0e..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/baselines/mve_25tdlambda2.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "inherits": ["config/algos/mve_tdlambda.json", "config/envs/humanoid.json"],
- "updates":{
- "policy_config": {
- "value_expansion": {
- "lambda_return": 0.25
- }
- }
- }
-}
diff --git a/research/steve/config/experiments/ablations/baselines/mve_75tdlambda0.json b/research/steve/config/experiments/ablations/baselines/mve_75tdlambda0.json
deleted file mode 100644
index 7366ba77b4df755e819b4701d6bb2923fc1516dc..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/baselines/mve_75tdlambda0.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "inherits": ["config/algos/mve_tdlambda.json", "config/envs/humanoid.json"],
- "updates":{
- "policy_config": {
- "value_expansion": {
- "lambda_return": 0.75
- }
- }
- }
-}
diff --git a/research/steve/config/experiments/ablations/baselines/mve_75tdlambda1.json b/research/steve/config/experiments/ablations/baselines/mve_75tdlambda1.json
deleted file mode 100644
index 7366ba77b4df755e819b4701d6bb2923fc1516dc..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/baselines/mve_75tdlambda1.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "inherits": ["config/algos/mve_tdlambda.json", "config/envs/humanoid.json"],
- "updates":{
- "policy_config": {
- "value_expansion": {
- "lambda_return": 0.75
- }
- }
- }
-}
diff --git a/research/steve/config/experiments/ablations/baselines/mve_75tdlambda2.json b/research/steve/config/experiments/ablations/baselines/mve_75tdlambda2.json
deleted file mode 100644
index 7366ba77b4df755e819b4701d6bb2923fc1516dc..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/baselines/mve_75tdlambda2.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "inherits": ["config/algos/mve_tdlambda.json", "config/envs/humanoid.json"],
- "updates":{
- "policy_config": {
- "value_expansion": {
- "lambda_return": 0.75
- }
- }
- }
-}
diff --git a/research/steve/config/experiments/ablations/baselines/mve_meank0.json b/research/steve/config/experiments/ablations/baselines/mve_meank0.json
deleted file mode 100644
index ce7d9b1ea4fb0742f8947f1a54115ea5704c5a7e..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/baselines/mve_meank0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_mean.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/ablations/baselines/mve_meank1.json b/research/steve/config/experiments/ablations/baselines/mve_meank1.json
deleted file mode 100644
index ce7d9b1ea4fb0742f8947f1a54115ea5704c5a7e..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/baselines/mve_meank1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_mean.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/ablations/baselines/mve_meank2.json b/research/steve/config/experiments/ablations/baselines/mve_meank2.json
deleted file mode 100644
index ce7d9b1ea4fb0742f8947f1a54115ea5704c5a7e..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/baselines/mve_meank2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_mean.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/ablations/baselines/steve_cov0.json b/research/steve/config/experiments/ablations/baselines/steve_cov0.json
deleted file mode 100644
index df2e8a0d8f8785200fd53fff4580fc12fe657c8f..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/baselines/steve_cov0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve_cov.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/ablations/baselines/steve_cov1.json b/research/steve/config/experiments/ablations/baselines/steve_cov1.json
deleted file mode 100644
index df2e8a0d8f8785200fd53fff4580fc12fe657c8f..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/baselines/steve_cov1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve_cov.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/ablations/baselines/steve_cov2.json b/research/steve/config/experiments/ablations/baselines/steve_cov2.json
deleted file mode 100644
index df2e8a0d8f8785200fd53fff4580fc12fe657c8f..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/baselines/steve_cov2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve_cov.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/ablations/horizons/steve_1h0.json b/research/steve/config/experiments/ablations/horizons/steve_1h0.json
deleted file mode 100644
index 48b6730b7a0f2ae9777d1f06efdb9789a94f43b0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/horizons/steve_1h0.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "inherits": ["config/algos/steve.json", "config/envs/humanoid.json"],
- "updates": {
- "policy_config": {
- "value_expansion": {
- "rollout_len": 1
- }
- }
- }
-}
diff --git a/research/steve/config/experiments/ablations/horizons/steve_1h1.json b/research/steve/config/experiments/ablations/horizons/steve_1h1.json
deleted file mode 100644
index 48b6730b7a0f2ae9777d1f06efdb9789a94f43b0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/horizons/steve_1h1.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "inherits": ["config/algos/steve.json", "config/envs/humanoid.json"],
- "updates": {
- "policy_config": {
- "value_expansion": {
- "rollout_len": 1
- }
- }
- }
-}
diff --git a/research/steve/config/experiments/ablations/horizons/steve_1h2.json b/research/steve/config/experiments/ablations/horizons/steve_1h2.json
deleted file mode 100644
index 48b6730b7a0f2ae9777d1f06efdb9789a94f43b0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/horizons/steve_1h2.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "inherits": ["config/algos/steve.json", "config/envs/humanoid.json"],
- "updates": {
- "policy_config": {
- "value_expansion": {
- "rollout_len": 1
- }
- }
- }
-}
diff --git a/research/steve/config/experiments/ablations/horizons/steve_2h0.json b/research/steve/config/experiments/ablations/horizons/steve_2h0.json
deleted file mode 100644
index 48b6730b7a0f2ae9777d1f06efdb9789a94f43b0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/horizons/steve_2h0.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "inherits": ["config/algos/steve.json", "config/envs/humanoid.json"],
- "updates": {
- "policy_config": {
- "value_expansion": {
- "rollout_len": 1
- }
- }
- }
-}
diff --git a/research/steve/config/experiments/ablations/horizons/steve_2h1.json b/research/steve/config/experiments/ablations/horizons/steve_2h1.json
deleted file mode 100644
index 48b6730b7a0f2ae9777d1f06efdb9789a94f43b0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/horizons/steve_2h1.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "inherits": ["config/algos/steve.json", "config/envs/humanoid.json"],
- "updates": {
- "policy_config": {
- "value_expansion": {
- "rollout_len": 1
- }
- }
- }
-}
diff --git a/research/steve/config/experiments/ablations/horizons/steve_2h2.json b/research/steve/config/experiments/ablations/horizons/steve_2h2.json
deleted file mode 100644
index 48b6730b7a0f2ae9777d1f06efdb9789a94f43b0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/horizons/steve_2h2.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "inherits": ["config/algos/steve.json", "config/envs/humanoid.json"],
- "updates": {
- "policy_config": {
- "value_expansion": {
- "rollout_len": 1
- }
- }
- }
-}
diff --git a/research/steve/config/experiments/ablations/horizons/steve_5h0.json b/research/steve/config/experiments/ablations/horizons/steve_5h0.json
deleted file mode 100644
index 48b6730b7a0f2ae9777d1f06efdb9789a94f43b0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/horizons/steve_5h0.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "inherits": ["config/algos/steve.json", "config/envs/humanoid.json"],
- "updates": {
- "policy_config": {
- "value_expansion": {
- "rollout_len": 1
- }
- }
- }
-}
diff --git a/research/steve/config/experiments/ablations/horizons/steve_5h1.json b/research/steve/config/experiments/ablations/horizons/steve_5h1.json
deleted file mode 100644
index 48b6730b7a0f2ae9777d1f06efdb9789a94f43b0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/horizons/steve_5h1.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "inherits": ["config/algos/steve.json", "config/envs/humanoid.json"],
- "updates": {
- "policy_config": {
- "value_expansion": {
- "rollout_len": 1
- }
- }
- }
-}
diff --git a/research/steve/config/experiments/ablations/horizons/steve_5h2.json b/research/steve/config/experiments/ablations/horizons/steve_5h2.json
deleted file mode 100644
index 48b6730b7a0f2ae9777d1f06efdb9789a94f43b0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/ablations/horizons/steve_5h2.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "inherits": ["config/algos/steve.json", "config/envs/humanoid.json"],
- "updates": {
- "policy_config": {
- "value_expansion": {
- "rollout_len": 1
- }
- }
- }
-}
diff --git a/research/steve/config/experiments/goodruns/flagrun/ddpg0.json b/research/steve/config/experiments/goodruns/flagrun/ddpg0.json
deleted file mode 100644
index a68ee412d11e75821f21d49664977ff0ebc539a7..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/flagrun/ddpg0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/flagrun.json"]}
diff --git a/research/steve/config/experiments/goodruns/flagrun/ddpg1.json b/research/steve/config/experiments/goodruns/flagrun/ddpg1.json
deleted file mode 100644
index a68ee412d11e75821f21d49664977ff0ebc539a7..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/flagrun/ddpg1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/flagrun.json"]}
diff --git a/research/steve/config/experiments/goodruns/flagrun/ddpg2.json b/research/steve/config/experiments/goodruns/flagrun/ddpg2.json
deleted file mode 100644
index a68ee412d11e75821f21d49664977ff0ebc539a7..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/flagrun/ddpg2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/flagrun.json"]}
diff --git a/research/steve/config/experiments/goodruns/flagrun/ddpg3.json b/research/steve/config/experiments/goodruns/flagrun/ddpg3.json
deleted file mode 100644
index a68ee412d11e75821f21d49664977ff0ebc539a7..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/flagrun/ddpg3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/flagrun.json"]}
diff --git a/research/steve/config/experiments/goodruns/flagrun/mve_tdk0.json b/research/steve/config/experiments/goodruns/flagrun/mve_tdk0.json
deleted file mode 100644
index 8da85dd375077521f25f6b4f9d0926cf4d8b66b0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/flagrun/mve_tdk0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/flagrun.json"]}
diff --git a/research/steve/config/experiments/goodruns/flagrun/mve_tdk1.json b/research/steve/config/experiments/goodruns/flagrun/mve_tdk1.json
deleted file mode 100644
index 8da85dd375077521f25f6b4f9d0926cf4d8b66b0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/flagrun/mve_tdk1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/flagrun.json"]}
diff --git a/research/steve/config/experiments/goodruns/flagrun/mve_tdk2.json b/research/steve/config/experiments/goodruns/flagrun/mve_tdk2.json
deleted file mode 100644
index 8da85dd375077521f25f6b4f9d0926cf4d8b66b0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/flagrun/mve_tdk2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/flagrun.json"]}
diff --git a/research/steve/config/experiments/goodruns/flagrun/mve_tdk3.json b/research/steve/config/experiments/goodruns/flagrun/mve_tdk3.json
deleted file mode 100644
index 8da85dd375077521f25f6b4f9d0926cf4d8b66b0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/flagrun/mve_tdk3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/flagrun.json"]}
diff --git a/research/steve/config/experiments/goodruns/flagrun/steve0.json b/research/steve/config/experiments/goodruns/flagrun/steve0.json
deleted file mode 100644
index 21d32930224e1e0632e88646654892a2229ab90b..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/flagrun/steve0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/flagrun.json"]}
diff --git a/research/steve/config/experiments/goodruns/flagrun/steve1.json b/research/steve/config/experiments/goodruns/flagrun/steve1.json
deleted file mode 100644
index 21d32930224e1e0632e88646654892a2229ab90b..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/flagrun/steve1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/flagrun.json"]}
diff --git a/research/steve/config/experiments/goodruns/flagrun/steve2.json b/research/steve/config/experiments/goodruns/flagrun/steve2.json
deleted file mode 100644
index 21d32930224e1e0632e88646654892a2229ab90b..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/flagrun/steve2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/flagrun.json"]}
diff --git a/research/steve/config/experiments/goodruns/flagrun/steve3.json b/research/steve/config/experiments/goodruns/flagrun/steve3.json
deleted file mode 100644
index 21d32930224e1e0632e88646654892a2229ab90b..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/flagrun/steve3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/flagrun.json"]}
diff --git a/research/steve/config/experiments/goodruns/halfcheetah/ddpg0.json b/research/steve/config/experiments/goodruns/halfcheetah/ddpg0.json
deleted file mode 100644
index fc9d9eef28dfd4d631e41a9f4aeb625c66af27d0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/halfcheetah/ddpg0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/halfcheetah.json"]}
diff --git a/research/steve/config/experiments/goodruns/halfcheetah/ddpg1.json b/research/steve/config/experiments/goodruns/halfcheetah/ddpg1.json
deleted file mode 100644
index fc9d9eef28dfd4d631e41a9f4aeb625c66af27d0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/halfcheetah/ddpg1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/halfcheetah.json"]}
diff --git a/research/steve/config/experiments/goodruns/halfcheetah/ddpg2.json b/research/steve/config/experiments/goodruns/halfcheetah/ddpg2.json
deleted file mode 100644
index fc9d9eef28dfd4d631e41a9f4aeb625c66af27d0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/halfcheetah/ddpg2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/halfcheetah.json"]}
diff --git a/research/steve/config/experiments/goodruns/halfcheetah/ddpg3.json b/research/steve/config/experiments/goodruns/halfcheetah/ddpg3.json
deleted file mode 100644
index fc9d9eef28dfd4d631e41a9f4aeb625c66af27d0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/halfcheetah/ddpg3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/halfcheetah.json"]}
diff --git a/research/steve/config/experiments/goodruns/halfcheetah/mve_tdk0.json b/research/steve/config/experiments/goodruns/halfcheetah/mve_tdk0.json
deleted file mode 100644
index dcae7eb48df84194e6cc7dfb6c29a5000f2c5a8a..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/halfcheetah/mve_tdk0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/halfcheetah.json"]}
diff --git a/research/steve/config/experiments/goodruns/halfcheetah/mve_tdk1.json b/research/steve/config/experiments/goodruns/halfcheetah/mve_tdk1.json
deleted file mode 100644
index dcae7eb48df84194e6cc7dfb6c29a5000f2c5a8a..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/halfcheetah/mve_tdk1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/halfcheetah.json"]}
diff --git a/research/steve/config/experiments/goodruns/halfcheetah/mve_tdk2.json b/research/steve/config/experiments/goodruns/halfcheetah/mve_tdk2.json
deleted file mode 100644
index dcae7eb48df84194e6cc7dfb6c29a5000f2c5a8a..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/halfcheetah/mve_tdk2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/halfcheetah.json"]}
diff --git a/research/steve/config/experiments/goodruns/halfcheetah/mve_tdk3.json b/research/steve/config/experiments/goodruns/halfcheetah/mve_tdk3.json
deleted file mode 100644
index dcae7eb48df84194e6cc7dfb6c29a5000f2c5a8a..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/halfcheetah/mve_tdk3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/halfcheetah.json"]}
diff --git a/research/steve/config/experiments/goodruns/halfcheetah/steve0.json b/research/steve/config/experiments/goodruns/halfcheetah/steve0.json
deleted file mode 100644
index f2fd36d3bbf79a94bf241a2ac394a8a3652b5ad3..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/halfcheetah/steve0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/halfcheetah.json"]}
diff --git a/research/steve/config/experiments/goodruns/halfcheetah/steve1.json b/research/steve/config/experiments/goodruns/halfcheetah/steve1.json
deleted file mode 100644
index f2fd36d3bbf79a94bf241a2ac394a8a3652b5ad3..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/halfcheetah/steve1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/halfcheetah.json"]}
diff --git a/research/steve/config/experiments/goodruns/halfcheetah/steve2.json b/research/steve/config/experiments/goodruns/halfcheetah/steve2.json
deleted file mode 100644
index f2fd36d3bbf79a94bf241a2ac394a8a3652b5ad3..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/halfcheetah/steve2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/halfcheetah.json"]}
diff --git a/research/steve/config/experiments/goodruns/halfcheetah/steve3.json b/research/steve/config/experiments/goodruns/halfcheetah/steve3.json
deleted file mode 100644
index f2fd36d3bbf79a94bf241a2ac394a8a3652b5ad3..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/halfcheetah/steve3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/halfcheetah.json"]}
diff --git a/research/steve/config/experiments/goodruns/hardcore/ddpg0.json b/research/steve/config/experiments/goodruns/hardcore/ddpg0.json
deleted file mode 100644
index 3dce87b15ce8079953529c417e0c25c30a734ca2..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hardcore/ddpg0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/hardcore.json"]}
diff --git a/research/steve/config/experiments/goodruns/hardcore/ddpg1.json b/research/steve/config/experiments/goodruns/hardcore/ddpg1.json
deleted file mode 100644
index 3dce87b15ce8079953529c417e0c25c30a734ca2..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hardcore/ddpg1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/hardcore.json"]}
diff --git a/research/steve/config/experiments/goodruns/hardcore/ddpg2.json b/research/steve/config/experiments/goodruns/hardcore/ddpg2.json
deleted file mode 100644
index 3dce87b15ce8079953529c417e0c25c30a734ca2..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hardcore/ddpg2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/hardcore.json"]}
diff --git a/research/steve/config/experiments/goodruns/hardcore/ddpg3.json b/research/steve/config/experiments/goodruns/hardcore/ddpg3.json
deleted file mode 100644
index 3dce87b15ce8079953529c417e0c25c30a734ca2..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hardcore/ddpg3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/hardcore.json"]}
diff --git a/research/steve/config/experiments/goodruns/hardcore/mve_tdk0.json b/research/steve/config/experiments/goodruns/hardcore/mve_tdk0.json
deleted file mode 100644
index 095d8763ac1ee32233ef08e5643f105eff67e6cd..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hardcore/mve_tdk0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/hardcore.json"]}
diff --git a/research/steve/config/experiments/goodruns/hardcore/mve_tdk1.json b/research/steve/config/experiments/goodruns/hardcore/mve_tdk1.json
deleted file mode 100644
index 095d8763ac1ee32233ef08e5643f105eff67e6cd..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hardcore/mve_tdk1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/hardcore.json"]}
diff --git a/research/steve/config/experiments/goodruns/hardcore/mve_tdk2.json b/research/steve/config/experiments/goodruns/hardcore/mve_tdk2.json
deleted file mode 100644
index 095d8763ac1ee32233ef08e5643f105eff67e6cd..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hardcore/mve_tdk2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/hardcore.json"]}
diff --git a/research/steve/config/experiments/goodruns/hardcore/mve_tdk3.json b/research/steve/config/experiments/goodruns/hardcore/mve_tdk3.json
deleted file mode 100644
index 095d8763ac1ee32233ef08e5643f105eff67e6cd..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hardcore/mve_tdk3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/hardcore.json"]}
diff --git a/research/steve/config/experiments/goodruns/hardcore/steve0.json b/research/steve/config/experiments/goodruns/hardcore/steve0.json
deleted file mode 100644
index f094208520fe3f93065f981e557571958370b7fb..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hardcore/steve0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/hardcore.json"]}
diff --git a/research/steve/config/experiments/goodruns/hardcore/steve1.json b/research/steve/config/experiments/goodruns/hardcore/steve1.json
deleted file mode 100644
index f094208520fe3f93065f981e557571958370b7fb..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hardcore/steve1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/hardcore.json"]}
diff --git a/research/steve/config/experiments/goodruns/hardcore/steve2.json b/research/steve/config/experiments/goodruns/hardcore/steve2.json
deleted file mode 100644
index f094208520fe3f93065f981e557571958370b7fb..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hardcore/steve2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/hardcore.json"]}
diff --git a/research/steve/config/experiments/goodruns/hardcore/steve3.json b/research/steve/config/experiments/goodruns/hardcore/steve3.json
deleted file mode 100644
index f094208520fe3f93065f981e557571958370b7fb..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hardcore/steve3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/hardcore.json"]}
diff --git a/research/steve/config/experiments/goodruns/hopper/ddpg0.json b/research/steve/config/experiments/goodruns/hopper/ddpg0.json
deleted file mode 100644
index 4916ab1161349792f0c396904d109d33d0d59d59..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hopper/ddpg0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/hopper.json"]}
diff --git a/research/steve/config/experiments/goodruns/hopper/ddpg1.json b/research/steve/config/experiments/goodruns/hopper/ddpg1.json
deleted file mode 100644
index 4916ab1161349792f0c396904d109d33d0d59d59..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hopper/ddpg1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/hopper.json"]}
diff --git a/research/steve/config/experiments/goodruns/hopper/ddpg2.json b/research/steve/config/experiments/goodruns/hopper/ddpg2.json
deleted file mode 100644
index 4916ab1161349792f0c396904d109d33d0d59d59..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hopper/ddpg2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/hopper.json"]}
diff --git a/research/steve/config/experiments/goodruns/hopper/ddpg3.json b/research/steve/config/experiments/goodruns/hopper/ddpg3.json
deleted file mode 100644
index 4916ab1161349792f0c396904d109d33d0d59d59..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hopper/ddpg3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/hopper.json"]}
diff --git a/research/steve/config/experiments/goodruns/hopper/mve_tdk0.json b/research/steve/config/experiments/goodruns/hopper/mve_tdk0.json
deleted file mode 100644
index 40663e8b9450fa0b831eaa6f6c0089545b02d4a8..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hopper/mve_tdk0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/hopper.json"]}
diff --git a/research/steve/config/experiments/goodruns/hopper/mve_tdk1.json b/research/steve/config/experiments/goodruns/hopper/mve_tdk1.json
deleted file mode 100644
index 40663e8b9450fa0b831eaa6f6c0089545b02d4a8..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hopper/mve_tdk1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/hopper.json"]}
diff --git a/research/steve/config/experiments/goodruns/hopper/mve_tdk2.json b/research/steve/config/experiments/goodruns/hopper/mve_tdk2.json
deleted file mode 100644
index 40663e8b9450fa0b831eaa6f6c0089545b02d4a8..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hopper/mve_tdk2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/hopper.json"]}
diff --git a/research/steve/config/experiments/goodruns/hopper/mve_tdk3.json b/research/steve/config/experiments/goodruns/hopper/mve_tdk3.json
deleted file mode 100644
index 40663e8b9450fa0b831eaa6f6c0089545b02d4a8..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hopper/mve_tdk3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/hopper.json"]}
diff --git a/research/steve/config/experiments/goodruns/hopper/steve0.json b/research/steve/config/experiments/goodruns/hopper/steve0.json
deleted file mode 100644
index 708ce89132733c03f36d8ca7d58e1b91cd5ad9cd..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hopper/steve0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/hopper.json"]}
diff --git a/research/steve/config/experiments/goodruns/hopper/steve1.json b/research/steve/config/experiments/goodruns/hopper/steve1.json
deleted file mode 100644
index 708ce89132733c03f36d8ca7d58e1b91cd5ad9cd..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hopper/steve1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/hopper.json"]}
diff --git a/research/steve/config/experiments/goodruns/hopper/steve2.json b/research/steve/config/experiments/goodruns/hopper/steve2.json
deleted file mode 100644
index 708ce89132733c03f36d8ca7d58e1b91cd5ad9cd..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hopper/steve2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/hopper.json"]}
diff --git a/research/steve/config/experiments/goodruns/hopper/steve3.json b/research/steve/config/experiments/goodruns/hopper/steve3.json
deleted file mode 100644
index 708ce89132733c03f36d8ca7d58e1b91cd5ad9cd..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/hopper/steve3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/hopper.json"]}
diff --git a/research/steve/config/experiments/goodruns/humanoid/ddpg0.json b/research/steve/config/experiments/goodruns/humanoid/ddpg0.json
deleted file mode 100644
index 3bd27e7d5f176340826691b17ee16849bb6ac708..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/humanoid/ddpg0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/goodruns/humanoid/ddpg1.json b/research/steve/config/experiments/goodruns/humanoid/ddpg1.json
deleted file mode 100644
index 3bd27e7d5f176340826691b17ee16849bb6ac708..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/humanoid/ddpg1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/goodruns/humanoid/ddpg2.json b/research/steve/config/experiments/goodruns/humanoid/ddpg2.json
deleted file mode 100644
index 3bd27e7d5f176340826691b17ee16849bb6ac708..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/humanoid/ddpg2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/goodruns/humanoid/ddpg3.json b/research/steve/config/experiments/goodruns/humanoid/ddpg3.json
deleted file mode 100644
index 3bd27e7d5f176340826691b17ee16849bb6ac708..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/humanoid/ddpg3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/goodruns/humanoid/mve_tdk0.json b/research/steve/config/experiments/goodruns/humanoid/mve_tdk0.json
deleted file mode 100644
index 542ed8d80cec5f3d653c512febbeba3291c579e5..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/humanoid/mve_tdk0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/goodruns/humanoid/mve_tdk1.json b/research/steve/config/experiments/goodruns/humanoid/mve_tdk1.json
deleted file mode 100644
index 542ed8d80cec5f3d653c512febbeba3291c579e5..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/humanoid/mve_tdk1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/goodruns/humanoid/mve_tdk2.json b/research/steve/config/experiments/goodruns/humanoid/mve_tdk2.json
deleted file mode 100644
index 542ed8d80cec5f3d653c512febbeba3291c579e5..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/humanoid/mve_tdk2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/goodruns/humanoid/mve_tdk3.json b/research/steve/config/experiments/goodruns/humanoid/mve_tdk3.json
deleted file mode 100644
index 542ed8d80cec5f3d653c512febbeba3291c579e5..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/humanoid/mve_tdk3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/goodruns/humanoid/steve0.json b/research/steve/config/experiments/goodruns/humanoid/steve0.json
deleted file mode 100644
index 835b3f6213490a83e016846001122d113f2b5b17..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/humanoid/steve0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/goodruns/humanoid/steve1.json b/research/steve/config/experiments/goodruns/humanoid/steve1.json
deleted file mode 100644
index 835b3f6213490a83e016846001122d113f2b5b17..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/humanoid/steve1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/goodruns/humanoid/steve2.json b/research/steve/config/experiments/goodruns/humanoid/steve2.json
deleted file mode 100644
index 835b3f6213490a83e016846001122d113f2b5b17..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/humanoid/steve2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/goodruns/humanoid/steve3.json b/research/steve/config/experiments/goodruns/humanoid/steve3.json
deleted file mode 100644
index 835b3f6213490a83e016846001122d113f2b5b17..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/humanoid/steve3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/humanoid.json"]}
diff --git a/research/steve/config/experiments/goodruns/rshum/ddpg0.json b/research/steve/config/experiments/goodruns/rshum/ddpg0.json
deleted file mode 100644
index 9fd98d11e712231750f8dce5cf6352522e92abd8..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/rshum/ddpg0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/rshum.json"]}
diff --git a/research/steve/config/experiments/goodruns/rshum/ddpg1.json b/research/steve/config/experiments/goodruns/rshum/ddpg1.json
deleted file mode 100644
index 9fd98d11e712231750f8dce5cf6352522e92abd8..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/rshum/ddpg1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/rshum.json"]}
diff --git a/research/steve/config/experiments/goodruns/rshum/ddpg2.json b/research/steve/config/experiments/goodruns/rshum/ddpg2.json
deleted file mode 100644
index 9fd98d11e712231750f8dce5cf6352522e92abd8..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/rshum/ddpg2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/rshum.json"]}
diff --git a/research/steve/config/experiments/goodruns/rshum/ddpg3.json b/research/steve/config/experiments/goodruns/rshum/ddpg3.json
deleted file mode 100644
index 9fd98d11e712231750f8dce5cf6352522e92abd8..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/rshum/ddpg3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/rshum.json"]}
diff --git a/research/steve/config/experiments/goodruns/rshum/mve_tdk0.json b/research/steve/config/experiments/goodruns/rshum/mve_tdk0.json
deleted file mode 100644
index ade2434ee2fae17c53aaaec2bffab7983b45c0d4..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/rshum/mve_tdk0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/rshum.json"]}
diff --git a/research/steve/config/experiments/goodruns/rshum/mve_tdk1.json b/research/steve/config/experiments/goodruns/rshum/mve_tdk1.json
deleted file mode 100644
index ade2434ee2fae17c53aaaec2bffab7983b45c0d4..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/rshum/mve_tdk1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/rshum.json"]}
diff --git a/research/steve/config/experiments/goodruns/rshum/mve_tdk2.json b/research/steve/config/experiments/goodruns/rshum/mve_tdk2.json
deleted file mode 100644
index ade2434ee2fae17c53aaaec2bffab7983b45c0d4..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/rshum/mve_tdk2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/rshum.json"]}
diff --git a/research/steve/config/experiments/goodruns/rshum/mve_tdk3.json b/research/steve/config/experiments/goodruns/rshum/mve_tdk3.json
deleted file mode 100644
index ade2434ee2fae17c53aaaec2bffab7983b45c0d4..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/rshum/mve_tdk3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/rshum.json"]}
diff --git a/research/steve/config/experiments/goodruns/rshum/steve0.json b/research/steve/config/experiments/goodruns/rshum/steve0.json
deleted file mode 100644
index 510854fbf80a03ccfeab8e1a2379ffebf8cc91ab..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/rshum/steve0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/rshum.json"]}
diff --git a/research/steve/config/experiments/goodruns/rshum/steve1.json b/research/steve/config/experiments/goodruns/rshum/steve1.json
deleted file mode 100644
index 510854fbf80a03ccfeab8e1a2379ffebf8cc91ab..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/rshum/steve1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/rshum.json"]}
diff --git a/research/steve/config/experiments/goodruns/rshum/steve2.json b/research/steve/config/experiments/goodruns/rshum/steve2.json
deleted file mode 100644
index 510854fbf80a03ccfeab8e1a2379ffebf8cc91ab..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/rshum/steve2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/rshum.json"]}
diff --git a/research/steve/config/experiments/goodruns/rshum/steve3.json b/research/steve/config/experiments/goodruns/rshum/steve3.json
deleted file mode 100644
index 510854fbf80a03ccfeab8e1a2379ffebf8cc91ab..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/rshum/steve3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/rshum.json"]}
diff --git a/research/steve/config/experiments/goodruns/swimmer/ddpg0.json b/research/steve/config/experiments/goodruns/swimmer/ddpg0.json
deleted file mode 100644
index a94fc7c52ac1f31b9f12b83c5ac10f49e78d66d6..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/swimmer/ddpg0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/swimmer.json"]}
diff --git a/research/steve/config/experiments/goodruns/swimmer/ddpg1.json b/research/steve/config/experiments/goodruns/swimmer/ddpg1.json
deleted file mode 100644
index a94fc7c52ac1f31b9f12b83c5ac10f49e78d66d6..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/swimmer/ddpg1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/swimmer.json"]}
diff --git a/research/steve/config/experiments/goodruns/swimmer/ddpg2.json b/research/steve/config/experiments/goodruns/swimmer/ddpg2.json
deleted file mode 100644
index a94fc7c52ac1f31b9f12b83c5ac10f49e78d66d6..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/swimmer/ddpg2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/swimmer.json"]}
diff --git a/research/steve/config/experiments/goodruns/swimmer/ddpg3.json b/research/steve/config/experiments/goodruns/swimmer/ddpg3.json
deleted file mode 100644
index a94fc7c52ac1f31b9f12b83c5ac10f49e78d66d6..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/swimmer/ddpg3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/swimmer.json"]}
diff --git a/research/steve/config/experiments/goodruns/swimmer/mve_tdk0.json b/research/steve/config/experiments/goodruns/swimmer/mve_tdk0.json
deleted file mode 100644
index 14210117887df275a89990d6844c3d9fc4c64c24..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/swimmer/mve_tdk0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/swimmer.json"]}
diff --git a/research/steve/config/experiments/goodruns/swimmer/mve_tdk1.json b/research/steve/config/experiments/goodruns/swimmer/mve_tdk1.json
deleted file mode 100644
index 14210117887df275a89990d6844c3d9fc4c64c24..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/swimmer/mve_tdk1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/swimmer.json"]}
diff --git a/research/steve/config/experiments/goodruns/swimmer/mve_tdk2.json b/research/steve/config/experiments/goodruns/swimmer/mve_tdk2.json
deleted file mode 100644
index 14210117887df275a89990d6844c3d9fc4c64c24..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/swimmer/mve_tdk2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/swimmer.json"]}
diff --git a/research/steve/config/experiments/goodruns/swimmer/mve_tdk3.json b/research/steve/config/experiments/goodruns/swimmer/mve_tdk3.json
deleted file mode 100644
index 14210117887df275a89990d6844c3d9fc4c64c24..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/swimmer/mve_tdk3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/swimmer.json"]}
diff --git a/research/steve/config/experiments/goodruns/swimmer/steve0.json b/research/steve/config/experiments/goodruns/swimmer/steve0.json
deleted file mode 100644
index d33583283089eb38f038c5669ba330d3b0720fbb..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/swimmer/steve0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/swimmer.json"]}
diff --git a/research/steve/config/experiments/goodruns/swimmer/steve1.json b/research/steve/config/experiments/goodruns/swimmer/steve1.json
deleted file mode 100644
index d33583283089eb38f038c5669ba330d3b0720fbb..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/swimmer/steve1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/swimmer.json"]}
diff --git a/research/steve/config/experiments/goodruns/swimmer/steve2.json b/research/steve/config/experiments/goodruns/swimmer/steve2.json
deleted file mode 100644
index d33583283089eb38f038c5669ba330d3b0720fbb..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/swimmer/steve2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/swimmer.json"]}
diff --git a/research/steve/config/experiments/goodruns/swimmer/steve3.json b/research/steve/config/experiments/goodruns/swimmer/steve3.json
deleted file mode 100644
index d33583283089eb38f038c5669ba330d3b0720fbb..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/swimmer/steve3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/swimmer.json"]}
diff --git a/research/steve/config/experiments/goodruns/walker2d/ddpg0.json b/research/steve/config/experiments/goodruns/walker2d/ddpg0.json
deleted file mode 100644
index 81fe2ff5643d47dded60431bbbf39541cdfb3f30..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/walker2d/ddpg0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/walker2d.json"]}
diff --git a/research/steve/config/experiments/goodruns/walker2d/ddpg1.json b/research/steve/config/experiments/goodruns/walker2d/ddpg1.json
deleted file mode 100644
index 81fe2ff5643d47dded60431bbbf39541cdfb3f30..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/walker2d/ddpg1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/walker2d.json"]}
diff --git a/research/steve/config/experiments/goodruns/walker2d/ddpg2.json b/research/steve/config/experiments/goodruns/walker2d/ddpg2.json
deleted file mode 100644
index 81fe2ff5643d47dded60431bbbf39541cdfb3f30..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/walker2d/ddpg2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/walker2d.json"]}
diff --git a/research/steve/config/experiments/goodruns/walker2d/ddpg3.json b/research/steve/config/experiments/goodruns/walker2d/ddpg3.json
deleted file mode 100644
index 81fe2ff5643d47dded60431bbbf39541cdfb3f30..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/walker2d/ddpg3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/walker2d.json"]}
diff --git a/research/steve/config/experiments/goodruns/walker2d/mve_tdk0.json b/research/steve/config/experiments/goodruns/walker2d/mve_tdk0.json
deleted file mode 100644
index d8420effaf5059eb359bcbd5edc17a50824d4d94..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/walker2d/mve_tdk0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/walker2d.json"]}
diff --git a/research/steve/config/experiments/goodruns/walker2d/mve_tdk1.json b/research/steve/config/experiments/goodruns/walker2d/mve_tdk1.json
deleted file mode 100644
index d8420effaf5059eb359bcbd5edc17a50824d4d94..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/walker2d/mve_tdk1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/walker2d.json"]}
diff --git a/research/steve/config/experiments/goodruns/walker2d/mve_tdk2.json b/research/steve/config/experiments/goodruns/walker2d/mve_tdk2.json
deleted file mode 100644
index d8420effaf5059eb359bcbd5edc17a50824d4d94..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/walker2d/mve_tdk2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/walker2d.json"]}
diff --git a/research/steve/config/experiments/goodruns/walker2d/mve_tdk3.json b/research/steve/config/experiments/goodruns/walker2d/mve_tdk3.json
deleted file mode 100644
index d8420effaf5059eb359bcbd5edc17a50824d4d94..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/walker2d/mve_tdk3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/walker2d.json"]}
diff --git a/research/steve/config/experiments/goodruns/walker2d/steve0.json b/research/steve/config/experiments/goodruns/walker2d/steve0.json
deleted file mode 100644
index a98c410cad3c219541663a6e76072f4e23888135..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/walker2d/steve0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/walker2d.json"]}
diff --git a/research/steve/config/experiments/goodruns/walker2d/steve1.json b/research/steve/config/experiments/goodruns/walker2d/steve1.json
deleted file mode 100644
index a98c410cad3c219541663a6e76072f4e23888135..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/walker2d/steve1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/walker2d.json"]}
diff --git a/research/steve/config/experiments/goodruns/walker2d/steve2.json b/research/steve/config/experiments/goodruns/walker2d/steve2.json
deleted file mode 100644
index a98c410cad3c219541663a6e76072f4e23888135..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/walker2d/steve2.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/walker2d.json"]}
diff --git a/research/steve/config/experiments/goodruns/walker2d/steve3.json b/research/steve/config/experiments/goodruns/walker2d/steve3.json
deleted file mode 100644
index a98c410cad3c219541663a6e76072f4e23888135..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/goodruns/walker2d/steve3.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/walker2d.json"]}
diff --git a/research/steve/config/experiments/speedruns/flagrun/speedy_ddpg0.json b/research/steve/config/experiments/speedruns/flagrun/speedy_ddpg0.json
deleted file mode 100644
index b7280d71ef0a78f8e70dfe9c76575628853c9ff5..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/speedruns/flagrun/speedy_ddpg0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/flagrun.json", "config/experimental_setups/speedrun.json"]}
diff --git a/research/steve/config/experiments/speedruns/flagrun/speedy_ddpg1.json b/research/steve/config/experiments/speedruns/flagrun/speedy_ddpg1.json
deleted file mode 100644
index b7280d71ef0a78f8e70dfe9c76575628853c9ff5..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/speedruns/flagrun/speedy_ddpg1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/flagrun.json", "config/experimental_setups/speedrun.json"]}
diff --git a/research/steve/config/experiments/speedruns/flagrun/speedy_mve_tdk0.json b/research/steve/config/experiments/speedruns/flagrun/speedy_mve_tdk0.json
deleted file mode 100644
index 73252566b5e8a6515f008e1ddbe5c939b2ee000b..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/speedruns/flagrun/speedy_mve_tdk0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/flagrun.json", "config/experimental_setups/speedrun.json"]}
diff --git a/research/steve/config/experiments/speedruns/flagrun/speedy_mve_tdk1.json b/research/steve/config/experiments/speedruns/flagrun/speedy_mve_tdk1.json
deleted file mode 100644
index 73252566b5e8a6515f008e1ddbe5c939b2ee000b..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/speedruns/flagrun/speedy_mve_tdk1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/flagrun.json", "config/experimental_setups/speedrun.json"]}
diff --git a/research/steve/config/experiments/speedruns/flagrun/speedy_steve0.json b/research/steve/config/experiments/speedruns/flagrun/speedy_steve0.json
deleted file mode 100644
index ba5708f1ffb59a20751474d999f8a8798e89e751..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/speedruns/flagrun/speedy_steve0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/flagrun.json", "config/experimental_setups/speedrun.json"]}
diff --git a/research/steve/config/experiments/speedruns/flagrun/speedy_steve1.json b/research/steve/config/experiments/speedruns/flagrun/speedy_steve1.json
deleted file mode 100644
index ba5708f1ffb59a20751474d999f8a8798e89e751..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/speedruns/flagrun/speedy_steve1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/flagrun.json", "config/experimental_setups/speedrun.json"]}
diff --git a/research/steve/config/experiments/speedruns/humanoid/speedy_ddpg0.json b/research/steve/config/experiments/speedruns/humanoid/speedy_ddpg0.json
deleted file mode 100644
index eb07f31dc90b40ae7d66046627b29b153d3f2de9..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/speedruns/humanoid/speedy_ddpg0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/humanoid.json", "config/experimental_setups/speedrun.json"]}
diff --git a/research/steve/config/experiments/speedruns/humanoid/speedy_ddpg1.json b/research/steve/config/experiments/speedruns/humanoid/speedy_ddpg1.json
deleted file mode 100644
index eb07f31dc90b40ae7d66046627b29b153d3f2de9..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/speedruns/humanoid/speedy_ddpg1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/ddpg.json", "config/envs/humanoid.json", "config/experimental_setups/speedrun.json"]}
diff --git a/research/steve/config/experiments/speedruns/humanoid/speedy_mve_tdk0.json b/research/steve/config/experiments/speedruns/humanoid/speedy_mve_tdk0.json
deleted file mode 100644
index 51a3bdcb5a3a18903d9671e48eee3b2c10922c95..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/speedruns/humanoid/speedy_mve_tdk0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/humanoid.json", "config/experimental_setups/speedrun.json"]}
diff --git a/research/steve/config/experiments/speedruns/humanoid/speedy_mve_tdk1.json b/research/steve/config/experiments/speedruns/humanoid/speedy_mve_tdk1.json
deleted file mode 100644
index 51a3bdcb5a3a18903d9671e48eee3b2c10922c95..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/speedruns/humanoid/speedy_mve_tdk1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/mve_tdk.json", "config/envs/humanoid.json", "config/experimental_setups/speedrun.json"]}
diff --git a/research/steve/config/experiments/speedruns/humanoid/speedy_steve0.json b/research/steve/config/experiments/speedruns/humanoid/speedy_steve0.json
deleted file mode 100644
index 0d2bfaa4e3dd03a0ab88d28b12c97964d6c409d0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/speedruns/humanoid/speedy_steve0.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/humanoid.json", "config/experimental_setups/speedrun.json"]}
diff --git a/research/steve/config/experiments/speedruns/humanoid/speedy_steve1.json b/research/steve/config/experiments/speedruns/humanoid/speedy_steve1.json
deleted file mode 100644
index 0d2bfaa4e3dd03a0ab88d28b12c97964d6c409d0..0000000000000000000000000000000000000000
--- a/research/steve/config/experiments/speedruns/humanoid/speedy_steve1.json
+++ /dev/null
@@ -1 +0,0 @@
-{"inherits": ["config/algos/steve.json", "config/envs/humanoid.json", "config/experimental_setups/speedrun.json"]}
diff --git a/research/steve/envwrap.py b/research/steve/envwrap.py
deleted file mode 100644
index bd88c3035c0afd22d5074460ee51fa346f37a798..0000000000000000000000000000000000000000
--- a/research/steve/envwrap.py
+++ /dev/null
@@ -1,106 +0,0 @@
-from builtins import object
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-try:
- import roboschool
-except:
- pass
-import gym
-import numpy as np
-
-from config import config
-
-MAX_FRAMES = config["env"]["max_frames"]
-
-gym.logger.level=40
-
-def get_env(env_name, *args, **kwargs):
- MAPPING = {
- "CartPole-v0": CartPoleWrapper,
- }
- if env_name in MAPPING: return MAPPING[env_name](env_name, *args, **kwargs)
- else: return NoTimeLimitMujocoWrapper(env_name, *args, **kwargs)
-
-class GymWrapper(object):
- """
- Generic wrapper for OpenAI gym environments.
- """
- def __init__(self, env_name):
- self.internal_env = gym.make(env_name)
- self.observation_space = self.internal_env.observation_space
- self.action_space = self.internal_env.action_space
- self.custom_init()
-
- def custom_init(self):
- pass
-
- def reset(self):
- self.clock = 0
- return self.preprocess_obs(self.internal_env.reset())
-
- # returns normalized actions
- def sample(self):
- return self.action_space.sample()
-
- # this is used for converting continuous approximations back to the original domain
- def normalize_actions(self, actions):
- return actions
-
- # puts actions into a form where they can be predicted. by default, called after sample()
- def unnormalize_actions(self, actions):
- return actions
-
- def preprocess_obs(self, obs):
- # return np.append(obs, [self.clock/float(MAX_FRAMES)])
- return obs
-
- def step(self, normalized_action):
- out = self.internal_env.step(normalized_action)
- self.clock += 1
- obs, reward, done = self.preprocess_obs(out[0]), out[1], float(out[2])
- reset = done == 1. or self.clock == MAX_FRAMES
- return obs, reward, done, reset
-
- def render_rollout(self, states):
- ## states is numpy array of size [timesteps, state]
- self.internal_env.reset()
- for state in states:
- self.internal_env.env.state = state
- self.internal_env.render()
-
-class CartPoleWrapper(GymWrapper):
- """
- Wrap CartPole.
- """
- def sample(self):
- return np.array([np.random.uniform(0., 1.)])
-
- def normalize_actions(self, action):
- return 1 if action[0] >= 0 else 0
-
- def unnormalize_actions(self, action):
- return 2. * action - 1.
-
-class NoTimeLimitMujocoWrapper(GymWrapper):
- """
- Wrap Mujoco-style environments, removing the termination condition after time.
- This is needed to keep it Markovian.
- """
- def __init__(self, env_name):
- self.internal_env = gym.make(env_name).env
- self.observation_space = self.internal_env.observation_space
- self.action_space = self.internal_env.action_space
- self.custom_init()
diff --git a/research/steve/learner.py b/research/steve/learner.py
deleted file mode 100644
index 8a4c074cd0b85f84ea19d52bf8b43331aab9c5c5..0000000000000000000000000000000000000000
--- a/research/steve/learner.py
+++ /dev/null
@@ -1,272 +0,0 @@
-from __future__ import division
-from __future__ import print_function
-from builtins import zip
-from builtins import range
-from builtins import object
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import traceback, threading, time, warnings
-import tensorflow as tf
-import numpy as np
-
-import util
-from replay import ReplayBuffer
-
-class Learner(object):
- """
- Generic object which runs the main training loop of anything that trains using
- a replay buffer. Handles updating, logging, saving/loading, batching, etc.
- """
- def __init__(self, interactor_queue, lock, config, env_config, learner_config, **bonus_kwargs):
- self.learner_name = self.learner_name()
- self.interactor_queue = interactor_queue
- self.learner_lock = lock
- self.config = config
- self.env_config = env_config
- self.learner_config = learner_config
- self.bonus_kwargs = bonus_kwargs
- self.kill_threads = False
- self.permit_desync = False
- self.need_frames_notification = threading.Condition()
- self._reset_inspections()
- self.total_frames = 0
-
- self.save_path = util.create_directory("%s/%s/%s/%s" % (self.config["output_root"], self.config["env"]["name"], self.config["name"], self.config["save_model_path"]))
- self.log_path = util.create_directory("%s/%s/%s/%s" % (self.config["output_root"], self.config["env"]["name"], self.config["name"], self.config["log_path"])) + "/%s.log" % self.learner_name
-
- # replay buffer to store data
- self.replay_buffer_lock = threading.RLock()
- self.replay_buffer = ReplayBuffer(self.learner_config["replay_size"],
- np.prod(self.env_config["obs_dims"]),
- self.env_config["action_dim"])
-
- # data loaders pull data from the replay buffer and put it into the tfqueue for model usage
- self.data_loaders = self.make_loader_placeholders()
- queue_capacity = np.ceil(1./self.learner_config["frames_per_update"]) if self.learner_config["frames_per_update"] else 100
- self.tf_queue = tf.FIFOQueue(capacity=queue_capacity, dtypes=[dl.dtype for dl in self.data_loaders])
- self.enqueue_op = self.tf_queue.enqueue(self.data_loaders)
- self.current_batch = self.tf_queue.dequeue()
-
- # build the TF graph for the actual model to train
- self.core, self.train_losses, self.train_ops, self.inspect_losses = self.make_core_model()
- self.sess = tf.Session()
- self.sess.run(tf.global_variables_initializer())
-
- ## Mandatory functions to override
- def learner_name(self): raise Exception('unimplemented: learner_name')
- def make_loader_placeholders(self): raise Exception('unimplemented: make_loader_placeholders')
- def make_core_model(self): raise Exception('unimplemented: make_core_model')
-
- ## Optional functions to override
- def initialize(self): warnings.warn('unimplemented: initialize')
- def resume_from_checkpoint(self, epoch): warnings.warn('unimplemented: resume_from_checkpoint')
- def checkpoint(self): warnings.warn('unimplemented: checkpoint')
- def backup(self): warnings.warn('unimplemented: backup')
-
- ## Internal functions
- def _start(self):
- # fetch data from the interactors to pre-fill the replay buffer
- self.prefetch_thread = threading.Thread(target=self._poll_interactors, args=(True, self.learner_config["frames_before_learning"],))
- self.prefetch_thread.start()
- self.prefetch_thread.join()
-
- # start the interactor and data loader
- self.data_load_thread = threading.Thread(target=self._run_enqueue_data)
- self.data_load_thread.start()
-
- # initialize the learner, pretraining if needed
- if self.config["resume"]: self._resume_from_checkpoint()
- else: self._initialize()
-
- # re-sync everything, and start up interactions with the environment
- self.interactor_poll_thread = threading.Thread(target=self._poll_interactors)
- self.interactor_poll_thread.start()
-
- # start the clock
- self._last_checkpoint_time = time.time()
-
- def _learn(self, permit_desync=False, log=True, checkpoint=True, backup=True):
- # this is to keep the frames/update synced properly
- if self.learner_config["frames_per_update"] is not False and not permit_desync:
- if not self._have_enough_frames():
- with self.need_frames_notification:
- self.need_frames_notification.notify()
- return
-
- # log
- if log and (self.update_i + 1) % self.learner_config["log_every_n"] == 0:
- self._log()
-
- # checkpoint
- if checkpoint and (self.update_i + 1) % self.learner_config["epoch_every_n"] == 0:
- self._checkpoint()
-
- # backup
- if backup and (self.update_i + 1) % self.learner_config["backup_every_n"] == 0:
- self._backup()
-
- # train
- self._training_step()
-
- def _have_enough_frames(self):
- gathered_frames = self.total_frames - self.learner_config["frames_before_learning"]
- return gathered_frames > self.learner_config["frames_per_update"] * self.update_i
-
- def _initialize(self):
- self.epoch = 0
- self.update_i = 0
- self.hours = 0
- self._last_checkpoint_time = time.time()
-
- self.initialize()
-
- if self.learner_config["pretrain_n"]: self._pretrain()
- self._checkpoint()
-
- def _pretrain(self):
- for _ in range(self.learner_config["pretrain_n"]):
- self._learn(permit_desync=True, checkpoint=False, backup=False)
- self.epoch = 0
- self.update_i = 0
-
- def _resume_from_checkpoint(self):
- epoch = util.get_largest_epoch_in_dir(self.save_path, self.core.saveid)
- if not self.config['keep_all_replay_buffers']: util.wipe_all_but_largest_epoch_in_dir(self.save_path, self.core.saveid)
- if epoch is False:
- raise Exception("Tried to reload but no model found")
- with self.learner_lock:
- self.core.load(self.sess, self.save_path, epoch)
- self.epoch, self.update_i, self.total_frames, self.hours = self.sess.run([self.core.epoch_n, self.core.update_n, self.core.frame_n, self.core.hours])
- with self.replay_buffer_lock:
- self.replay_buffer.load(self.save_path, '%09d_%s' % (epoch, self.learner_name))
- self.resume_from_checkpoint(epoch)
-
- def _log(self):
- if self.denom > 0:
- logstring = "(%3.2f sec) h%-8.2f e%-8d s%-8d f%-8d\t" % (time.time() - self._log_time, self.hours, self.epoch, self.update_i + 1, self.total_frames) + ', '.join(["%8f" % x for x in (self.running_total / self.denom).tolist()])
- print("%s\t%s" % (self.learner_name, logstring))
- with open(self.log_path, "a") as f: f.write(logstring + "\n")
- self._reset_inspections()
-
- def _reset_inspections(self):
- self.running_total = 0.
- self.denom = 0.
- self._log_time = time.time()
-
- def _checkpoint(self):
- self.checkpoint()
- self.epoch += 1
- self.hours += (time.time() - self._last_checkpoint_time) / 3600.
- self._last_checkpoint_time = time.time()
- self.core.update_epoch(self.sess, self.epoch, self.update_i, self.total_frames, self.hours)
- with self.learner_lock: self.core.save(self.sess, self.save_path)
-
- def _backup(self):
- self.backup()
- if not self.learner_config['keep_all_replay_buffers']: util.wipe_all_but_largest_epoch_in_dir(self.save_path, self.core.saveid)
- with self.learner_lock:
- self.core.save(self.sess, self.save_path, self.epoch)
- with self.replay_buffer_lock:
- self.replay_buffer.save(self.save_path, '%09d_%s' % (self.epoch, self.learner_name))
-
- def _training_step(self):
- train_ops = tuple([op for op, loss in zip(self.train_ops,
- self.train_losses)
- if loss is not None])
- outs = self.sess.run(train_ops + self.inspect_losses)
- self.running_total += np.array(outs[len(train_ops):])
- self.denom += 1.
- self.update_i += 1
-
- def _poll_interactors(self, continuous_poll=False, frames_before_terminate=None):
- # poll the interactors for new frames.
- # the synced_condition semaphore prevents this from consuming too much CPU
- while not self.kill_threads:
- if self.learner_config["frames_per_update"] is not False and not continuous_poll:
- with self.need_frames_notification: self.need_frames_notification.wait()
- while not self.interactor_queue.empty():
- new_frames = self.interactor_queue.get()
- self._add_frames(new_frames)
- if frames_before_terminate and self.total_frames >= frames_before_terminate: return
-
- def _add_frames(self, frames):
- with self.replay_buffer_lock:
- for frame in frames:
- self.replay_buffer.add_replay(*frame)
- self.total_frames = self.replay_buffer.count
- return self.total_frames
-
- def _run_enqueue_data(self):
- while not self.kill_threads:
- data = self.replay_buffer.random_batch(self.learner_config["batch_size"])
- self.sess.run(self.enqueue_op, feed_dict=dict(list(zip(self.data_loaders, data))))
-
- def _kill_threads(self):
- self.kill_threads = True
-
-
-class CoreModel(object):
- """The base class for the "core" of learners."""
- def __init__(self, name, env_config, learner_config):
- self.name = self.saveid + "/" + name
- self.env_config = env_config
- self.learner_config = learner_config
-
- with tf.variable_scope(self.name):
- self.epoch_n = tf.get_variable('epoch_n', [], initializer=tf.constant_initializer(0), dtype=tf.int64, trainable=False)
- self.update_n = tf.get_variable('update_n', [], initializer=tf.constant_initializer(0), dtype=tf.int64, trainable=False)
- self.frame_n = tf.get_variable('frame_n', [], initializer=tf.constant_initializer(0), dtype=tf.int64, trainable=False)
- self.hours = tf.get_variable('hours', [], initializer=tf.constant_initializer(0.), dtype=tf.float64, trainable=False)
- self.epoch_n_placeholder = tf.placeholder(tf.int64, [])
- self.update_n_placeholder = tf.placeholder(tf.int64, [])
- self.frame_n_placeholder = tf.placeholder(tf.int64, [])
- self.hours_placeholder = tf.placeholder(tf.float64, [])
- self.assign_epoch_op = [tf.assign(self.epoch_n, self.epoch_n_placeholder), tf.assign(self.update_n, self.update_n_placeholder), tf.assign(self.frame_n, self.frame_n_placeholder), tf.assign(self.hours, self.hours_placeholder)]
-
- self.create_params(env_config, learner_config)
- self.model_params = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope=self.name)
- self.saver = tf.train.Saver(self.model_params)
-
- @property
- def saveid(self):
- raise Exception("specify a save ID")
-
- def create_params(self, env_config, learner_config):
- raise Exception("unimplemented")
-
- def update_epoch(self, sess, epoch, updates, frames, hours):
- sess.run(self.assign_epoch_op, feed_dict={self.epoch_n_placeholder: int(epoch), self.update_n_placeholder: int(updates), self.frame_n_placeholder: int(frames), self.hours_placeholder: float(hours)})
-
- def save(self, sess, path, epoch=None):
- if epoch is None: self.saver.save(sess, path + "/%s.params" % self.saveid)
- else: self.saver.save(sess, path + "/%09d_%s.params" % (epoch, self.saveid))
-
- def load(self, sess, path, epoch=None):
- if epoch is None: self.saver.restore(sess, path + "/%s.params" % self.saveid)
- else: self.saver.restore(sess, path + "/%09d_%s.params" % (epoch, self.saveid))
-
-def run_learner(learner_subclass, queue, lock, config, env_config, learner_config, **bonus_kwargs):
- learner = learner_subclass(queue, lock, config, env_config, learner_config, **bonus_kwargs)
- try:
- learner._start()
- while True: learner._learn()
-
- except Exception as e:
- print('Caught exception in learner process')
- traceback.print_exc()
- learner._kill_threads()
- print()
- raise e
diff --git a/research/steve/master.py b/research/steve/master.py
deleted file mode 100644
index 4d08474724dff64980f16257b9fe7a13cceb2cc1..0000000000000000000000000000000000000000
--- a/research/steve/master.py
+++ /dev/null
@@ -1,85 +0,0 @@
-from builtins import str
-from builtins import range
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import multiprocessing
-import os, sys, time
-
-from config import config, log_config
-import util
-
-AGENT_COUNT = config["agent_config"]["count"]
-EVALUATOR_COUNT = config["evaluator_config"]["count"]
-MODEL_AUGMENTED = config["model_config"] is not False
-if config["resume"]:
- ROOT_PATH = "output/" + config["env"]["name"] + "/" + config["name"]
-else:
- ROOT_PATH = util.create_and_wipe_directory("output/" + config["env"]["name"] + "/" + config["name"])
-log_config()
-import learner, agent, valuerl_learner
-if MODEL_AUGMENTED: import worldmodel_learner
-
-if __name__ == '__main__':
- all_procs = set([])
- interaction_procs = set([])
-
- # lock
- policy_lock = multiprocessing.Lock()
- model_lock = multiprocessing.Lock() if MODEL_AUGMENTED else None
-
- # queue
- policy_replay_frame_queue = multiprocessing.Queue(1)
- model_replay_frame_queue = multiprocessing.Queue(1) if MODEL_AUGMENTED else None
-
- # interactors
- for interact_proc_i in range(AGENT_COUNT):
- interact_proc = multiprocessing.Process(target=agent.main, args=(interact_proc_i, False, policy_replay_frame_queue, model_replay_frame_queue, policy_lock, config))
- all_procs.add(interact_proc)
- interaction_procs.add(interact_proc)
-
- # evaluators
- for interact_proc_i in range(EVALUATOR_COUNT):
- interact_proc = multiprocessing.Process(target=agent.main, args=(interact_proc_i, True, policy_replay_frame_queue, model_replay_frame_queue, policy_lock, config))
- all_procs.add(interact_proc)
- interaction_procs.add(interact_proc)
-
- # policy training
- train_policy_proc = multiprocessing.Process(target=learner.run_learner, args=(valuerl_learner.ValueRLLearner, policy_replay_frame_queue, policy_lock, config, config["env"], config["policy_config"]), kwargs={"model_lock": model_lock})
- all_procs.add(train_policy_proc)
-
- # model training
- if MODEL_AUGMENTED:
- train_model_proc = multiprocessing.Process(target=learner.run_learner, args=(worldmodel_learner.WorldmodelLearner, model_replay_frame_queue, model_lock, config, config["env"], config["model_config"]))
- all_procs.add(train_model_proc)
-
- # start all policies
- os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
- for i, proc in enumerate(interaction_procs):
- os.environ['CUDA_VISIBLE_DEVICES'] = ''
- proc.start()
-
- os.environ['CUDA_VISIBLE_DEVICES'] = str(int(sys.argv[2]))
- train_policy_proc.start()
-
- if MODEL_AUGMENTED:
- os.environ['CUDA_VISIBLE_DEVICES'] = str(1+int(sys.argv[2]))
- train_model_proc.start()
-
- while True:
- try:
- pass
- except:
- for proc in all_procs: proc.join()
diff --git a/research/steve/nn.py b/research/steve/nn.py
deleted file mode 100644
index c87c6eb834506d0cbb462f92d53bcf3af30a4567..0000000000000000000000000000000000000000
--- a/research/steve/nn.py
+++ /dev/null
@@ -1,189 +0,0 @@
-from builtins import range
-from builtins import object
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import tensorflow as tf
-import numpy as np
-from itertools import product
-
-class FeedForwardNet(object):
- """Custom feed-forward network layer."""
- def __init__(self, name, in_size, out_shape, layers=1, hidden_dim=32, final_nonlinearity=None, get_uncertainty=False):
- self.name = name
- self.in_size = in_size
- self.out_shape = out_shape
- self.out_size = np.prod(out_shape)
- self.layers = layers
- self.hidden_dim = hidden_dim
- self.final_nonlinearity = (lambda x:x) if final_nonlinearity is None else final_nonlinearity
- self.get_uncertainty = get_uncertainty
-
- self.weights = [None] * layers
- self.biases = [None] * layers
-
- self.params_list = []
-
- with tf.variable_scope(name):
- for layer_i in range(self.layers):
- in_size = self.hidden_dim
- out_size = self.hidden_dim
- if layer_i == 0: in_size = self.in_size
- if layer_i == self.layers - 1: out_size = self.out_size
- self.weights[layer_i] = tf.get_variable("weights%d" % layer_i, [in_size, out_size], initializer=tf.contrib.layers.xavier_initializer())
- self.biases[layer_i] = tf.get_variable("bias%d" % layer_i, [1, out_size], initializer=tf.constant_initializer(0.0))
- self.params_list += [self.weights[layer_i], self.biases[layer_i]]
-
- def __call__(self, x, stop_params_gradient=False, is_eval=True, ensemble_idxs=None, pre_expanded=None, reduce_mode="none"):
- original_shape = tf.shape(x)
- h = tf.reshape(x, [-1, self.in_size])
- for layer_i in range(self.layers):
- nonlinearity = tf.nn.relu if layer_i + 1 < self.layers else self.final_nonlinearity
- if stop_params_gradient: h = nonlinearity(tf.matmul(h, tf.stop_gradient(self.weights[layer_i])) + tf.stop_gradient(self.biases[layer_i]))
- else: h = nonlinearity(tf.matmul(h, self.weights[layer_i]) + self.biases[layer_i])
- if len(self.out_shape) > 0: h = tf.reshape(h, tf.concat([original_shape[:-1], tf.constant(self.out_shape)], -1))
- else: h = tf.reshape(h, original_shape[:-1])
- if pre_expanded is None: pre_expanded = ensemble_idxs is not None
- if reduce_mode == "none" and not pre_expanded and self.get_uncertainty:
- if len(self.out_shape) > 0: h = tf.expand_dims(h, -2)
- else: h = tf.expand_dims(h, -1)
- return h
-
- def l2_loss(self):
- return tf.add_n([tf.reduce_sum(.5 * tf.square(mu)) for mu in self.params_list])
-
-class BayesianDropoutFeedForwardNet(FeedForwardNet):
- """Custom feed-forward network layer, with dropout as a Bayesian approximation."""
- def __init__(self, name, in_size, out_shape, layers=1, hidden_dim=32, final_nonlinearity=None, get_uncertainty=False, keep_prob=.5, eval_sample_count=2, consistent_random_seed=False):
- super(BayesianDropoutFeedForwardNet, self).__init__(name, in_size, out_shape, layers=layers, hidden_dim=hidden_dim,
- final_nonlinearity=final_nonlinearity, get_uncertainty=get_uncertainty)
- self.keep_prob = keep_prob
- self.eval_sample_count = eval_sample_count
- if eval_sample_count < 2: raise Exception("eval_sample_count must be at least 2 to estimate uncertainty")
- self.dropout_seed = tf.random_uniform([layers], maxval=1e18, dtype=tf.int64) if consistent_random_seed else [None] * layers
-
- def __call__(self, x, stop_params_gradient=False, is_eval=True, pre_expanded=False, ensemble_idxs=None, reduce_mode="none"):
- if is_eval:
- x = tf.tile(tf.expand_dims(x,0), tf.concat([tf.constant([self.eval_sample_count]), tf.ones_like(tf.shape(x))], 0))
- original_shape = tf.shape(x)
- h = tf.reshape(x, [-1, self.in_size])
- for layer_i in range(self.layers):
- nonlinearity = tf.nn.relu if layer_i + 1 < self.layers else self.final_nonlinearity
- if layer_i > 0: h = tf.nn.dropout(h, keep_prob=self.keep_prob, seed=self.dropout_seed[layer_i])
- if stop_params_gradient: h = nonlinearity(tf.matmul(h, tf.stop_gradient(self.weights[layer_i])) + tf.stop_gradient(self.biases[layer_i]))
- else: h = nonlinearity(tf.matmul(h, self.weights[layer_i]) + self.biases[layer_i])
- if len(self.out_shape) > 0: h = tf.reshape(h, tf.concat([original_shape[:-1], tf.constant(self.out_shape)], -1))
- else: h = tf.reshape(h, original_shape[:-1])
- if is_eval:
- h, uncertainty = tf.nn.moments(h, 0)
- if self.get_uncertainty: return h, uncertainty
- else: return h
- else:
- return h
-
-
-class EnsembleFeedForwardNet(FeedForwardNet):
- """Custom feed-forward network layer with an ensemble."""
- def __init__(self, name, in_size, out_shape, layers=1, hidden_dim=32, final_nonlinearity=None, get_uncertainty=False, ensemble_size=2, train_sample_count=2, eval_sample_count=2):
- if train_sample_count > ensemble_size: raise Exception("train_sample_count cannot be larger than ensemble size")
- if eval_sample_count > ensemble_size: raise Exception("eval_sample_count cannot be larger than ensemble size")
- self.name = name
- self.in_size = in_size
- self.out_shape = out_shape
- self.out_size = np.prod(out_shape)
- self.layers = layers
- self.hidden_dim = hidden_dim
- self.final_nonlinearity = (lambda x:x) if final_nonlinearity is None else final_nonlinearity
- self.get_uncertainty = get_uncertainty
- self.ensemble_size = ensemble_size
- self.train_sample_count = train_sample_count
- self.eval_sample_count = eval_sample_count
-
- self.weights = [None] * layers
- self.biases = [None] * layers
-
- self.params_list = []
-
- with tf.variable_scope(name):
- for layer_i in range(self.layers):
- in_size = self.hidden_dim
- out_size = self.hidden_dim
- if layer_i == 0: in_size = self.in_size
- if layer_i == self.layers - 1: out_size = self.out_size
- self.weights[layer_i] = tf.get_variable("weights%d" % layer_i, [ensemble_size, in_size, out_size], initializer=tf.contrib.layers.xavier_initializer())
- self.biases[layer_i] = tf.get_variable("bias%d" % layer_i, [ensemble_size, out_size], initializer=tf.constant_initializer(0.0))
- self.params_list += [self.weights[layer_i], self.biases[layer_i]]
-
- def __call__(self, x, stop_params_gradient=False, is_eval=True, ensemble_idxs=None, pre_expanded=None, reduce_mode="none"):
- if pre_expanded is None: pre_expanded = ensemble_idxs is not None
- if ensemble_idxs is None:
- ensemble_idxs = tf.random_shuffle(tf.range(self.ensemble_size))
- ensemble_sample_n = self.eval_sample_count if is_eval else self.train_sample_count
- ensemble_idxs = ensemble_idxs[:ensemble_sample_n]
- else:
- ensemble_sample_n = tf.shape(ensemble_idxs)[0]
-
- weights = [tf.gather(w, ensemble_idxs, axis=0) for w in self.weights]
- biases = [tf.expand_dims(tf.gather(b, ensemble_idxs, axis=0),0) for b in self.biases]
-
- original_shape = tf.shape(x)
- if pre_expanded: h = tf.reshape(x, [-1, ensemble_sample_n, self.in_size])
- else: h = tf.tile(tf.reshape(x, [-1, 1, self.in_size]), [1, ensemble_sample_n, 1])
- for layer_i in range(self.layers):
- nonlinearity = tf.nn.relu if layer_i + 1 < self.layers else self.final_nonlinearity
- if stop_params_gradient: h = nonlinearity(tf.einsum('bri,rij->brj', h, tf.stop_gradient(weights[layer_i])) + tf.stop_gradient(biases[layer_i]))
- else: h = nonlinearity(tf.einsum('bri,rij->brj', h, weights[layer_i]) + biases[layer_i])
-
- if pre_expanded:
- if len(self.out_shape) > 0: h = tf.reshape(h, tf.concat([original_shape[:-1], tf.constant(self.out_shape)], -1))
- else: h = tf.reshape(h, original_shape[:-1])
- else:
- if len(self.out_shape) > 0: h = tf.reshape(h, tf.concat([original_shape[:-1], tf.constant([ensemble_sample_n]), tf.constant(self.out_shape)], -1))
- else: h = tf.reshape(h, tf.concat([original_shape[:-1], tf.constant([ensemble_sample_n])], -1))
-
- if reduce_mode == "none":
- pass
- elif reduce_mode == "random":
- if len(self.out_shape) > 0: h = tf.reduce_sum(h * tf.reshape(tf.one_hot(tf.random_uniform([tf.shape(h)[0]], 0, ensemble_sample_n, dtype=tf.int64), ensemble_sample_n), tf.concat([tf.shape(h)[:1], tf.ones_like(tf.shape(h)[1:-2]), tf.constant([ensemble_sample_n]), tf.constant([1])], 0)), -2)
- else: h = tf.reduce_sum(h * tf.reshape(tf.one_hot(tf.random_uniform([tf.shape(h)[0]], 0, ensemble_sample_n, dtype=tf.int64), ensemble_sample_n), tf.concat([tf.shape(h)[:1], tf.ones_like(tf.shape(h)[1:-1]), tf.constant([ensemble_sample_n])], 0)), -1)
- elif reduce_mode == "mean":
- if len(self.out_shape) > 0: h = tf.reduce_mean(h, -2)
- else: h = tf.reduce_mean(h, -1)
- else: raise Exception("use a valid reduce mode: none, random, or mean")
-
- return h
-
-
-class ReparamNormal(object):
- """Wrapper to make a feedforward network that outputs both mu and logsigma,
- for use in the reparameterization trick."""
- def __init__(self, base_net, name, in_size, out_shape, layers=2, hidden_dim=32, final_nonlinearity=None, ls_start_bias=0.0, final_net=FeedForwardNet, logsigma_min=-5., logsigma_max=2., **kwargs):
- assert layers > 1
- self.main_encoder = base_net(name+"_base", in_size, [hidden_dim], layers, hidden_dim, final_nonlinearity=tf.nn.relu, **kwargs)
- self.mu = final_net(name+"_mu", hidden_dim, out_shape, layers=1, final_nonlinearity=final_nonlinearity, **kwargs)
- self.logsigma = final_net(name+"_logsigma", hidden_dim, out_shape, layers=1, final_nonlinearity=None, **kwargs)
- self.ls_start_bias = ls_start_bias
- self.params_list = self.main_encoder.params_list + self.mu.params_list + self.logsigma.params_list
- self.logsigma_min = logsigma_min
- self.logsigma_max = logsigma_max
-
- def __call__(self, x):
- encoded = self.main_encoder(x)
- mu = self.mu(encoded)
- logsigma = tf.clip_by_value(self.logsigma(encoded) + self.ls_start_bias, self.logsigma_min, self.logsigma_max)
- return mu, logsigma
-
- def l2_loss(self):
- return self.main_encoder.l2_loss() + self.mu.l2_loss() + self.logsigma.l2_loss()
diff --git a/research/steve/replay.py b/research/steve/replay.py
deleted file mode 100644
index 989cc0b2a518398718f36fc6dd8e33cc35083a76..0000000000000000000000000000000000000000
--- a/research/steve/replay.py
+++ /dev/null
@@ -1,109 +0,0 @@
-from __future__ import print_function
-from future import standard_library
-standard_library.install_aliases()
-from builtins import zip
-from builtins import str
-from builtins import object
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import numpy as np
-import pickle
-import multiprocessing
-
-class ReplayBuffer(object):
- """
- Stores frames sampled from the environment, with the ability to sample a batch
- for training.
- """
-
- def __init__(self, max_size, obs_dim, action_dim, roundrobin=True):
- self.max_size = max_size
- self.obs_dim = obs_dim
- self.action_dim = action_dim
- self.roundrobin = roundrobin
-
- self.obs_buffer = np.zeros([max_size, obs_dim])
- self.next_obs_buffer = np.zeros([max_size, obs_dim])
- self.action_buffer = np.zeros([max_size, action_dim])
- self.reward_buffer = np.zeros([max_size])
- self.done_buffer = np.zeros([max_size])
-
- self.count = 0
-
- def random_batch(self, batch_size):
- indices = np.random.randint(0, min(self.count, self.max_size), batch_size)
-
- return (
- self.obs_buffer[indices],
- self.next_obs_buffer[indices],
- self.action_buffer[indices],
- self.reward_buffer[indices],
- self.done_buffer[indices],
- self.count
- )
-
- def add_replay(self, obs, next_obs, action, reward, done):
- if self.count >= self.max_size:
- if self.roundrobin: index = self.count % self.max_size
- else: index = np.random.randint(0, self.max_size)
- else:
- index = self.count
-
- self.obs_buffer[index] = obs
- self.next_obs_buffer[index] = next_obs
- self.action_buffer[index] = action
- self.reward_buffer[index] = reward
- self.done_buffer[index] = done
-
- self.count += 1
-
- def save(self, path, name):
- def _save(datas, fnames):
- print("saving replay buffer...")
- for data, fname in zip(datas, fnames):
- with open("%s.npz"%fname, "wb") as f:
- pickle.dump(data, f)
- with open("%s/%s.count" % (path,name), "wb") as f:
- f.write(str(self.count))
- print("...done saving.")
-
- datas = [
- self.obs_buffer,
- self.next_obs_buffer,
- self.action_buffer,
- self.reward_buffer,
- self.done_buffer
- ]
-
- fnames = [
- "%s/%s.obs_buffer" % (path, name),
- "%s/%s.next_obs_buffer" % (path, name),
- "%s/%s.action_buffer" % (path, name),
- "%s/%s.reward_buffer" % (path, name),
- "%s/%s.done_buffer" % (path, name)
- ]
-
- proc = multiprocessing.Process(target=_save, args=(datas, fnames))
- proc.start()
-
- def load(self, path, name):
- print("Loading %s replay buffer (may take a while...)" % name)
- with open("%s/%s.obs_buffer.npz" % (path,name)) as f: self.obs_buffer = pickle.load(f)
- with open("%s/%s.next_obs_buffer.npz" % (path,name)) as f: self.next_obs_buffer = pickle.load(f)
- with open("%s/%s.action_buffer.npz" % (path,name)) as f: self.action_buffer = pickle.load(f)
- with open("%s/%s.reward_buffer.npz" % (path,name)) as f: self.reward_buffer = pickle.load(f)
- with open("%s/%s.done_buffer.npz" % (path,name)) as f: self.done_buffer = pickle.load(f)
- with open("%s/%s.count" % (path,name), "r") as f: self.count = int(f.read())
diff --git a/research/steve/toy_demo.py b/research/steve/toy_demo.py
deleted file mode 100644
index 859a86f72a9f8162d9aa9ea1bf78e8baa8b15a4e..0000000000000000000000000000000000000000
--- a/research/steve/toy_demo.py
+++ /dev/null
@@ -1,430 +0,0 @@
-from __future__ import division
-from __future__ import print_function
-from builtins import range
-from past.utils import old_div
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import numpy as np
-import scipy
-import matplotlib.pyplot as plt
-import seaborn as sns
-
-### Hyperparameters
-
-NONTERMINAL_STATE_COUNT = 100
-NOISE_AMOUNT = 0.1
-TRAIN_STEPS = 10000
-Q_ENSEMBLE_SIZE = 8
-MODEL_ENSEMBLE_SIZE = 8
-HORIZON = 5
-TRIAL_N = 10
-
-### Helper functions
-
-initial_state = 0
-terminal_state = NONTERMINAL_STATE_COUNT + 1
-nonterminal_state_count = NONTERMINAL_STATE_COUNT
-state_count = NONTERMINAL_STATE_COUNT + 1
-final_reward = NONTERMINAL_STATE_COUNT
-colors = sns.color_palette('husl', 4)
-plt.rcParams["figure.figsize"] = (6,5)
-
-def step(state):
- if state == terminal_state: next_state = terminal_state
- else: next_state = state + 1
-
- if state == terminal_state: reward = 0
- elif state+1 == terminal_state: reward = final_reward
- else: reward = -1
-
- return next_state, reward
-
-def noisy_step(state):
- if state == terminal_state: next_state = terminal_state
- elif np.random.random([]) < NOISE_AMOUNT: next_state = np.random.randint(0, state_count)
- else: next_state = state + 1
-
- if state == terminal_state: reward = 0
- elif state+1 == terminal_state: reward = final_reward
- else: reward = -1
-
- return next_state, reward
-
-def get_error(Q):
- losses = np.square(np.arange(state_count) - Q[:-1])
- return np.mean(losses)
-
-def downsample(array, factor):
- pad_size = np.ceil(old_div(float(array.size),factor))*factor - array.size
- array_padded = np.append(array, np.zeros([pad_size.astype(np.int64)])*np.NaN)
- return scipy.nanmean(array_padded.reshape(-1,factor), axis=1)
-
-
-######################
-### Main experiments
-######################
-
-# Basic Q
-if True:
- print("Running basic Q-learning.")
- trial_results = []
- for run_i in range(TRIAL_N):
- print("Trial %d" % run_i)
- Q = np.random.randint(0,state_count,[state_count+1]).astype(np.float64)
- Q[state_count] = 0
- losses = []
- for step_i in range(TRAIN_STEPS):
- state = np.random.randint(0,state_count)
- next_state, reward = step(state)
- Q[state] = reward + Q[next_state]
- losses.append(get_error(Q))
- trial_results.append(losses)
- print("...complete.\n")
-
- result = np.stack(trial_results, axis=1)
- means = np.mean(result, axis=1)
- stdevs = np.std(result, axis=1)
- plt.plot(means, label="Basic Q-learning", color=colors[0])
- plt.fill_between(np.arange(TRAIN_STEPS), means - stdevs, means + stdevs, alpha=.2, color=colors[0])
- with open('Toy-v1/baseline.csv', 'w') as f:
- data = []
- for frame_i in range(result.shape[0]):
- for loss in result[frame_i]:
- data.append("%f,%f,%f,%f" % (frame_i, frame_i, frame_i, loss))
- f.write("\n".join(data))
-
-# Ensemble Q
-if True:
- print("Running ensemble Q-learning.")
- trial_results = []
- for run_i in range(TRIAL_N):
- print("Trial %d" % run_i)
- Q = np.random.randint(0,state_count,[Q_ENSEMBLE_SIZE, state_count+1]).astype(np.float64)
- Q[:, state_count] = 0
- losses = []
- for step_i in range(TRAIN_STEPS):
- for q_ensemble_i in range(Q_ENSEMBLE_SIZE):
- state = np.random.randint(0,state_count)
- next_state, reward = step(state)
- Q[q_ensemble_i, state] = reward + np.mean(Q[:, next_state])
- losses.append(get_error(np.mean(Q, axis=0)))
- trial_results.append(losses)
- print("...complete.\n")
-
- result = np.stack(trial_results, axis=1)
- means = np.mean(result, axis=1)
- stdevs = np.std(result, axis=1)
- plt.plot(means, label="Ensemble Q-learning", color=colors[1])
- plt.fill_between(np.arange(TRAIN_STEPS), means - stdevs, means + stdevs, alpha=.2, color=colors[1])
-
-# Ensemble MVE-Oracle
-if True:
- print("Running ensemble oracle MVE.")
- trial_results = []
- for run_i in range(TRIAL_N):
- print("Trial %d" % run_i)
- Q = np.random.randint(0,state_count,[Q_ENSEMBLE_SIZE, state_count+1]).astype(np.float64)
- Q[:, state_count] = 0
- losses = []
- for step_i in range(TRAIN_STEPS):
- for q_ensemble_i in range(Q_ENSEMBLE_SIZE):
- state = np.random.randint(0,state_count)
- next_state, reward = step(state)
-
- # MVE rollout
- target = reward
- for _ in range(HORIZON):
- next_state, reward = step(next_state)
- target += reward
- target += np.mean(Q[:,next_state])
-
- Q[q_ensemble_i, state] = target
- losses.append(get_error(np.mean(Q, axis=0)))
- trial_results.append(losses)
- print("...complete.\n")
-
- result = np.stack(trial_results, axis=1)
- means = np.mean(result, axis=1)
- stdevs = np.std(result, axis=1)
- plt.plot(means, label="MVE-oracle", color=colors[2])
- plt.fill_between(np.arange(TRAIN_STEPS), means - stdevs, means + stdevs, alpha=.2, color=colors[2])
- with open('Toy-v1/mve_oracle.csv', 'w') as f:
- data = []
- for frame_i in range(result.shape[0]):
- for loss in result[frame_i]:
- data.append("%f,%f,%f,%f" % (frame_i, frame_i, frame_i, loss))
- f.write("\n".join(data))
-
-# Ensemble MVE-Noisy
-if True:
- print("Running ensemble noisy MVE.")
- trial_results = []
- for run_i in range(TRIAL_N):
- print("Trial %d" % run_i)
- Q = np.random.randint(0,state_count,[Q_ENSEMBLE_SIZE, state_count+1]).astype(np.float64)
- Q[:, state_count] = 0
- losses = []
- for step_i in range(TRAIN_STEPS):
- for q_ensemble_i in range(Q_ENSEMBLE_SIZE):
- state = np.random.randint(0,state_count)
- next_state, reward = step(state)
-
- # MVE rollout
- targets = []
- first_next_state, first_reward = next_state, reward
- for model_ensemble_i in range(MODEL_ENSEMBLE_SIZE):
- next_state, reward = first_next_state, first_reward
- target = reward
- for _ in range(HORIZON):
- next_state, reward = noisy_step(next_state)
- target += reward
- target += np.mean(Q[:,next_state])
- targets.append(target)
-
- Q[q_ensemble_i, state] = np.mean(targets)
- losses.append(get_error(np.mean(Q, axis=0)))
- trial_results.append(losses)
- print("...complete.\n")
-
- result = np.stack(trial_results, axis=1)
- means = np.mean(result, axis=1)
- stdevs = np.std(result, axis=1)
- plt.plot(means, label="MVE-noisy", color=colors[2], linestyle='dotted')
- plt.fill_between(np.arange(TRAIN_STEPS), means - stdevs, means + stdevs, alpha=.2, color=colors[2])
- with open('Toy-v1/mve_noisy.csv', 'w') as f:
- data = []
- for frame_i in range(result.shape[0]):
- for loss in result[frame_i]:
- data.append("%f,%f,%f,%f" % (frame_i, frame_i, frame_i, loss))
- f.write("\n".join(data))
-
-# STEVE-Oracle
-if True:
- print("Running ensemble oracle STEVE.")
- trial_results = []
-
- oracle_q_estimate_errors = []
- oracle_mve_estimate_errors = []
- oracle_steve_estimate_errors = []
- oracle_opt_estimate_errors = []
-
-
- for run_i in range(TRIAL_N):
- print("Trial %d" % run_i)
- Q = np.random.randint(0,state_count,[Q_ENSEMBLE_SIZE, state_count+1]).astype(np.float64)
- Q[:, state_count] = 0
- losses = []
-
- q_estimate_errors = []
- mve_estimate_errors = []
- steve_estimate_errors = []
- opt_estimate_errors = []
- steve_beat_freq= []
-
- for step_i in range(TRAIN_STEPS):
- _q_estimate_errors = []
- _mve_estimate_errors = []
- _steve_estimate_errors = []
- _opt_estimate_errors = []
- _steve_beat_freq = []
-
- for q_ensemble_i in range(Q_ENSEMBLE_SIZE):
- state = np.random.randint(0,state_count)
- next_state, reward = step(state)
-
- # STEVE rollout
- Q_est_mat = np.zeros([HORIZON + 1, Q_ENSEMBLE_SIZE])
- reward_est_mat = np.zeros([HORIZON + 1, 1])
- first_next_state, first_reward = next_state, reward
- next_state, reward = first_next_state, first_reward
- Q_est_mat[0, :] = Q[:, next_state]
- reward_est_mat[0, 0] = reward
- for timestep_i in range(1,HORIZON+1):
- next_state, reward = step(next_state)
- Q_est_mat[timestep_i, :] = Q[:, next_state]
- reward_est_mat[timestep_i, 0] = reward
- all_targets = Q_est_mat + np.cumsum(reward_est_mat, axis=0)
-
- # STEVE weight calculation
- estimates = np.mean(all_targets, axis=1)
- confidences = old_div(1., (np.var(all_targets, axis=1) + 1e-8))
- coefficients = old_div(confidences, np.sum(confidences))
- target = np.sum(estimates * coefficients)
-
- Q[q_ensemble_i, state] = target
-
- true_target = state + 1. if state != terminal_state else 0.
- _q_estimate_errors.append(np.square(estimates[0] - true_target))
- _mve_estimate_errors.append(np.square(estimates[-1] - true_target))
- _steve_estimate_errors.append(np.square(np.sum(estimates * coefficients) - true_target))
- _opt_estimate_errors.append(np.min(np.square(estimates - true_target)))
-
- losses.append(get_error(np.mean(Q, axis=0)))
- q_estimate_errors.append(np.mean(_q_estimate_errors))
- mve_estimate_errors.append(np.mean(_mve_estimate_errors))
- steve_estimate_errors.append(np.mean(_steve_estimate_errors))
- opt_estimate_errors.append(np.mean(_opt_estimate_errors))
- trial_results.append(losses)
- oracle_q_estimate_errors.append(q_estimate_errors)
- oracle_mve_estimate_errors.append(mve_estimate_errors)
- oracle_steve_estimate_errors.append(steve_estimate_errors)
- oracle_opt_estimate_errors.append(opt_estimate_errors)
- print("...complete.\n")
-
- result = np.stack(trial_results, axis=1)
- means = np.mean(result, axis=1)
- stdevs = np.std(result, axis=1)
- plt.plot(means, label="STEVE-oracle", color=colors[3])
- plt.fill_between(np.arange(TRAIN_STEPS), means - stdevs, means + stdevs, alpha=.2, color=colors[3])
- with open('Toy-v1/steve_oracle.csv', 'w') as f:
- data = []
- for frame_i in range(result.shape[0]):
- for loss in result[frame_i]:
- data.append("%f,%f,%f,%f" % (frame_i, frame_i, frame_i, loss))
- f.write("\n".join(data))
-
-# STEVE-Noisy
-if True:
- print("Running ensemble noisy STEVE.")
- trial_results = []
-
- noisy_q_estimate_errors = []
- noisy_mve_estimate_errors = []
- noisy_steve_estimate_errors = []
- noisy_opt_estimate_errors = []
- noisy_steve_beat_freq = []
-
- for run_i in range(TRIAL_N):
- print("Trial %d" % run_i)
- Q = np.random.randint(0,state_count,[Q_ENSEMBLE_SIZE, state_count+1]).astype(np.float64)
- Q[:, state_count] = 0
- losses = []
-
- q_estimate_errors = []
- mve_estimate_errors = []
- steve_estimate_errors = []
- opt_estimate_errors = []
- steve_beat_freq= []
-
- for step_i in range(TRAIN_STEPS):
- _q_estimate_errors = []
- _mve_estimate_errors = []
- _steve_estimate_errors = []
- _opt_estimate_errors = []
- _steve_beat_freq = []
- for q_ensemble_i in range(Q_ENSEMBLE_SIZE):
- state = np.random.randint(0,state_count)
- next_state, reward = step(state)
-
- # STEVE rollout
- Q_est_mat = np.zeros([HORIZON + 1, MODEL_ENSEMBLE_SIZE, Q_ENSEMBLE_SIZE])
- reward_est_mat = np.zeros([HORIZON + 1, MODEL_ENSEMBLE_SIZE, 1])
- first_next_state, first_reward = next_state, reward
- for model_ensemble_i in range(MODEL_ENSEMBLE_SIZE):
- next_state, reward = first_next_state, first_reward
- Q_est_mat[0, model_ensemble_i, :] = Q[:, next_state]
- reward_est_mat[0, model_ensemble_i, 0] = reward
- for timestep_i in range(1,HORIZON+1):
- next_state, reward = noisy_step(next_state)
- Q_est_mat[timestep_i, model_ensemble_i, :] = Q[:, next_state]
- reward_est_mat[timestep_i, model_ensemble_i, 0] = reward
- all_targets = Q_est_mat + np.cumsum(reward_est_mat, axis=0)
-
- # STEVE weight calculation
- all_targets = np.reshape(all_targets, [HORIZON+1, MODEL_ENSEMBLE_SIZE * Q_ENSEMBLE_SIZE])
- estimates = np.mean(all_targets, axis=1)
- confidences = old_div(1., (np.var(all_targets, axis=1) + 1e-8))
- coefficients = old_div(confidences, np.sum(confidences))
- target = np.sum(estimates * coefficients)
- # target = estimates[0]
-
- Q[q_ensemble_i, state] = target
-
- true_target = state + 1. if state != terminal_state else 0.
- _q_estimate_errors.append(np.square(estimates[0] - true_target))
- _mve_estimate_errors.append(np.square(estimates[-1] - true_target))
- _steve_estimate_errors.append(np.square(np.sum(estimates * coefficients) - true_target))
- _opt_estimate_errors.append(np.min(np.square(estimates - true_target)))
- _steve_beat_freq.append(float(np.square(estimates[0] - true_target) > np.square(target - true_target)))
-
- losses.append(get_error(np.mean(Q, axis=0)))
- q_estimate_errors.append(np.mean(_q_estimate_errors))
- mve_estimate_errors.append(np.mean(_mve_estimate_errors))
- steve_estimate_errors.append(np.mean(_steve_estimate_errors))
- opt_estimate_errors.append(np.mean(_opt_estimate_errors))
- steve_beat_freq.append(np.mean(_steve_beat_freq))
- trial_results.append(losses)
- noisy_q_estimate_errors.append(q_estimate_errors)
- noisy_mve_estimate_errors.append(mve_estimate_errors)
- noisy_steve_estimate_errors.append(steve_estimate_errors)
- noisy_opt_estimate_errors.append(opt_estimate_errors)
- noisy_steve_beat_freq.append(steve_beat_freq)
-
- print("...complete.\n")
-
- result = np.stack(trial_results, axis=1)
- means = np.mean(result, axis=1)
- stdevs = np.std(result, axis=1)
- plt.plot(means, label="STEVE-noisy", color=colors[3], linestyle='dotted')
- plt.fill_between(np.arange(TRAIN_STEPS), means - stdevs, means + stdevs, alpha=.2, color=colors[3])
- with open('Toy-v1/steve_noisy.csv', 'w') as f:
- data = []
- for frame_i in range(result.shape[0]):
- for loss in result[frame_i]:
- data.append("%f,%f,%f,%f" % (frame_i, frame_i, frame_i, loss))
- f.write("\n".join(data))
-
-# ### Display results
-# plt.title("Comparison of convergence rates")
-# plt.legend()
-# plt.savefig("comparison.pdf")
-# plt.show()
-#
-# ### Display secondary results - error comparison
-# DOWNSAMPLE = 50
-# colors = sns.color_palette('husl', 8)
-# for i, (error_curve, label) in enumerate([
-# (oracle_q_estimate_errors, "Oracle Q error"),
-# (oracle_mve_estimate_errors, "Oracle MVE error"),
-# (oracle_steve_estimate_errors, "Oracle STEVE error"),
-# # (oracle_opt_estimate_errors, "Oracle minimum single-estimate error"),
-# ]):
-# result = np.stack(error_curve, axis=1)
-# means = downsample(np.mean(result, axis=1), DOWNSAMPLE)
-# stdevs = downsample(np.std(result, axis=1), DOWNSAMPLE)
-# plt.plot(means, label=label, color=colors[i])
-# plt.fill_between(np.arange(means.shape[0]), means - stdevs, means + stdevs, alpha=.2, color=colors[i])
-#
-# plt.title("Comparison of errors for oracle dynamics")
-# plt.legend()
-# plt.show()
-#
-# for i, (error_curve, label) in enumerate([
-# (noisy_q_estimate_errors, "Noisy Q error"),
-# (noisy_mve_estimate_errors, "Noisy MVE error"),
-# (noisy_steve_estimate_errors, "Noisy STEVE error"),
-# # (noisy_opt_estimate_errors, "Noisy minimum single-estimate error"),
-# # (trial_steve_beat_freq, "STEVE beat freq"),
-# ]):
-# result = np.stack(error_curve, axis=1)
-# means = downsample(np.mean(result, axis=1), DOWNSAMPLE)
-# stdevs = downsample(np.std(result, axis=1), DOWNSAMPLE)
-# plt.plot(means, label=label, color=colors[i])
-# plt.fill_between(np.arange(means.shape[0]), means - stdevs, means + stdevs, alpha=.2, color=colors[i])
-#
-# plt.title("Comparison of errors for noisy dynamics")
-# plt.legend()
-# plt.show()
\ No newline at end of file
diff --git a/research/steve/util.py b/research/steve/util.py
deleted file mode 100644
index bf0abec0ae193a3ba067a47c895f7cd21593e7b8..0000000000000000000000000000000000000000
--- a/research/steve/util.py
+++ /dev/null
@@ -1,164 +0,0 @@
-from __future__ import division
-from future import standard_library
-standard_library.install_aliases()
-from builtins import str
-from builtins import range
-from past.utils import old_div
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import numpy as np
-import tensorflow as tf
-import os, random, gc, math, re
-import multiprocessing, types, shutil, pickle, json
-from collections import defaultdict, MutableMapping
-
-def tanh_sample_info(mu, logsigma, stop_action_gradient=False, n_samples=1):
- if n_samples > 1:
- mu = tf.expand_dims(mu, 2)
- logsigma = tf.expand_dims(logsigma, 2)
- sample_shape = tf.concat([tf.shape(mu), n_samples], 0)
- else:
- sample_shape = tf.shape(mu)
-
- flat_act = mu + tf.random_normal(sample_shape) * tf.exp(logsigma)
- if stop_action_gradient: flat_act = tf.stop_gradient(flat_act)
- normalized_dist_t = (flat_act - mu) * tf.exp(-logsigma) # ... x D
- quadratic = - 0.5 * tf.reduce_sum(normalized_dist_t ** 2, axis=-1) # ... x (None)
- log_z = tf.reduce_sum(logsigma, axis=-1) # ... x (None)
- D_t = tf.cast(tf.shape(mu)[-1], tf.float32)
- log_z += 0.5 * D_t * np.log(2 * np.pi)
- flat_ll = quadratic - log_z
-
- scaled_act = tf.tanh(flat_act)
- corr = tf.reduce_sum(tf.log(1. - tf.square(scaled_act) + 1e-6), axis=-1)
- scaled_ll = flat_ll - corr
- return flat_act, flat_ll, scaled_act, scaled_ll
-
-def tf_cheating_contcartpole(state, action):
- gravity = 9.8
- masscart = 1.0
- masspole = 0.1
- total_mass = (masspole + masscart)
- length = 0.5 # actually half the pole's length
- polemass_length = (masspole * length)
- force_mag = 10.0
- tau = 0.02 # seconds between state updates
-
- # Angle at which to fail the episode
- theta_threshold_radians = 12 * 2 * math.pi / 360
- x_threshold = 2.4
-
- x, x_dot, theta, theta_dot = tf.split(state, 4, axis=-1)
- done = tf.logical_or(x < -x_threshold,
- tf.logical_or(x > x_threshold,
- tf.logical_or(theta < -theta_threshold_radians,
- theta > theta_threshold_radians)))
-
- force = force_mag * action
- costheta = tf.cos(theta)
- sintheta = tf.sin(theta)
- temp = old_div((force + polemass_length * theta_dot * theta_dot * sintheta), total_mass)
- thetaacc = old_div((gravity * sintheta - costheta* temp), (length * (old_div(4.0,3.0) - masspole * costheta * costheta / total_mass)))
- xacc = temp - polemass_length * thetaacc * costheta / total_mass
- x = x + tau * x_dot
- x_dot = x_dot + tau * xacc
- theta = theta + tau * theta_dot
- theta_dot = theta_dot + tau * thetaacc
- state = tf.concat([x,x_dot,theta,theta_dot], -1)
- done = tf.squeeze(tf.cast(done, tf.float32), -1)
- reward = 1.0 - done
- done *= 0.
- return state, reward, done
-
-def create_directory(dir):
- dir_chunks = dir.split("/")
- for i in range(len(dir_chunks)):
- partial_dir = "/".join(dir_chunks[:i+1])
- try:
- os.makedirs(partial_dir)
- except OSError:
- pass
- return dir
-
-def create_and_wipe_directory(dir):
- shutil.rmtree(create_directory(dir))
- create_directory(dir)
-
-def wipe_file(fname):
- with open(fname, "w") as f:
- f.write("")
- return fname
-
-def get_largest_epoch_in_dir(dir, saveid):
- reg_matches = [re.findall('\d+_%s'%saveid,filename) for filename in os.listdir(dir)]
- epoch_labels = [int(regmatch[0].split("_")[0]) for regmatch in reg_matches if regmatch]
- if len(epoch_labels) == 0: return False
- return max(epoch_labels)
-
-def wipe_all_but_largest_epoch_in_dir(dir, saveid):
- largest = get_largest_epoch_in_dir(dir, saveid)
- reg_matches = [(filename, re.findall('\d+_%s'%saveid,filename)) for filename in os.listdir(dir)]
- for filename, regmatch in reg_matches:
- if regmatch and int(regmatch[0].split("_")[0]) != largest:
- os.remove(os.path.join(dir,filename))
-
-class ConfigDict(dict):
- def __init__(self, loc=None, ghost=False):
- self._dict = defaultdict(lambda :False)
- self.ghost = ghost
- if loc:
- with open(loc) as f: raw = json.load(f)
- if "inherits" in raw and raw["inherits"]:
- for dep_loc in raw["inherits"]:
- self.update(ConfigDict(dep_loc))
- if "updates" in raw and raw["updates"]:
- self.update(raw["updates"], include_all=True)
-
- def __getitem__(self, key):
- return self._dict[key]
-
- def __setitem__(self, key, value):
- self._dict[key] = value
-
- def __str__(self):
- return str(dict(self._dict))
-
- def __repr__(self):
- return str(dict(self._dict))
-
- def __iter__(self):
- return self._dict.__iter__()
-
- def __bool__(self):
- return bool(self._dict)
-
- def __nonzero__(self):
- return bool(self._dict)
-
- def update(self, dictlike, include_all=False):
- for key in dictlike:
- value = dictlike[key]
- if isinstance(value, dict):
- if key[0] == "*": # this means only override, do not set
- key = key[1:]
- ghost = True
- else:
- ghost = False
- if not include_all and isinstance(value, ConfigDict) and key not in self._dict and value.ghost: continue
- if key not in self._dict: self._dict[key] = ConfigDict(ghost=ghost)
- self._dict[key].update(value)
- else:
- self._dict[key] = value
diff --git a/research/steve/valuerl.py b/research/steve/valuerl.py
deleted file mode 100644
index 4819dd08c2f813eb524c56ebadec25a24115223b..0000000000000000000000000000000000000000
--- a/research/steve/valuerl.py
+++ /dev/null
@@ -1,307 +0,0 @@
-from __future__ import division
-from builtins import zip
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import tensorflow as tf
-import numpy as np
-import nn
-import util
-from learner import CoreModel
-
-
-class ValueRL(CoreModel):
- """
- Learn a state-action value function and its corresponding policy.
- """
-
- @property
- def saveid(self):
- return "valuerl"
-
- def create_params(self, env_config, learner_config):
- self.obs_dim = np.prod(env_config["obs_dims"])
- self.action_dim = env_config["action_dim"]
- self.reward_scale = env_config["reward_scale"]
- self.discount = env_config["discount"]
-
- self.hidden_dim = learner_config["hidden_dim"]
- self.bayesian_config = learner_config["bayesian"]
- self.value_expansion = learner_config["value_expansion"]
- self.explore_chance = learner_config["ddpg_explore_chance"]
-
- with tf.variable_scope(self.name):
- self.policy = nn.FeedForwardNet('policy', self.obs_dim, [self.action_dim], layers=4, hidden_dim=self.hidden_dim, get_uncertainty=False)
-
- if self.bayesian_config:
- self.Q = nn.EnsembleFeedForwardNet('Q', self.obs_dim + self.action_dim, [], layers=4, hidden_dim=self.hidden_dim, get_uncertainty=True, ensemble_size=self.bayesian_config["ensemble_size"], train_sample_count=self.bayesian_config["train_sample_count"], eval_sample_count=self.bayesian_config["eval_sample_count"])
- self.old_Q = nn.EnsembleFeedForwardNet('old_q', self.obs_dim + self.action_dim, [], layers=4, hidden_dim=self.hidden_dim, get_uncertainty=True, ensemble_size=self.bayesian_config["ensemble_size"], train_sample_count=self.bayesian_config["train_sample_count"], eval_sample_count=self.bayesian_config["eval_sample_count"])
- else:
- self.Q = nn.FeedForwardNet('Q', self.obs_dim + self.action_dim, [], layers=4, hidden_dim=self.hidden_dim, get_uncertainty=True)
- self.old_Q = nn.FeedForwardNet('old_q', self.obs_dim + self.action_dim, [], layers=4, hidden_dim=self.hidden_dim, get_uncertainty=True)
-
- self.policy_params = [v for v in tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope=self.name) if "policy" in v.name]
- self.Q_params = [v for v in tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope=self.name) if "Q" in v.name]
- self.agent_params = tf.get_collection(tf.GraphKeys.GLOBAL_VARIABLES, scope=self.name)
-
- self.copy_to_old_ops = [tf.assign(p_old, p) for p_old, p in zip(self.old_Q.params_list, self.Q.params_list)]
- self.assign_epoch_op = [tf.assign(self.epoch_n, self.epoch_n_placeholder), tf.assign(self.update_n, self.update_n_placeholder), tf.assign(self.frame_n, self.frame_n_placeholder), tf.assign(self.hours, self.hours_placeholder)]
-
- def update_epoch(self, sess, epoch, updates, frames, hours):
- sess.run(self.assign_epoch_op, feed_dict={self.epoch_n_placeholder: int(epoch), self.update_n_placeholder: int(updates), self.frame_n_placeholder: int(frames), self.hours_placeholder: float(hours)})
-
- def copy_to_old(self, sess):
- sess.run(self.copy_to_old_ops)
-
- def build_evalution_graph(self, obs, get_full_info=False, mode="regular", n_samples=1):
- assert mode in {"regular", "explore", "exploit"}
- policy_actions_pretanh = self.policy(obs)
-
- if mode == "regular" or mode == "exploit":
- policy_actions = tf.tanh(policy_actions_pretanh)
- elif mode == "explore":
- _, _, exploring_policy_actions, _ = util.tanh_sample_info(policy_actions_pretanh, tf.zeros_like(policy_actions_pretanh), n_samples=n_samples)
- policy_actions = tf.where(tf.random_uniform(tf.shape(exploring_policy_actions)) < self.explore_chance, x=exploring_policy_actions, y=tf.tanh(policy_actions_pretanh))
- else: raise Exception('this should never happen')
-
- if get_full_info: return policy_actions_pretanh, policy_actions
- else: return policy_actions
-
- def build_training_graph(self, obs, next_obs, empirical_actions, rewards, dones, data_size, worldmodel=None):
- average_model_use = tf.constant(0.)
- empirical_Q_info = tf.concat([obs, empirical_actions], 1)
-
- if worldmodel is None:
- policy_action_pretanh, policy_actions = self.build_evalution_graph(obs, get_full_info=True)
- policy_Q_info = tf.concat([obs, policy_actions], 1)
- state_value_estimate = self.Q(policy_Q_info, reduce_mode="mean")
-
- next_policy_actions = self.build_evalution_graph(next_obs)
- policy_next_Q_info = tf.concat([next_obs, next_policy_actions], 1)
- next_Q_estimate = self.old_Q(policy_next_Q_info, reduce_mode="mean")
-
- Q_guess = self.Q(empirical_Q_info, is_eval=False, reduce_mode="random")
- Q_target = rewards * self.reward_scale + self.discount * next_Q_estimate * (1. - dones)
-
- policy_losses = -state_value_estimate
- Q_losses = .5 * tf.square( Q_guess - tf.stop_gradient(Q_target) )
-
- else:
- targets, confidence, Q_guesses, reach_probs = self.build_Q_expansion_graph(next_obs, rewards, dones, worldmodel, rollout_len=self.value_expansion["rollout_len"], model_ensembling=worldmodel.bayesian_config is not False)
-
- # targets is a 3D matrix: [batch_i, start_timestep, end_timestep]. here, we reduce out the last dimension, turning
- # it into a [batch_i, start_timestep] matrix. in other words, we are taking a bunch of candidate targets and reducing
- # them into a single target. the four options here correspond to the four ways to do that reduction.
- if self.value_expansion["mean_k_return"]:
- target_counts = self.value_expansion["rollout_len"]+1 - tf.reshape(tf.range(self.value_expansion["rollout_len"]+1), [1, self.value_expansion["rollout_len"]+1])
- k_returns = tf.reduce_sum(targets, 2) / tf.cast(target_counts, tf.float32)
- elif self.value_expansion["lambda_return"]:
- cont_coeffs = self.value_expansion["lambda_return"] ** tf.cast(tf.reshape(tf.range(self.value_expansion["rollout_len"]+1), [1,1,self.value_expansion["rollout_len"]+1]), tf.float32)
- stop_coeffs = tf.concat([(1 - self.value_expansion["lambda_return"]) * tf.ones_like(targets)[:,:,:-1], tf.ones_like(targets)[:,:,-1:]], 2)
- k_returns = tf.reduce_sum(targets * stop_coeffs * cont_coeffs, 2)
- elif self.value_expansion["steve_reweight"]:
- k_returns = tf.reduce_sum(targets * confidence, 2)
- average_model_use = 1. - tf.reduce_mean(confidence[:,0,0])
- else:
- # MVE objective: just take the last one
- k_returns = targets[:,:,-1]
-
- # now we have [batch_i, start_timestep]. if we are using the TDK trick, then we want to use all of the targets,
- # so we construct a corresponding [batch_i, start_timestep] matrix of guesses. otherwise, we just take the targets
- # for the first timestep.
- Q_guess = self.Q(empirical_Q_info, is_eval=False, reduce_mode="random")
- if self.value_expansion["tdk_trick"]:
- Q_guess = tf.concat([tf.expand_dims(Q_guess, 1), Q_guesses], 1)
- reach_probs = tf.concat([tf.expand_dims(tf.ones_like(reach_probs[:,0]), 1), reach_probs[:,:-1]], 1)
- Q_target = k_returns
- else:
- # non-TDK trick means we just take the first one
- Q_target = k_returns[:,0]
-
- policy_action_pretanh, policy_actions = self.build_evalution_graph(obs, get_full_info=True)
- policy_Q_info = tf.concat([obs, policy_actions], 1)
- state_value_estimate = self.Q(policy_Q_info, stop_params_gradient=True, reduce_mode="mean")
-
- policy_losses = -state_value_estimate
- Q_losses = .5 * tf.square( Q_guess - tf.stop_gradient(Q_target) )
- if self.value_expansion["tdk_trick"]: Q_losses *= reach_probs # we downscale the various TDK-trick losses by
- # the likelihood of actually reaching the state
- # from which the guess was made
- policy_loss = tf.reduce_mean(policy_losses)
- Q_loss = tf.reduce_mean(Q_losses)
- policy_reg_loss = tf.reduce_mean(tf.square(policy_action_pretanh)) * .001 # a small regularization to make sure the
- # tanh does not saturate
-
- # anything in inspect gets logged
- inspect = (policy_loss, Q_loss, policy_reg_loss, average_model_use)
-
- return (policy_loss + policy_reg_loss, Q_loss), inspect
-
-
- def build_Q_expansion_graph(self, obs, first_rewards, first_done, worldmodel, rollout_len=1, model_ensembling=False):
- ### this sets up the machinery for having multiple parallel rollouts, each of which has a single consistent transition
- ensemble_idxs, transition_sample_n, reward_sample_n = worldmodel.get_ensemble_idx_info()
- q_sample_n = self.bayesian_config["eval_sample_count"] if self.bayesian_config is not False else 1
- first_rewards = tf.tile(tf.expand_dims(tf.expand_dims(first_rewards,1),1), [1,transition_sample_n,reward_sample_n])
- first_rewards.set_shape([None, transition_sample_n, reward_sample_n])
- if model_ensembling:
- obs = tf.tile(tf.expand_dims(obs,1), [1,transition_sample_n,1])
- obs.set_shape([None, transition_sample_n, self.obs_dim])
- first_done = tf.tile(tf.expand_dims(first_done, 1), [1, transition_sample_n])
- first_done.set_shape([None, transition_sample_n])
-
- ### below, we use a while loop to actually do the iterative model rollout
- extra_info = worldmodel.init_extra_info(obs)
-
- action_ta = tf.TensorArray(size=rollout_len, dynamic_size=False, dtype=tf.float32)
- obs_ta = tf.TensorArray(size=rollout_len, dynamic_size=False, dtype=tf.float32)
- done_ta = tf.TensorArray(size=rollout_len, dynamic_size=False, dtype=tf.float32)
- extra_info_ta =tf.TensorArray(size=rollout_len, dynamic_size=False, dtype=tf.float32)
-
- def rollout_loop_body(r_i, xxx_todo_changeme):
- (obs, done, extra_info, action_ta, obs_ta, dones_ta, extra_info_ta) = xxx_todo_changeme
- action_pretanh, action = self.build_evalution_graph(tf.stop_gradient(obs), get_full_info=True)
-
- if model_ensembling:
- next_obs, next_dones, next_extra_info = worldmodel.transition(obs, action, extra_info, ensemble_idxs=ensemble_idxs)
- else:
- next_obs, next_dones, next_extra_info = worldmodel.transition(obs, action, extra_info)
- next_obs = tf.reduce_mean(next_obs, -2)
- next_dones = tf.reduce_mean(next_dones, -1)
-
- action_ta = action_ta.write(r_i, action)
- obs_ta = obs_ta.write(r_i, obs)
- dones_ta = dones_ta.write(r_i, done)
- extra_info_ta = extra_info_ta.write(r_i, extra_info)
- return r_i+1, (next_obs, next_dones, next_extra_info, action_ta, obs_ta, dones_ta, extra_info_ta)
-
- _, (final_obs, final_done, final_extra_info, action_ta, obs_ta, done_ta, extra_info_ta) = tf.while_loop(
- lambda r_i, _: r_i < rollout_len,
- rollout_loop_body,
- [0, (obs, first_done, extra_info, action_ta, obs_ta, done_ta, extra_info_ta)]
- )
-
- final_action_pretanh, final_action = self.build_evalution_graph(tf.stop_gradient(final_obs), get_full_info=True)
-
- ### compile the TensorArrays into useful tensors
- obss = obs_ta.stack()
- obss = tf.reshape(obss, tf.stack([rollout_len, -1, transition_sample_n, self.obs_dim]))
- obss = tf.transpose(obss, [1, 0, 2, 3])
- final_obs = tf.reshape(final_obs, tf.stack([-1, 1, transition_sample_n, self.obs_dim]))
- all_obss = tf.concat([obss, final_obs],1)
- next_obss = all_obss[:,1:]
-
- dones = done_ta.stack()
- dones = tf.reshape(dones, tf.stack([rollout_len, -1, transition_sample_n]))
- dones = tf.transpose(dones, [1, 0, 2])
- final_done = tf.reshape(final_done, tf.stack([-1, 1, transition_sample_n]))
- all_dones = tf.concat([dones, final_done],1)
-
- actions = action_ta.stack()
- actions = tf.reshape(actions, tf.stack([rollout_len, -1, transition_sample_n, self.action_dim]))
- actions = tf.transpose(actions , [1, 0, 2, 3])
- final_action = tf.reshape(final_action, tf.stack([-1, 1, transition_sample_n, self.action_dim]))
- all_actions = tf.concat([actions, final_action],1)
-
- continue_probs = tf.cumprod(1. - all_dones, axis=1)
- rewards = worldmodel.get_rewards(obss, actions, next_obss)
- rawrew = rewards = tf.concat([tf.expand_dims(first_rewards, 1), rewards],1)
-
- ### TDK trick means we have to guess at every timestep
- if self.value_expansion["tdk_trick"]:
- guess_info = tf.concat([obss,actions], -1)
- Q_guesses = self.Q(guess_info, reduce_mode="random")
- Q_guesses = tf.reduce_mean(Q_guesses, -1) # make it so there's only one guess per rollout length, which is the mean of the guesses under all the various model rollouts
- reached_this_point_to_guess_prob = tf.reduce_mean(continue_probs, -1)
- else:
- Q_guesses = None
- reached_this_point_to_guess_prob = None
-
- ### use the Q function at every timestep to get value estimates
- target_info = tf.concat([all_obss, all_actions], -1)
- Q_targets = self.old_Q(target_info, reduce_mode="none")
-
- rollout_frames = rollout_len + 1 # if we take N steps, we have N+1 frames
-
- ### create "decay-exponent matrix" of size [1,ROLLOUT_FRAMES,ROLLOUT_FRAMES,1]. the first ROLLOUT_FRAMES corresponds to the index of the source, the second to the target.
- ts_count_mat = (tf.cast(tf.reshape(tf.range(rollout_frames), [1, rollout_frames]) - tf.reshape(tf.range(rollout_frames), [rollout_frames, 1]), tf.float32))
- reward_coeff_matrix = tf.matrix_band_part(tf.ones([rollout_frames, rollout_frames]), 0, -1) * self.discount ** ts_count_mat
- value_coeff_matrix = tf.matrix_band_part(tf.ones([rollout_frames, rollout_frames]), 0, -1) * self.discount ** (1. + ts_count_mat)
- reward_coeff_matrix = tf.reshape(reward_coeff_matrix, [1, rollout_frames, rollout_frames, 1, 1])
- value_coeff_matrix = tf.reshape(value_coeff_matrix, [1, rollout_frames, rollout_frames, 1, 1])
-
- ### similarly, create a "done" matrix
- shifted_continue_probs = tf.concat([tf.expand_dims(tf.ones_like(continue_probs[:,0]),1), continue_probs[:,:-1]], 1)
- reward_continue_matrix = tf.expand_dims(shifted_continue_probs, 1) / tf.expand_dims(shifted_continue_probs+1e-8, 2)
- value_continue_matrix = tf.expand_dims(continue_probs, 1) / tf.expand_dims(shifted_continue_probs+1e-8, 2)
- reward_continue_matrix = tf.expand_dims(reward_continue_matrix, -1)
- value_continue_matrix = tf.expand_dims(value_continue_matrix, -1)
-
- ### apply the discounting factors to the rewards and values
- rewards = tf.expand_dims(rewards, 1) * reward_coeff_matrix * reward_continue_matrix
- rewards = tf.cumsum(rewards, axis=2)
- values = tf.expand_dims(Q_targets, 1) * value_coeff_matrix * value_continue_matrix
-
- ### compute the targets using the Bellman equation
- sampled_targets = tf.expand_dims(rewards,-2) * self.reward_scale + tf.expand_dims(values,-1)
-
- ### flatten out the various sources of variance (transition, reward, and Q-function ensembles) to get a set of estimates for each candidate target
- sampled_targets = tf.reshape(sampled_targets, tf.stack([-1, rollout_frames, rollout_frames, transition_sample_n * reward_sample_n * q_sample_n]))
-
- ### compute the mean and variance for each candidate target
- target_means, target_variances = tf.nn.moments(sampled_targets, 3)
-
- ### compute the confidence, either using the full covariance matrix, or approximating all the estimators as independent
- if self.value_expansion["covariances"]:
- targetdiffs = sampled_targets - tf.expand_dims(target_means,3)
- target_covariances = tf.einsum("abij,abjk->abik", targetdiffs, tf.transpose(targetdiffs, [0,1,3,2]))
- target_confidence = tf.squeeze(tf.matrix_solve(target_covariances + tf.expand_dims(tf.expand_dims(tf.matrix_band_part(tf.ones(tf.shape(target_covariances)[-2:]),0,0) * 1e-3,0),0), tf.ones(tf.concat([tf.shape(target_covariances)[:-1], tf.constant([1])],0))),-1)
- else:
- target_confidence = 1./(target_variances + 1e-8)
-
- ### normalize so weights sum to 1
- target_confidence *= tf.matrix_band_part(tf.ones([1, rollout_frames, rollout_frames]), 0, -1)
- target_confidence = target_confidence / tf.reduce_sum(target_confidence, axis=2, keepdims=True)
-
- ### below here is a bunch of debugging Print statements that I use as a sanity check:
- # target_confidence = tf.Print(target_confidence, [], message="raw rewards")
- # target_confidence = tf.Print(target_confidence, [rawrew[0,:,0,0]], summarize=rollout_len+1)
- # target_means = tf.Print(target_means, [], message="\n", summarize=rollout_len+1)
- # target_means = tf.Print(target_means, [(1. - all_dones)[0,:,0]], message="contin", summarize=rollout_len+1)
- # target_means = tf.Print(target_means, [continue_probs[0,:,0]], message="cum_contin", summarize=rollout_len+1)
- # target_means = tf.Print(target_means, [shifted_continue_probs[0,:,0]], message="shifted contin", summarize=rollout_len+1)
- # target_means = tf.Print(target_means, [], message="reward_coeff")
- # for i in range(rollout_len+1): target_means = tf.Print(target_means, [reward_coeff_matrix[0,i,:,0,0]], summarize=rollout_len+1)
- # target_means = tf.Print(target_means, [], message="reward_continue")
- # for i in range(rollout_len+1): target_means = tf.Print(target_means, [reward_continue_matrix[0,i,:,0,0]], summarize=rollout_len+1)
- # target_means = tf.Print(target_means, [], message="value_coeff")
- # for i in range(rollout_len+1): target_means = tf.Print(target_means, [value_coeff_matrix[0,i,:,0,0]], summarize=rollout_len+1)
- # target_means = tf.Print(target_means, [], message="value_continue")
- # for i in range(rollout_len+1): target_means = tf.Print(target_means, [value_continue_matrix[0,i,:,0,0]], summarize=rollout_len+1)
- # target_confidence = tf.Print(target_confidence, [], message="rewards")
- # for i in range(rollout_len+1): target_confidence = tf.Print(target_confidence, [rewards[0,i,:,0,0]], summarize=rollout_len+1)
- # target_confidence = tf.Print(target_confidence, [], message="target Qs")
- # target_confidence = tf.Print(target_confidence, [Q_targets[0,:,0,0]], summarize=rollout_len+1)
- # target_confidence = tf.Print(target_confidence, [], message="values")
- # for i in range(rollout_len+1): target_confidence = tf.Print(target_confidence, [values[0,i,:,0,0]], summarize=rollout_len+1)
- # target_confidence = tf.Print(target_confidence, [], message="target_means")
- # for i in range(rollout_len+1): target_confidence = tf.Print(target_confidence, [target_means[0,i,:]], summarize=rollout_len+1)
- # target_confidence = tf.Print(target_confidence, [], message="target_variance")
- # for i in range(rollout_len+1): target_confidence = tf.Print(target_confidence, [target_variances[0,i,:]], summarize=rollout_len+1)
- # target_confidence = tf.Print(target_confidence, [], message="target_confidence")
- # for i in range(rollout_len+1): target_confidence = tf.Print(target_confidence, [target_confidence[0,i,:]], summarize=rollout_len+1)
- # target_means = tf.Print(target_means, [target_confidence, action_lls, tf.shape(Q_targets)], message="\n\n", summarize=10)
-
- return target_means, target_confidence, Q_guesses, reached_this_point_to_guess_prob
\ No newline at end of file
diff --git a/research/steve/valuerl_learner.py b/research/steve/valuerl_learner.py
deleted file mode 100644
index a3c6308f83b02f065757f4d7c56766911719f541..0000000000000000000000000000000000000000
--- a/research/steve/valuerl_learner.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import tensorflow as tf
-import numpy as np
-import os
-
-from learner import Learner
-from valuerl import ValueRL
-from worldmodel import DeterministicWorldModel
-
-class ValueRLLearner(Learner):
- """
- ValueRL-specific training loop details.
- """
-
- def learner_name(self): return "valuerl"
-
- def make_loader_placeholders(self):
- self.obs_loader = tf.placeholder(tf.float32, [self.learner_config["batch_size"], np.prod(self.env_config["obs_dims"])])
- self.next_obs_loader = tf.placeholder(tf.float32, [self.learner_config["batch_size"], np.prod(self.env_config["obs_dims"])])
- self.action_loader = tf.placeholder(tf.float32, [self.learner_config["batch_size"], self.env_config["action_dim"]])
- self.reward_loader = tf.placeholder(tf.float32, [self.learner_config["batch_size"]])
- self.done_loader = tf.placeholder(tf.float32, [self.learner_config["batch_size"]])
- self.datasize_loader = tf.placeholder(tf.float64, [])
- return [self.obs_loader, self.next_obs_loader, self.action_loader, self.reward_loader, self.done_loader, self.datasize_loader]
-
- def make_core_model(self):
- if self.config["model_config"] is not False:
- self.worldmodel = DeterministicWorldModel(self.config["name"], self.env_config, self.config["model_config"])
- else:
- self.worldmodel = None
-
- valuerl = ValueRL(self.config["name"], self.env_config, self.learner_config)
- (policy_loss, Q_loss), inspect_losses = valuerl.build_training_graph(*self.current_batch, worldmodel=self.worldmodel)
-
- policy_optimizer = tf.train.AdamOptimizer(3e-4)
- policy_gvs = policy_optimizer.compute_gradients(policy_loss, var_list=valuerl.policy_params)
- capped_policy_gvs = policy_gvs
- policy_train_op = policy_optimizer.apply_gradients(capped_policy_gvs)
-
- Q_optimizer = tf.train.AdamOptimizer(3e-4)
- Q_gvs = Q_optimizer.compute_gradients(Q_loss, var_list=valuerl.Q_params)
- capped_Q_gvs = Q_gvs
- Q_train_op = Q_optimizer.apply_gradients(capped_Q_gvs)
-
- return valuerl, (policy_loss, Q_loss), (policy_train_op, Q_train_op), inspect_losses
-
- ## Optional functions to override
- def initialize(self):
- if self.config["model_config"] is not False:
- while not self.load_worldmodel(): pass
-
- def resume_from_checkpoint(self, epoch):
- if self.config["model_config"] is not False:
- with self.bonus_kwargs["model_lock"]: self.worldmodel.load(self.sess, self.save_path, epoch)
-
- def checkpoint(self):
- self.core.copy_to_old(self.sess)
- if self.config["model_config"] is not False:
- self.load_worldmodel()
-
- def backup(self): pass
-
- # Other functions
- def load_worldmodel(self):
- if not os.path.exists("%s/%s.params.index" % (self.save_path, self.worldmodel.saveid)): return False
- with self.bonus_kwargs["model_lock"]: self.worldmodel.load(self.sess, self.save_path)
- return True
diff --git a/research/steve/visualizer.py b/research/steve/visualizer.py
deleted file mode 100644
index 825f1a238617d78dc2ada4611dcecc175f238eb5..0000000000000000000000000000000000000000
--- a/research/steve/visualizer.py
+++ /dev/null
@@ -1,107 +0,0 @@
-from __future__ import print_function
-from builtins import range
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import numpy as np
-import tensorflow as tf
-# import moviepy.editor as mpy
-import time, os, traceback, multiprocessing, portalocker, sys
-
-import envwrap
-import util
-import valuerl, worldmodel
-from config import config
-
-MODEL_NAME = config["name"]
-LOG_PATH = util.create_directory("output/" + config["env"] + "/" + MODEL_NAME + "/" + config["log_path"]) + "/" + MODEL_NAME
-LOAD_PATH = util.create_directory("output/" + config["env"] + "/" + MODEL_NAME + "/" + config["save_model_path"])
-OBS_DIM = np.prod(config["obs_dims"])
-HIDDEN_DIM = config["hidden_dim"]
-ACTION_DIM = config["action_dim"]
-MAX_FRAMES = config["max_frames"]
-REWARD_SCALE = config["reward_scale"]
-DISCOUNT = config["discount"]
-ALGO = config["policy_config"]["algo"]
-AGENT_BATCH_SIZE = config["agent_config"]["batch_size"]
-EVALUATOR_BATCH_SIZE = config["evaluator_config"]["batch_size"]
-RELOAD_EVERY_N = config["agent_config"]["reload_every_n"]
-FRAMES_BEFORE_LEARNING = config["policy_config"]["frames_before_learning"]
-FRAMES_PER_UPDATE = config["policy_config"]["frames_per_update"]
-LEARNER_EPOCH_N = config["policy_config"]["epoch_n"]
-SYNC_UPDATES = config["policy_config"]["frames_per_update"] >= 0
-POLICY_BAYESIAN_CONFIG = config["policy_config"]["bayesian"]
-AUX_CONFIG = config["aux_config"]
-DDPG_EXPLORE_CHANCE = config["policy_config"]["explore_chance"] if ALGO == "ddpg" else 0.
-MODEL_AUGMENTED = config["model_config"] is not False
-if MODEL_AUGMENTED: MODEL_BAYESIAN_CONFIG = config["model_config"]["bayesian"]
-
-FILENAME = sys.argv[3]
-
-if __name__ == '__main__':
- oprl = valuerl.ValueRL(MODEL_NAME, ALGO, OBS_DIM, ACTION_DIM, HIDDEN_DIM, REWARD_SCALE, DISCOUNT, POLICY_BAYESIAN_CONFIG, AUX_CONFIG, DDPG_EXPLORE_CHANCE)
-
- obs_loader = tf.placeholder(tf.float32, [1, OBS_DIM])
- policy_actions, _ = oprl.build_evalution_graph(obs_loader, mode="exploit")
-
- if MODEL_AUGMENTED:
- next_obs_loader = tf.placeholder(tf.float32, [1, OBS_DIM])
- reward_loader = tf.placeholder(tf.float32, [1])
- done_loader = tf.placeholder(tf.float32, [1])
- worldmodel = worldmodel.DeterministicWorldModel(MODEL_NAME, OBS_DIM, ACTION_DIM, HIDDEN_DIM, REWARD_SCALE, DISCOUNT, MODEL_BAYESIAN_CONFIG)
- _, _, _, _, _, confidence, _ = oprl.build_Q_expansion_graph(next_obs_loader, reward_loader, done_loader, worldmodel, rollout_len=3, model_ensembling=True)
-
- sess = tf.Session()
- sess.run(tf.global_variables_initializer())
-
- oprl.load(sess, FILENAME)
- if MODEL_AUGMENTED: worldmodel.load(sess, FILENAME)
-
- env = envwrap.get_env(config["env"])
-
- hist = np.zeros([4, 10])
- for _ in range(10):
- ts = 0
- rgb_frames = []
- obs, reward, done, reset = env.reset(), 0, False, False
- while not reset:
- # env.internal_env.render()
- # rgb_frames.append(env.internal_env.render(mode='rgb_array'))
- # action = env.action_space.sample()
- all_actions = sess.run(policy_actions, feed_dict={obs_loader: np.array([obs])})
- all_actions = np.clip(all_actions, -1., 1.)
- action = all_actions[0]
- obs, _reward, done, reset = env.step(action)
-
- if MODEL_AUGMENTED:
- _confidences = sess.run(confidence, feed_dict={next_obs_loader: np.expand_dims(obs,0),
- reward_loader: np.expand_dims(_reward,0),
- done_loader: np.expand_dims(done,0)})
- # print "%.02f %.02f %.02f %.02f" % tuple(_confidences[0,0])
- for h in range(4):
- bucket = int((_confidences[0,0,h]-1e-5)*10)
- hist[h,bucket] += 1
-
- reward += _reward
- ts += 1
- # print ts, _reward, reward
- print(ts, reward)
- hist /= np.sum(hist, axis=1, keepdims=True)
- for row in reversed(hist.T): print(' '.join(["%.02f"] * 4) % tuple(row))
-
- #clip = mpy.ImageSequenceClip(rgb_frames, fps=100)
- #clip.write_videofile(FILENAME + "/movie.mp4")
-
-
diff --git a/research/steve/worldmodel.py b/research/steve/worldmodel.py
deleted file mode 100644
index 613bc6cb3f69a534fe4a5cada67badf7d4052d4f..0000000000000000000000000000000000000000
--- a/research/steve/worldmodel.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import tensorflow as tf
-import numpy as np
-import nn
-
-from learner import CoreModel
-
-class DeterministicWorldModel(CoreModel):
- """
- A simple feed-forward neural network world model, with an option for an ensemble.
- """
-
- @property
- def saveid(self):
- return "worldmodel"
-
- def create_params(self, env_config, learner_config):
- self.obs_dim = np.prod(env_config["obs_dims"])
- self.action_dim = env_config["action_dim"]
- self.reward_scale = env_config["reward_scale"]
- self.discount = env_config["discount"]
-
- self.aux_hidden_dim = self.learner_config["aux_hidden_dim"]
- self.transition_hidden_dim = self.learner_config["transition_hidden_dim"]
- self.bayesian_config = self.learner_config["bayesian"]
-
- with tf.variable_scope(self.name):
- if self.bayesian_config:
- self.transition_predictor = nn.EnsembleFeedForwardNet('transition_predictor', self.obs_dim + self.action_dim, [self.obs_dim], layers=8, hidden_dim=self.transition_hidden_dim, get_uncertainty=True, ensemble_size=self.bayesian_config["transition"]["ensemble_size"], train_sample_count=self.bayesian_config["transition"]["train_sample_count"], eval_sample_count=self.bayesian_config["transition"]["eval_sample_count"])
- self.done_predictor = nn.EnsembleFeedForwardNet('done_predictor', self.obs_dim + self.obs_dim + self.action_dim, [], layers=4, hidden_dim=self.aux_hidden_dim, get_uncertainty=True, ensemble_size=self.bayesian_config["transition"]["ensemble_size"], train_sample_count=self.bayesian_config["transition"]["train_sample_count"], eval_sample_count=self.bayesian_config["transition"]["eval_sample_count"])
- self.reward_predictor = nn.EnsembleFeedForwardNet('reward_predictor', self.obs_dim + self.obs_dim + self.action_dim, [], layers=4, hidden_dim=self.aux_hidden_dim, get_uncertainty=True, ensemble_size=self.bayesian_config["reward"]["ensemble_size"], train_sample_count=self.bayesian_config["reward"]["train_sample_count"], eval_sample_count=self.bayesian_config["reward"]["eval_sample_count"])
- else:
- self.transition_predictor = nn.FeedForwardNet('transition_predictor', self.obs_dim + self.action_dim, [self.obs_dim], layers=8, hidden_dim=self.transition_hidden_dim, get_uncertainty=True)
- self.done_predictor = nn.FeedForwardNet('done_predictor', self.obs_dim + self.obs_dim + self.action_dim, [], layers=4, hidden_dim=self.aux_hidden_dim, get_uncertainty=True)
- self.reward_predictor = nn.FeedForwardNet('reward_predictor', self.obs_dim + self.obs_dim + self.action_dim, [], layers=4, hidden_dim=self.aux_hidden_dim, get_uncertainty=True)
-
- def get_ensemble_idx_info(self):
- if self.bayesian_config is not False:
- ensemble_idxs = tf.random_shuffle(tf.range(self.transition_predictor.ensemble_size))
- transition_ensemble_sample_n = self.transition_predictor.eval_sample_count
- reward_ensemble_sample_n = self.reward_predictor.eval_sample_count
- ensemble_idxs = ensemble_idxs[:transition_ensemble_sample_n]
- return ensemble_idxs, transition_ensemble_sample_n, reward_ensemble_sample_n
- else:
- return None, 1, 1
-
- def build_training_graph(self, obs, next_obs, actions, rewards, dones, data_size):
- info = tf.concat([obs, actions], -1)
- predicted_next_obs = self.transition_predictor(info, is_eval=False, reduce_mode="random") + obs
- next_info = tf.concat([next_obs, info], -1)
- predicted_dones = self.done_predictor(next_info, is_eval=False, reduce_mode="random")
- predicted_rewards = self.reward_predictor(next_info, is_eval=False, reduce_mode="random")
-
- done_losses = tf.nn.sigmoid_cross_entropy_with_logits(labels=dones, logits=predicted_dones)
- reward_losses = .5 * tf.square(rewards - predicted_rewards)
- next_obs_losses = .5 * tf.reduce_sum(tf.square(next_obs - predicted_next_obs), -1)
-
- done_loss = tf.reduce_mean(done_losses)
- reward_loss = tf.reduce_mean(reward_losses)
- next_obs_loss = tf.reduce_mean(next_obs_losses)
- reg_loss = .0001 * (self.done_predictor.l2_loss() +
- self.reward_predictor.l2_loss() +
- self.transition_predictor.l2_loss())
-
- total_loss = done_loss + reward_loss + next_obs_loss + reg_loss
-
- inspect = (total_loss, done_loss, reward_loss, next_obs_loss, reg_loss)
-
- return total_loss, inspect
-
- def init_extra_info(self, obs):
- return tf.zeros_like(obs)
-
- def transition(self, obs, action, extra_info, ensemble_idxs=None, pre_expanded=None):
- info = tf.concat([obs, action], -1)
- next_obs_delta = self.transition_predictor(info, reduce_mode="none", ensemble_idxs=ensemble_idxs, pre_expanded=pre_expanded)
- if ensemble_idxs is None:
- next_obs = tf.expand_dims(obs,-2) + next_obs_delta
- next_info = tf.concat([next_obs, tf.expand_dims(info,-2)], -1)
- else:
- next_obs = obs + next_obs_delta
- next_info = tf.concat([next_obs, info], -1)
- done = tf.nn.sigmoid(self.done_predictor(next_info, reduce_mode="none", ensemble_idxs=ensemble_idxs, pre_expanded=True))
- extra_info = tf.zeros_like(obs)
- return next_obs, done, extra_info
-
- def get_rewards(self, obs, action, next_obs):
- next_info = tf.concat([next_obs, obs, action], -1)
- reward = self.reward_predictor(next_info, reduce_mode="none")
- return reward
\ No newline at end of file
diff --git a/research/steve/worldmodel_learner.py b/research/steve/worldmodel_learner.py
deleted file mode 100644
index c36a50f6adff604dd44f961d0360540469d503e5..0000000000000000000000000000000000000000
--- a/research/steve/worldmodel_learner.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-import tensorflow as tf
-import numpy as np
-from learner import Learner
-from worldmodel import DeterministicWorldModel
-
-class WorldmodelLearner(Learner):
- """
- Worldmodel-specific training loop details.
- """
- def learner_name(self): return "worldmodel"
-
- def make_loader_placeholders(self):
- self.obs_loader = tf.placeholder(tf.float32, [self.learner_config["batch_size"], np.prod(self.env_config["obs_dims"])])
- self.next_obs_loader = tf.placeholder(tf.float32, [self.learner_config["batch_size"], np.prod(self.env_config["obs_dims"])])
- self.action_loader = tf.placeholder(tf.float32, [self.learner_config["batch_size"], self.env_config["action_dim"]])
- self.reward_loader = tf.placeholder(tf.float32, [self.learner_config["batch_size"]])
- self.done_loader = tf.placeholder(tf.float32, [self.learner_config["batch_size"]])
- self.datasize_loader = tf.placeholder(tf.float64, [])
- return [self.obs_loader, self.next_obs_loader, self.action_loader, self.reward_loader, self.done_loader, self.datasize_loader]
-
- def make_core_model(self):
- worldmodel = DeterministicWorldModel(self.config["name"], self.env_config, self.learner_config)
- worldmodel_loss, inspect_losses = worldmodel.build_training_graph(*self.current_batch)
-
- model_optimizer = tf.train.AdamOptimizer(3e-4)
- model_gvs = model_optimizer.compute_gradients(worldmodel_loss, var_list=worldmodel.model_params)
- capped_model_gvs = model_gvs
- worldmodel_train_op = model_optimizer.apply_gradients(capped_model_gvs)
-
- return worldmodel, (worldmodel_loss,), (worldmodel_train_op,), inspect_losses
-
- ## Optional functions to override
- def initialize(self): pass
- def resume_from_checkpoint(self, epoch): pass
- def checkpoint(self): pass
- def backup(self): pass
-
-
-
-
diff --git a/research/street/README.md b/research/street/README.md
deleted file mode 100644
index fc2c4d01ce31bb8e0c7db88797d16de4974d9505..0000000000000000000000000000000000000000
--- a/research/street/README.md
+++ /dev/null
@@ -1,268 +0,0 @@
-
-
-
-
-# StreetView Tensorflow Recurrent End-to-End Transcription (STREET) Model.
-
-A TensorFlow implementation of the STREET model described in the paper:
-
-"End-to-End Interpretation of the French Street Name Signs Dataset"
-
-Raymond Smith, Chunhui Gu, Dar-Shyang Lee, Huiyi Hu, Ranjith
-Unnikrishnan, Julian Ibarz, Sacha Arnoud, Sophia Lin.
-
-*International Workshop on Robust Reading, Amsterdam, 9 October 2016.*
-
-Available at: http://link.springer.com/chapter/10.1007%2F978-3-319-46604-0_30
-
-
-## Contact
-***Author:*** Ray Smith (rays@google.com).
-
-***Pull requests and issues:*** @theraysmith.
-
-## Contents
-* [Introduction](#introduction)
-* [Installing and setting up the STREET model](#installing-and-setting-up-the-street-model)
-* [Downloading the datasets](#downloading-the-datasets)
-* [Confidence Tests](#confidence-tests)
-* [Training a model](#training-a-model)
-* [The Variable Graph Specification Language](#the-variable-graph-specification-language)
-
-## Introduction
-
-The *STREET* model is a deep recurrent neural network that learns how to
-identify the name of a street (in France) from an image containing upto four
-different views of the street name sign. The model merges information from the
-different views and normalizes the text to the correct format. For example:
-
-
-
-Avenue des Sapins
-
-
-## Installing and setting up the STREET model
-[Install Tensorflow](https://www.tensorflow.org/install/)
-
-Install numpy:
-
-```
-sudo pip install numpy
-```
-
-Build the LSTM op:
-
-```
-cd cc
-TF_INC=$(python -c 'import tensorflow as tf; print(tf.sysconfig.get_include())')
-g++ -std=c++11 -shared rnn_ops.cc -o rnn_ops.so -fPIC -I $TF_INC -O3 -mavx
-```
-
-(Note: if running on Mac, add `-undefined dynamic_lookup` to your `g++` command.
-If you are running a newer version of gcc, you may also need to add
-`-D_GLIBCXX_USE_CXX11_ABI=0`.)
-
-Run the unittests:
-
-```
-cd ../python
-python decoder_test.py
-python errorcounter_test.py
-python shapes_test.py
-python vgslspecs_test.py
-python vgsl_model_test.py
-```
-
-## Downloading the datasets
-
-The French Street Name Signs (FSNS) dataset is split into subsets, each
-of which is composed of multiple files.
-Note that these datasets are very large. The approximate sizes are:
-
-* Train: 512 files of 300MB each.
-* Validation: 64 files of 40MB each.
-* Test: 64 files of 50MB each.
-* Testdata: some smaller data files of a few MB for testing.
-* Total: ~158 Gb.
-
-Here is a list of the download paths:
-
-```
-https://download.tensorflow.org/data/fsns-20160927/charset_size=134.txt
-https://download.tensorflow.org/data/fsns-20160927/test/test-00000-of-00064
-...
-https://download.tensorflow.org/data/fsns-20160927/test/test-00063-of-00064
-https://download.tensorflow.org/data/fsns-20160927/testdata/arial-32-00000-of-00001
-https://download.tensorflow.org/data/fsns-20160927/testdata/fsns-00000-of-00001
-https://download.tensorflow.org/data/fsns-20160927/testdata/mnist-sample-00000-of-00001
-https://download.tensorflow.org/data/fsns-20160927/testdata/numbers-16-00000-of-00001
-https://download.tensorflow.org/data/fsns-20160927/train/train-00000-of-00512
-...
-https://download.tensorflow.org/data/fsns-20160927/train/train-00511-of-00512
-https://download.tensorflow.org/data/fsns-20160927/validation/validation-00000-of-00064
-...
-https://download.tensorflow.org/data/fsns-20160927/validation/validation-00063-of-00064
-```
-
-All URLs are stored in the text file `python/fsns_urls.txt`, to download them in
-parallel:
-
-```
-aria2c -c -j 20 -i fsns_urls.txt
-```
-If you ctrl+c and re-execute the command it will continue the aborted download.
-
-
-## Confidence Tests
-
-The datasets download includes a directory `testdata` that contains some small
-datasets that are big enough to test that models can actually learn something.
-Assuming that you have put the downloads in directory `data` alongside
-`python` then you can run the following tests:
-
-### Mnist for zero-dimensional data
-
-```
-cd python
-train_dir=/tmp/mnist
-rm -rf $train_dir
-python vgsl_train.py --model_str='16,0,0,1[Ct5,5,16 Mp3,3 Lfys32 Lfxs64]O0s12' \
- --max_steps=1024 --train_data=../data/testdata/mnist-sample-00000-of-00001 \
- --initial_learning_rate=0.001 --final_learning_rate=0.001 \
- --num_preprocess_threads=1 --train_dir=$train_dir
-python vgsl_eval.py --model_str='16,0,0,1[Ct5,5,16 Mp3,3 Lfys32 Lfxs64]O0s12' \
- --num_steps=256 --eval_data=../data/testdata/mnist-sample-00000-of-00001 \
- --num_preprocess_threads=1 --decoder=../testdata/numbers.charset_size=12.txt \
- --eval_interval_secs=0 --train_dir=$train_dir --eval_dir=$train_dir/eval
-```
-
-Depending on your machine, this should run in about 1 minute, and should obtain
-error rates below 50%. Actual error rates will vary according to random
-initialization.
-
-### Fixed-length targets for number recognition
-
-```
-cd python
-train_dir=/tmp/fixed
-rm -rf $train_dir
-python vgsl_train.py --model_str='8,16,0,1[S1(1x16)1,3 Lfx32 Lrx32 Lfx32]O1s12' \
- --max_steps=3072 --train_data=../data/testdata/numbers-16-00000-of-00001 \
- --initial_learning_rate=0.001 --final_learning_rate=0.001 \
- --num_preprocess_threads=1 --train_dir=$train_dir
-python vgsl_eval.py --model_str='8,16,0,1[S1(1x16)1,3 Lfx32 Lrx32 Lfx32]O1s12' \
- --num_steps=256 --eval_data=../data/testdata/numbers-16-00000-of-00001 \
- --num_preprocess_threads=1 --decoder=../testdata/numbers.charset_size=12.txt \
- --eval_interval_secs=0 --train_dir=$train_dir --eval_dir=$train_dir/eval
-```
-
-Depending on your machine, this should run in about 1-2 minutes, and should
-obtain a label error rate between 50 and 80%, with word error rates probably
-not coming below 100%. Actual error rates will vary
-according to random initialization.
-
-### OCR-style data with CTC
-
-```
-cd python
-train_dir=/tmp/ctc
-rm -rf $train_dir
-python vgsl_train.py --model_str='1,32,0,1[S1(1x32)1,3 Lbx100]O1c105' \
- --max_steps=4096 --train_data=../data/testdata/arial-32-00000-of-00001 \
- --initial_learning_rate=0.001 --final_learning_rate=0.001 \
- --num_preprocess_threads=1 --train_dir=$train_dir &
-python vgsl_eval.py --model_str='1,32,0,1[S1(1x32)1,3 Lbx100]O1c105' \
- --num_steps=256 --eval_data=../data/testdata/arial-32-00000-of-00001 \
- --num_preprocess_threads=1 --decoder=../testdata/arial.charset_size=105.txt \
- --eval_interval_secs=15 --train_dir=$train_dir --eval_dir=$train_dir/eval &
-tensorboard --logdir=$train_dir
-```
-
-Depending on your machine, the background training should run for about 3-4
-minutes, and should obtain a label error rate between 10 and 50%, with
-correspondingly higher word error rates and even higher sequence error rate.
-Actual error rates will vary according to random initialization.
-The background eval will run for ever, and will have to be terminated by hand.
-The tensorboard command will run a visualizer that can be viewed with a
-browser. Go to the link that it prints to view tensorboard and see the
-training progress. See the [Tensorboard](https://www.tensorflow.org/versions/r0.10/how_tos/summaries_and_tensorboard/index.html)
-introduction for more information.
-
-
-### Mini FSNS dataset
-
-You can test the actual STREET model on a small FSNS data set. The model will
-overfit to this small dataset, but will give some confidence that everything
-is working correctly. *Note* that this test runs the training and evaluation
-in parallel, which is something that you should do when training any substantial
-system, so you can monitor progress.
-
-
-```
-cd python
-train_dir=/tmp/fsns
-rm -rf $train_dir
-python vgsl_train.py --max_steps=10000 --num_preprocess_threads=1 \
- --train_data=../data/testdata/fsns-00000-of-00001 \
- --initial_learning_rate=0.0001 --final_learning_rate=0.0001 \
- --train_dir=$train_dir &
-python vgsl_eval.py --num_steps=256 --num_preprocess_threads=1 \
- --eval_data=../data/testdata/fsns-00000-of-00001 \
- --decoder=../testdata/charset_size=134.txt \
- --eval_interval_secs=300 --train_dir=$train_dir --eval_dir=$train_dir/eval &
-tensorboard --logdir=$train_dir
-```
-
-Depending on your machine, the training should finish in about 1-2 *hours*.
-As with the CTC testset above, the eval and tensorboard will have to be
-terminated manually.
-
-## Training a full FSNS model
-
-After running the tests above, you are ready to train the real thing!
-*Note* that you might want to use a `train_dir` somewhere other than `/tmp` as
-you can stop the training, reboot if needed and continue if you keep the
-data intact, but `/tmp` gets deleted on a reboot.
-
-```
-cd python
-train_dir=/tmp/fsns
-rm -rf $train_dir
-python vgsl_train.py --max_steps=100000000 --train_data=../data/train/train* \
- --train_dir=$train_dir &
-python vgsl_eval.py --num_steps=1000 \
- --eval_data=../data/validation/validation* \
- --decoder=../testdata/charset_size=134.txt \
- --eval_interval_secs=300 --train_dir=$train_dir --eval_dir=$train_dir/eval &
-tensorboard --logdir=$train_dir
-```
-
-Training will take a very long time (probably many weeks) to reach minimum
-error rate on a single machine, although it will probably take substantially
-fewer iterations than with parallel training. Faster training can be obtained
-with parallel training on a cluster.
-Since the setup is likely to be very site-specific, please see the TensorFlow
-documentation on
-[Distributed TensorFlow](https://www.tensorflow.org/versions/r0.10/how_tos/distributed/index.html)
-for more information. Some code changes may be needed in the `Train` function
-in `vgsl_model.py`.
-
-With 40 parallel training workers, nearly optimal error rates (about 25%
-sequence error on the validation set) are obtained in about 30 million steps,
-although the error continues to fall slightly over the next 30 million, to
-perhaps as low as 23%.
-
-With a single machine the number of steps could be substantially lower.
-Although untested on this problem, on other problems the ratio is typically
-5 to 1 so low error rates could be obtained as soon as 6 million iterations,
-which could be reached in about 4 weeks.
-
-
-## The Variable Graph Specification Language
-
-The STREET model makes use of a graph specification language (VGSL) that
-enables rapid experimentation with different model architectures. The language
-defines a Tensor Flow graph that can be used to process images of variable sizes
-to output a 1-dimensional sequence, like a transcription/OCR problem, or a
-0-dimensional label, as for image identification problems. For more information
-see [vgslspecs](g3doc/vgslspecs.md)
diff --git a/research/street/cc/rnn_ops.cc b/research/street/cc/rnn_ops.cc
deleted file mode 100644
index 8e004d91c1e426d2eafcc52a390217bd67e40c9a..0000000000000000000000000000000000000000
--- a/research/street/cc/rnn_ops.cc
+++ /dev/null
@@ -1,538 +0,0 @@
-/* Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-==============================================================================*/
-
-// OpKernel of LSTM Neural Networks:
-//
-// LSTM: VariableLSTMOp (VariableLSTMGradOp)
-//
-// where (.*) are the ops to compute gradients for the corresponding ops.
-
-#define EIGEN_USE_THREADS
-
-#include
-#ifdef GOOGLE_INCLUDES
-#include "third_party/eigen3/Eigen/Core"
-#include "third_party/tensorflow/core/framework/op.h"
-#include "third_party/tensorflow/core/framework/op_kernel.h"
-#include "third_party/tensorflow/core/framework/tensor.h"
-#else
-#include "Eigen/Core"
-#include "tensorflow/core/framework/op.h"
-#include "tensorflow/core/framework/op_kernel.h"
-#include "tensorflow/core/framework/tensor.h"
-#endif // GOOGLE_INCLUDES
-
-namespace tensorflow {
-
-using Eigen::array;
-using Eigen::DenseIndex;
-using IndexPair = Eigen::IndexPair;
-
-Status AreDimsEqual(int dim1, int dim2, const string& message) {
- if (dim1 != dim2) {
- return errors::InvalidArgument(message, ": ", dim1, " vs. ", dim2);
- }
- return Status::OK();
-}
-
-// ------------------------------- VariableLSTMOp -----------------------------
-
-// Kernel to compute the forward propagation of a Long Short-Term Memory
-// network. See the doc of the op below for more detail.
-class VariableLSTMOp : public OpKernel {
- public:
- explicit VariableLSTMOp(OpKernelConstruction* ctx) : OpKernel(ctx) {
- OP_REQUIRES_OK(ctx, ctx->GetAttr("clip", &clip_));
- OP_REQUIRES(
- ctx, clip_ >= 0.0,
- errors::InvalidArgument("clip_ needs to be equal or greator than 0"));
- }
-
- void Compute(OpKernelContext* ctx) override {
- // Inputs.
- const auto input = ctx->input(0).tensor();
- const auto initial_state = ctx->input(1).tensor();
- const auto initial_memory = ctx->input(2).tensor();
- const auto w_m_m = ctx->input(3).tensor();
- const int batch_size = input.dimension(0);
- const int seq_len = input.dimension(1);
- const int output_dim = input.dimension(3);
-
- // Sanity checks.
- OP_REQUIRES_OK(ctx, AreDimsEqual(4, input.dimension(2), "Input num"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(batch_size, initial_state.dimension(0),
- "State batch"));
- OP_REQUIRES_OK(
- ctx, AreDimsEqual(output_dim, initial_state.dimension(1), "State dim"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(batch_size, initial_memory.dimension(0),
- "Memory batch"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(output_dim, initial_memory.dimension(1),
- "Memory dim"));
- OP_REQUIRES_OK(
- ctx, AreDimsEqual(output_dim, w_m_m.dimension(0), "Weight dim 0"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(4, w_m_m.dimension(1), "Weight dim 1"));
- OP_REQUIRES_OK(
- ctx, AreDimsEqual(output_dim, w_m_m.dimension(2), "Weight dim 2"));
-
- // Outputs.
- Tensor* act_tensor = nullptr;
- OP_REQUIRES_OK(ctx, ctx->allocate_output(
- 0, {batch_size, seq_len, output_dim}, &act_tensor));
- auto act = act_tensor->tensor();
- act.setZero();
-
- Tensor* gate_raw_act_tensor = nullptr;
- OP_REQUIRES_OK(ctx,
- ctx->allocate_output(1, {batch_size, seq_len, 4, output_dim},
- &gate_raw_act_tensor));
- auto gate_raw_act = gate_raw_act_tensor->tensor();
- gate_raw_act.setZero();
-
- Tensor* memory_tensor = nullptr;
- OP_REQUIRES_OK(ctx,
- ctx->allocate_output(2, {batch_size, seq_len, output_dim},
- &memory_tensor));
- auto memory = memory_tensor->tensor();
- memory.setZero();
-
- // Const and scratch tensors.
- Tensor ones_tensor;
- OP_REQUIRES_OK(ctx, ctx->allocate_temp(DT_FLOAT, {batch_size, output_dim},
- &ones_tensor));
- auto ones = ones_tensor.tensor();
- ones.setConstant(1.0);
-
- Tensor state_tensor;
- OP_REQUIRES_OK(ctx, ctx->allocate_temp(DT_FLOAT, {batch_size, output_dim},
- &state_tensor));
- auto state = state_tensor.tensor();
- state = initial_state;
-
- Tensor scratch_tensor;
- OP_REQUIRES_OK(ctx,
- ctx->allocate_temp(DT_FLOAT, {batch_size, 4, output_dim},
- &scratch_tensor));
- auto scratch = scratch_tensor.tensor();
- scratch.setZero();
-
- // Uses the most efficient order for the contraction depending on the batch
- // size.
-
- // This is the code shared by both cases. It is discouraged to use the
- // implicit capture with lambda functions, but it should be clear that what
- // is done here.
- auto Forward = [&](int i) {
- // Each pre-activation value is stored in the following order (See the
- // comment of the op for the meaning):
- //
- // i: 0
- // j: 1
- // f: 2
- // o: 3
-
- // Adds one to the pre-activation values of the forget gate. This is a
- // heuristic to make the training easier.
- scratch.chip(2, 1) += ones;
-
- gate_raw_act.chip(i, 1) = scratch;
-
- // c_t = f_t * c_{t-1} + i_t * j_t
- if (i == 0) {
- state = initial_memory * scratch.chip(2, 1).sigmoid();
- } else {
- state = memory.chip(i - 1, 1) * scratch.chip(2, 1).sigmoid();
- }
- state += scratch.chip(0, 1).sigmoid() * scratch.chip(1, 1).tanh();
-
- if (clip_ > 0.0) {
- // Clips the values if required.
- state = state.cwiseMax(-clip_).cwiseMin(clip_);
- }
-
- memory.chip(i, 1) = state;
-
- // h_t = o_t * tanh(c_t)
- state = scratch.chip(3, 1).sigmoid() * state.tanh();
-
- act.chip(i, 1) = state;
- };
- if (batch_size == 1) {
- // Reshapes the weight tensor to pretend as if it is a matrix
- // multiplication which is more efficient.
- auto w_m_m_r =
- w_m_m.reshape(array{output_dim, 4 * output_dim});
- // Dimensions for the contraction.
- const array m_m_dim = {IndexPair(1, 0)};
- for (int i = 0; i < seq_len; ++i) {
- // Computes the pre-activation value of the input and each gate.
- scratch = input.chip(i, 1) +
- state.contract(w_m_m_r, m_m_dim)
- .reshape(array{batch_size, 4, output_dim});
- Forward(i);
- }
- } else {
- // Shuffles the dimensions of the weight tensor to be efficient when used
- // in the left-hand side. Allocates memory for the shuffled tensor for
- // efficiency.
- Tensor w_m_m_s_tensor;
- OP_REQUIRES_OK(ctx,
- ctx->allocate_temp(DT_FLOAT, {output_dim * 4, output_dim},
- &w_m_m_s_tensor));
- auto w_m_m_s = w_m_m_s_tensor.tensor();
- w_m_m_s = w_m_m.shuffle(array{2, 1, 0})
- .reshape(array{output_dim * 4, output_dim});
- // Dimensions for the contraction.
- const array m_m_dim = {IndexPair(1, 1)};
- for (int i = 0; i < seq_len; ++i) {
- // Computes the pre-activation value of the input and each gate.
- scratch = input.chip(i, 1) +
- w_m_m_s.contract(state, m_m_dim)
- .reshape(array{output_dim, 4, batch_size})
- .shuffle(array{2, 1, 0});
- Forward(i);
- }
- }
- }
-
- private:
- // Threshold to clip the values of memory cells.
- float clip_ = 0;
-};
-
-REGISTER_KERNEL_BUILDER(Name("VariableLSTM").Device(DEVICE_CPU),
- VariableLSTMOp);
-REGISTER_OP("VariableLSTM")
- .Attr("clip: float = 0.0")
- .Input("input: float32")
- .Input("initial_state: float32")
- .Input("initial_memory: float32")
- .Input("w_m_m: float32")
- .Output("activation: float32")
- .Output("gate_raw_act: float32")
- .Output("memory: float32")
- .Doc(R"doc(
-Computes the forward propagation of a Long Short-Term Memory Network.
-
-It computes the following equation recursively for `0 0 else c_t
- h_t = o_t * tanh(c'_t)
-
-where
-
- a_{l,t} = w_{l,m,m} * h_{t-1} + x'_{l,t}
-
-where
-
- x'_{l,t} = w_{l,m,i} * x_{t}.
-
-`input` corresponds to the concatenation of `X'_i`, `X'_j`, `X'_f`, and `X'_o`
-where `X'_l = (x'_{l,1}, x'_{l,2}, ..., x'_{l,T})`, `initial_state` corresponds
-to `h_{0}`, `initial_memory` corresponds to `c_{0}` and `weight` corresponds to
-`w_{l,m,m}`. `X'_l` (the transformed input) is computed outside of the op in
-advance, so w_{l,m,i} is not passed in to the op.
-
-`activation` corresponds to `H = (h_1, h_2, ..., h_T)`, `gate_raw_activation`
-corresponds to the concatanation of `A_i`, `A_j`, `A_f` and `A_o`, and `memory`
-corresponds `C = (c_0, c_1, ..., c_T)`.
-
-All entries in the batch are propagated to the end, and are assumed to be the
-same length.
-
-input: 4-D with shape `[batch_size, seq_len, 4, num_nodes]`
-initial_state: 2-D with shape `[batch_size, num_nodes]`
-initial_memory: 2-D with shape `[batch_size, num_nodes]`
-w_m_m: 3-D with shape `[num_nodes, 4, num_nodes]`
-activation: 3-D with shape `[batch_size, seq_len, num_nodes]`
-gate_raw_act: 3-D with shape `[batch_size, seq_len, 4, num_nodes]`
-memory: 3-D with shape `[batch_size, seq_len, num_nodes]`
-)doc");
-
-// ----------------------------- VariableLSTMGradOp ----------------------------
-
-// Kernel to compute the gradient of VariableLSTMOp.
-class VariableLSTMGradOp : public OpKernel {
- public:
- explicit VariableLSTMGradOp(OpKernelConstruction* ctx) : OpKernel(ctx) {}
-
- void Compute(OpKernelContext* ctx) override {
- // Inputs.
- const auto initial_state = ctx->input(0).tensor();
- const auto initial_memory = ctx->input(1).tensor();
- const auto w_m_m = ctx->input(2).tensor();
- const auto act = ctx->input(3).tensor();
- const auto gate_raw_act = ctx->input(4).tensor();
- const auto memory = ctx->input(5).tensor();
- const auto act_grad = ctx->input(6).tensor();
- const auto gate_raw_act_grad = ctx->input(7).tensor();
- const auto memory_grad = ctx->input(8).tensor();
- const int batch_size = act.dimension(0);
- const int seq_len = act.dimension(1);
- const int output_dim = act.dimension(2);
-
- // Sanity checks.
- OP_REQUIRES_OK(ctx, AreDimsEqual(batch_size, initial_state.dimension(0),
- "State batch"));
- OP_REQUIRES_OK(
- ctx, AreDimsEqual(output_dim, initial_state.dimension(1), "State dim"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(batch_size, initial_memory.dimension(0),
- "Memory batch"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(output_dim, initial_memory.dimension(1),
- "Memory dim"));
- OP_REQUIRES_OK(
- ctx, AreDimsEqual(output_dim, w_m_m.dimension(0), "Weight dim 0"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(4, w_m_m.dimension(1), "Weight dim 1"));
- OP_REQUIRES_OK(
- ctx, AreDimsEqual(output_dim, w_m_m.dimension(2), "Weight dim 2"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(batch_size, gate_raw_act.dimension(0),
- "Gate raw activation batch"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(seq_len, gate_raw_act.dimension(1),
- "Gate raw activation len"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(4, gate_raw_act.dimension(2),
- "Gate raw activation num"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(output_dim, gate_raw_act.dimension(3),
- "Gate raw activation dim"));
- OP_REQUIRES_OK(
- ctx, AreDimsEqual(batch_size, memory.dimension(0), "Memory batch"));
- OP_REQUIRES_OK(ctx,
- AreDimsEqual(seq_len, memory.dimension(1), "Memory len"));
- OP_REQUIRES_OK(ctx,
- AreDimsEqual(output_dim, memory.dimension(2), "Memory dim"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(batch_size, act_grad.dimension(0),
- "Activation gradient batch"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(seq_len, act_grad.dimension(1),
- "Activation gradient len"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(output_dim, act_grad.dimension(2),
- "Activation gradient dim"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(batch_size, gate_raw_act_grad.dimension(0),
- "Activation gradient batch"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(seq_len, gate_raw_act_grad.dimension(1),
- "Activation gradient len"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(4, gate_raw_act_grad.dimension(2),
- "Activation gradient num"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(output_dim, gate_raw_act_grad.dimension(3),
- "Activation gradient dim"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(batch_size, memory_grad.dimension(0),
- "Memory gradient batch"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(seq_len, memory_grad.dimension(1),
- "Memory gradient len"));
- OP_REQUIRES_OK(ctx, AreDimsEqual(output_dim, memory_grad.dimension(2),
- "Memory gradient dim"));
-
- // Outputs.
- std::vector collections(4, nullptr);
- OP_REQUIRES_OK(ctx,
- ctx->allocate_output(0, {batch_size, seq_len, 4, output_dim},
- &collections[0]));
- auto input_grad = collections[0]->tensor();
- input_grad.setZero();
-
- OP_REQUIRES_OK(ctx, ctx->allocate_output(1, {batch_size, output_dim},
- &collections[1]));
- auto init_state_grad = collections[1]->tensor();
- init_state_grad.setZero();
-
- OP_REQUIRES_OK(ctx, ctx->allocate_output(2, {batch_size, output_dim},
- &collections[2]));
- auto init_memory_grad = collections[2]->tensor();
- init_memory_grad.setZero();
-
- OP_REQUIRES_OK(ctx, ctx->allocate_output(3, {output_dim, 4, output_dim},
- &collections[3]));
- auto w_m_m_grad = collections[3]->tensor();
- w_m_m_grad.setZero();
-
- // Const and scratch tensors.
- Tensor ones_tensor;
- OP_REQUIRES_OK(ctx, ctx->allocate_temp(DT_FLOAT, {batch_size, output_dim},
- &ones_tensor));
- auto ones = ones_tensor.tensor();
- ones.setConstant(1.0);
-
- Tensor scratch_tensor;
- OP_REQUIRES_OK(ctx,
- ctx->allocate_temp(DT_FLOAT, {batch_size, 4, output_dim},
- &scratch_tensor));
- auto scratch = scratch_tensor.tensor();
- scratch.setZero();
-
- Tensor tmp1_tensor;
- OP_REQUIRES_OK(ctx, ctx->allocate_temp(DT_FLOAT, {batch_size, output_dim},
- &tmp1_tensor));
- auto tmp1 = tmp1_tensor.tensor();
- tmp1.setZero();
-
- Tensor tmp2_tensor;
- OP_REQUIRES_OK(ctx, ctx->allocate_temp(DT_FLOAT, {batch_size, output_dim},
- &tmp2_tensor));
- auto tmp2 = tmp2_tensor.tensor();
- tmp2.setZero();
-
- // Uses the most efficient order for the contraction depending on the batch
- // size.
-
- // Shuffles the dimensions of the weight tensor to be efficient when used in
- // the left-hand side. Allocates memory for the shuffled tensor for
- // efficiency.
- Tensor w_m_m_s_tensor;
- OP_REQUIRES_OK(ctx,
- ctx->allocate_temp(DT_FLOAT, {4, output_dim, output_dim},
- &w_m_m_s_tensor));
- auto w_m_m_s = w_m_m_s_tensor.tensor();
- if (batch_size == 1) {
- // Allocates memory only it is used.
- w_m_m_s = w_m_m.shuffle(array{1, 2, 0});
- }
-
- // Dimensions for the contraction with the weight tensor.
- const array m_m_dim =
- batch_size == 1 ? array{IndexPair(1, 0)}
- : array{IndexPair(1, 1)};
- // Dimensions for the contraction of the batch dimensions.
- const array b_b_dim = {IndexPair(0, 0)};
- for (int i = seq_len - 1; i >= 0; --i) {
- if (i == seq_len - 1) {
- init_state_grad = act_grad.chip(i, 1);
- } else {
- w_m_m_grad +=
- act.chip(i, 1)
- .contract(scratch.reshape(
- array{batch_size, 4 * output_dim}),
- b_b_dim)
- .reshape(array{output_dim, 4, output_dim});
- if (batch_size == 1) {
- init_state_grad.device(ctx->eigen_cpu_device()) =
- scratch.chip(0, 1).contract(w_m_m_s.chip(0, 0), m_m_dim) +
- scratch.chip(1, 1).contract(w_m_m_s.chip(1, 0), m_m_dim) +
- scratch.chip(2, 1).contract(w_m_m_s.chip(2, 0), m_m_dim) +
- scratch.chip(3, 1).contract(w_m_m_s.chip(3, 0), m_m_dim);
- } else {
- init_state_grad.device(ctx->eigen_cpu_device()) =
- (w_m_m.chip(0, 1).contract(scratch.chip(0, 1), m_m_dim) +
- w_m_m.chip(1, 1).contract(scratch.chip(1, 1), m_m_dim) +
- w_m_m.chip(2, 1).contract(scratch.chip(2, 1), m_m_dim) +
- w_m_m.chip(3, 1).contract(scratch.chip(3, 1), m_m_dim))
- .shuffle(array{1, 0});
- }
- init_state_grad += act_grad.chip(i, 1);
- }
-
- auto gate_raw_act_t = gate_raw_act.chip(i, 1);
- auto gate_raw_act_grad_t = gate_raw_act_grad.chip(i, 1);
-
- // Output gate.
- tmp1 = memory.chip(i, 1);
- tmp1 = tmp1.tanh(); // y_t
- tmp2 = gate_raw_act_t.chip(3, 1).sigmoid(); // o_t
- scratch.chip(3, 1) = init_state_grad * tmp1 * tmp2 * (ones - tmp2) +
- gate_raw_act_grad_t.chip(3, 1);
-
- init_memory_grad += init_state_grad * tmp2 * (ones - tmp1.square()) +
- memory_grad.chip(i, 1);
-
- // Input gate.
- tmp1 = gate_raw_act_t.chip(0, 1).sigmoid(); // i_t
- tmp2 = gate_raw_act_t.chip(1, 1);
- tmp2 = tmp2.tanh(); // j_t
- scratch.chip(0, 1) = init_memory_grad * tmp2 * tmp1 * (ones - tmp1) +
- gate_raw_act_grad_t.chip(0, 1);
-
- // Input.
- scratch.chip(1, 1) = init_memory_grad * tmp1 * (ones - tmp2.square()) +
- gate_raw_act_grad_t.chip(1, 1);
-
- // Forget gate.
- tmp1 = gate_raw_act_t.chip(2, 1).sigmoid(); // f_t
- if (i == 0) {
- scratch.chip(2, 1) =
- init_memory_grad * initial_memory * tmp1 * (ones - tmp1) +
- gate_raw_act_grad_t.chip(2, 1);
- } else {
- scratch.chip(2, 1) =
- init_memory_grad * memory.chip(i - 1, 1) * tmp1 * (ones - tmp1) +
- gate_raw_act_grad_t.chip(2, 1);
- }
-
- // Memory.
- init_memory_grad *= tmp1;
-
- input_grad.chip(i, 1) = scratch;
- }
- w_m_m_grad += initial_state
- .contract(scratch.reshape(array{
- batch_size, 4 * output_dim}),
- b_b_dim)
- .reshape(array{output_dim, 4, output_dim});
- if (batch_size == 1) {
- init_state_grad.device(ctx->eigen_cpu_device()) =
- (scratch.chip(0, 1).contract(w_m_m_s.chip(0, 0), m_m_dim) +
- scratch.chip(1, 1).contract(w_m_m_s.chip(1, 0), m_m_dim) +
- scratch.chip(2, 1).contract(w_m_m_s.chip(2, 0), m_m_dim) +
- scratch.chip(3, 1).contract(w_m_m_s.chip(3, 0), m_m_dim));
- } else {
- init_state_grad.device(ctx->eigen_cpu_device()) =
- (w_m_m.chip(0, 1).contract(scratch.chip(0, 1), m_m_dim) +
- w_m_m.chip(1, 1).contract(scratch.chip(1, 1), m_m_dim) +
- w_m_m.chip(2, 1).contract(scratch.chip(2, 1), m_m_dim) +
- w_m_m.chip(3, 1).contract(scratch.chip(3, 1), m_m_dim))
- .shuffle(array{1, 0});
- }
- }
-};
-
-REGISTER_KERNEL_BUILDER(Name("VariableLSTMGrad").Device(DEVICE_CPU),
- VariableLSTMGradOp);
-
-REGISTER_OP("VariableLSTMGrad")
- .Input("initial_state: float32")
- .Input("initial_memory: float32")
- .Input("w_m_m: float32")
- .Input("activation: float32")
- .Input("gate_raw_act: float32")
- .Input("memory: float32")
- .Input("act_grad: float32")
- .Input("gate_raw_act_grad: float32")
- .Input("memory_grad: float32")
- .Output("input_grad: float32")
- .Output("initial_state_grad: float32")
- .Output("initial_memory_grad: float32")
- .Output("w_m_m_grad: float32")
- .Doc(R"doc(
-Computes the gradient for VariableLSTM.
-
-This is to be used conjunction with VariableLSTM. It ignores the clipping used
-in the forward pass.
-
-initial_state: 2-D with shape `[batch_size, num_nodes]`
-initial_memory: 2-D with shape `[batch_size, num_nodes]`
-w_m_m: 3-D with shape `[num_nodes, 4, num_nodes]`
-activation: 3-D with shape `[batch_size, seq_len, num_nodes]`
-gate_raw_act: 3-D with shape `[batch_size, seq_len, 4, num_nodes]`
-memory: 3-D with shape `[batch_size, seq_len, num_nodes]`
-act_grad: 3-D with shape `[batch_size, seq_len, num_nodes]`
-gate_raw_act_grad: 3-D with shape `[batch_size, seq_len, 4, num_nodes]`
-memory_grad: 3-D with shape `[batch_size, seq_len, num_nodes]`
-input_grad: 3-D with shape `[batch_size, seq_len, num_nodes]`
-initial_state_grad: 2-D with shape `[batch_size, num_nodes]`
-initial_memory_grad: 2-D with shape `[batch_size, num_nodes]`
-w_m_m_grad: 3-D with shape `[num_nodes, 4, num_nodes]`
-)doc");
-
-} // namespace tensorflow
diff --git a/research/street/g3doc/avdessapins.png b/research/street/g3doc/avdessapins.png
deleted file mode 100644
index 7cdb9657a480979060e377e59906120d104680f4..0000000000000000000000000000000000000000
Binary files a/research/street/g3doc/avdessapins.png and /dev/null differ
diff --git a/research/street/g3doc/vgslspecs.md b/research/street/g3doc/vgslspecs.md
deleted file mode 100644
index 74294952b3ca006d957b3d2d9384b02a887ebab0..0000000000000000000000000000000000000000
--- a/research/street/g3doc/vgslspecs.md
+++ /dev/null
@@ -1,324 +0,0 @@
-# VGSL Specs - rapid prototyping of mixed conv/LSTM networks for images.
-
-Variable-size Graph Specification Language (VGSL) enables the specification of a
-Tensor Flow graph, composed of convolutions and LSTMs, that can process
-variable-sized images, from a very short definition string.
-
-## Applications: What is VGSL Specs good for?
-
-VGSL Specs are designed specifically to create TF graphs for:
-
-* Variable size images as the input. (In one or BOTH dimensions!)
-* Output an image (heat map), sequence (like text), or a category.
-* Convolutions and LSTMs are the main computing component.
-* Fixed-size images are OK too!
-
-But wait, aren't there other systems that simplify generating TF graphs? There
-are indeed, but something they all have in common is that they are designed for
-fixed size images only. If you want to solve a real OCR problem, you either have
-to cut the image into arbitrary sized pieces and try to stitch the results back
-together, or use VGSL.
-
-## Basic Usage
-
-A full model, including input and the output layers, can be built using
-vgsl_model.py. Alternatively you can supply your own tensors and add your own
-loss function layer if you wish, using vgslspecs.py directly.
-
-### Building a full model
-
-Provided your problem matches the one addressed by vgsl_model, you are good to
-go.
-
-Targeted problems:
-
-* Images for input, either 8 bit greyscale or 24 bit color.
-* Output is 0-d (A category, like cat, dog, train, car.)
-* Output is 1-d, with either variable length or a fixed length sequence, eg
- OCR, transcription problems in general.
-
-Currently only softmax (1 of n) outputs are supported, but it would not be
-difficult to extend to logistic.
-
-Use vgsl_train.py to train your model, and vgsl_eval.py to evaluate it. They
-just call Train and Eval in vgsl_model.py.
-
-### Model string for a full model
-
-The model string for a full model includes the input spec, the output spec and
-the layers spec in between. Example:
-
-```
-'1,0,0,3[Ct5,5,16 Mp3,3 Lfys64 Lfx128 Lrx128 Lfx256]O1c105'
-```
-
-The first 4 numbers specify the standard TF tensor dimensions: [batch, height,
-width, depth], except that height and/or width may be zero, allowing them to be
-variable. Batch is specific only to training, and may be a different value at
-recognition/inference time. Depth needs to be 1 for greyscale and 3 for color.
-
-The model string in square brackets [] is the main model definition, which is
-described [below.](#basic-layers-syntax) The output specification takes the
-form:
-
-```
-O(2|1|0)(l|s|c)n output layer with n classes.
- 2 (heatmap) Output is a 2-d vector map of the input (possibly at
- different scale). (Not yet supported.)
- 1 (sequence) Output is a 1-d sequence of vector values.
- 0 (category) Output is a 0-d single vector value.
- l uses a logistic non-linearity on the output, allowing multiple
- hot elements in any output vector value. (Not yet supported.)
- s uses a softmax non-linearity, with one-hot output in each value.
- c uses a softmax with CTC. Can only be used with s (sequence).
- NOTE Only O0s, O1s and O1c are currently supported.
-```
-
-The number of classes must match the encoding of the TF Example data set.
-
-### Layers only - providing your own input and loss layers
-
-You don't have to use the canned input/output modules, if you provide your
-separate code to read TF Example and loss functions. First prepare your inputs:
-
-* A TF-conventional batch of: `images = tf.float32[batch, height, width,
- depth]`
-* A tensor of the width of each image in the batch: `widths = tf.int64[batch]`
-* A tensor of the height of each image in the batch: `heights =
- tf.int64[batch]`
-
-Note that these can be created from individual images using
-`tf.train.batch_join` with `dynamic_pad=True.`
-
-```python
-import vgslspecs
-...
-spec = '[Ct5,5,16 Mp3,3 Lfys64 Lfx128 Lrx128 Lfx256]'
-vgsl = vgslspecs.VGSLSpecs(widths, heights, is_training=True)
-last_layer = vgsl.Build(images, spec)
-...
-AddSomeLossFunction(last_layer)....
-```
-
-With some appropriate training data, this would create a world-class OCR engine!
-
-## Basic Layers Syntax
-
-NOTE that *all* ops input and output the standard TF convention of a 4-d tensor:
-`[batch, height, width, depth]` *regardless of any collapsing of dimensions.*
-This greatly simplifies things, and allows the VGSLSpecs class to track changes
-to the values of widths and heights, so they can be correctly passed in to LSTM
-operations, and used by any downstream CTC operation.
-
-NOTE: in the descriptions below, `` is a numeric value, and literals are
-described using regular expression syntax.
-
-NOTE: Whitespace is allowed between ops.
-
-### Naming
-
-Each op gets a unique name by default, based on its spec string plus its
-character position in the overall specification. All the Ops take an optional
-name argument in braces after the mnemonic code, but before any numeric
-arguments.
-
-### Functional ops
-
-```
-C(s|t|r|l|m)[{name}],, Convolves using a y,x window, with no shrinkage,
- SAME infill, d outputs, with s|t|r|l|m non-linear layer.
-F(s|t|r|l|m)[{name}] Fully-connected with s|t|r|l|m non-linearity and d
- outputs. Reduces height, width to 1. Input height and width must be constant.
-L(f|r|b)(x|y)[s][{name}] LSTM cell with n outputs.
- The LSTM must have one of:
- f runs the LSTM forward only.
- r runs the LSTM reversed only.
- b runs the LSTM bidirectionally.
- It will operate on either the x- or y-dimension, treating the other dimension
- independently (as if part of the batch).
- (Full 2-d and grid are not yet supported).
- s (optional) summarizes the output in the requested dimension,
- outputting only the final step, collapsing the dimension to a
- single element.
-Do[{name}] Insert a dropout layer.
-```
-
-In the above, `(s|t|r|l|m)` specifies the type of the non-linearity:
-
-```python
-s = sigmoid
-t = tanh
-r = relu
-l = linear (i.e., None)
-m = softmax
-```
-
-Examples:
-
-`Cr5,5,32` Runs a 5x5 Relu convolution with 32 depth/number of filters.
-
-`Lfx{MyLSTM}128` runs a forward-only LSTM, named 'MyLSTM' in the x-dimension
-with 128 outputs, treating the y dimension independently.
-
-`Lfys64` runs a forward-only LSTM in the y-dimension with 64 outputs, treating
-the x-dimension independently and collapses the y-dimension to 1 element.
-
-### Plumbing ops
-
-The plumbing ops allow the construction of arbitrarily complex graphs. Something
-currently missing is the ability to define macros for generating say an
-inception unit in multiple places.
-
-```
-[...] Execute ... networks in series (layers).
-(...) Execute ... networks in parallel, with their output concatenated in depth.
-S[{name}](x), Splits one dimension, moves one part to another
- dimension.
-Mp[{name}], Maxpool the input, reducing the (y,x) rectangle to a single
- value.
-```
-
-In the `S` op, `, , , , ` are numbers.
-
-`S` is a generalized reshape. It splits input dimension `d` into `a` x `b`,
-sending the high/most significant part `a` to the high/most significant side of
-dimension `e`, and the low part `b` to the high side of dimension `f`.
-Exception: if `d=e=f`, then then dimension `d` is internally transposed to
-`bxa`. *At least one* of `e`, `f` must be equal to `d`, so no dimension can be
-totally destroyed. Either `a` or `b` can be zero, meaning whatever is left after
-taking out the other, allowing dimensions to be of variable size.
-
-NOTE: Remember the standard TF convention of a 4-d tensor: `[batch, height,
-width, depth]`, so `batch=0, height=1, width=2, depth=3.`
-
-Eg. `S3(3x50)2,3` will split the 150-element depth into 3x50, with the 3 going
-to the most significant part of the width, and the 50 part staying in depth.
-This will rearrange a 3x50 output parallel operation to spread the 3 output sets
-over width.
-
-### Full Examples
-
-Example 1: A graph capable of high quality OCR.
-
-`1,0,0,1[Ct5,5,16 Mp3,3 Lfys64 Lfx128 Lrx128 Lfx256]O1c105`
-
-As layer descriptions: (Input layer is at the bottom, output at the top.)
-
-```
-O1c105: Output layer produces 1-d (sequence) output, trained with CTC,
- outputting 105 classes.
-Lfx256: Forward-only LSTM in x with 256 outputs
-Lrx128: Reverse-only LSTM in x with 128 outputs
-Lfx128: Forward-only LSTM in x with 128 outputs
-Lfys64: Dimension-summarizing LSTM, summarizing the y-dimension with 64 outputs
-Mp3,3: 3 x 3 Maxpool
-Ct5,5,16: 5 x 5 Convolution with 16 outputs and tanh non-linearity
-[]: The body of the graph is alway expressed as a series of layers.
-1,0,0,1: Input is a batch of 1 image of variable size in greyscale
-```
-
-Example 2: The STREET network for reading French street name signs end-to-end.
-For a detailed description see the [FSNS dataset
-paper](http://link.springer.com/chapter/10.1007%2F978-3-319-46604-0_30)
-
-```
-1,600,150,3[S2(4x150)0,2 Ct5,5,16 Mp2,2 Ct5,5,64 Mp3,3
- ([Lrys64 Lbx128][Lbys64 Lbx128][Lfys64 Lbx128]) S3(3x0)2,3
- Lfx128 Lrx128 S0(1x4)0,3 Lfx256]O1c134
-```
-
-Since networks are usually illustrated with the input at the bottom, the input
-layer is at the bottom, output at the top, with 'headings' *below* the section
-they introduce.
-
-```
-O1c134: Output is a 1-d sequence, trained with CTC and 134 output softmax.
-Lfx256: Forward-only LSTM with 256 outputs
-S0(1x4)0,3: Reshape transferring the batch of 4 tiles to the depth dimension.
-Lrx128: Reverse-only LSTM with 128 outputs
-Lfx128: Forward-only LSTM with 128 outputs
-(Final section above)
-S3(3x0)2,3: Split the outputs of the 3 parallel summarizers and spread over the
- x-dimension
- [Lfys64 Lbx128]: Summarizing LSTM downwards on the y-dimension with 64
- outputs, followed by a bi-directional LSTM in the x-dimension with 128
- outputs
- [Lbys64 Lbx128]: Summarizing bi-directional LSTM on the y-dimension with
- 64 outputs, followed by a bi-directional LSTM in the x-dimension with 128
- outputs
- [Lrys64 Lbx128]: Summarizing LSTM upwards on the y-dimension with 64 outputs,
- followed by a bi-directional LSTM in the x-dimension with 128 outputs
-(): In parallel (re-using the inputs and concatenating the outputs):
-(Summarizing section above)
-Mp3,3: 3 x 3 Maxpool
-Ct5,5,64: 5 x 5 Convolution with 64 outputs and tanh non-linearity
-Mp2,2: 2 x 2 Maxpool
-Ct5,5,16: 5 x 5 Convolution with 16 outputs and tanh non-linearity
-S2(4x150)0,2: Split the x-dimension into 4x150, converting each tiled 600x150
-image into a batch of 4 150x150 images
-(Convolutional input section above)
-[]: The body of the graph is alway expressed as a series of layers.
-1,150,600,3: Input is a batch of 1, 600x150 image in 24 bit color
-```
-
-## Variable size Tensors Under the Hood
-
-Here are some notes about handling variable-sized images since they require some
-consideration and a little bit of knowledge about what goes on inside.
-
-A variable-sized image is an input for which the width and/or height are not
-known at graph-building time, so the tensor shape contains unknown/None/-1
-sizes.
-
-Many standard NN layers, such as convolutions, are designed to cope naturally
-with variable-sized images in TF and produce a variable sized image as the
-output. For other layers, such as 'Fully connected' variable size is
-fundamentally difficult, if not impossible to deal with, since by definition,
-*all* its inputs are connected via a weight to an output. The number of inputs
-therefore must be fixed.
-
-It is possible to handle variable sized images by using sparse tensors. Some
-implementations make a single variable dimension a list instead of part of the
-tensor. Both these solutions suffer from completely segregating the world of
-variable size from the world of fixed size, making models and their descriptions
-completely non-interchangeable.
-
-In VGSL, we use a standard 4-d Tensor, `[batch, height, width, depth]` and
-either use a batch size of 1 or put up with padding of the input images to the
-largest size of any element of the batch. The other price paid for this
-standardization is that the user must supply a pair of tensors of shape [batch]
-specifying the width and height of each input in a batch. This allows the LSTMs
-in the graph to know how many iterations to execute and how to correctly
-back-propagate the gradients.
-
-The standard TF implementation of CTC also requires a tensor giving the sequence
-lengths of its inputs. If the output of VGSL is going into CTC, the lengths can
-be obtained using:
-
-```python
-import vgslspecs
-...
-spec = '[Ct5,5,16 Mp3,3 Lfys64 Lfx128 Lrx128 Lfx256]'
-vgsl = vgslspecs.VGSLSpecs(widths, heights, is_training=True)
-last_layer = vgsl.Build(images, spec)
-seq_lengths = vgsl.GetLengths()
-```
-
-The above will provide the widths that were given in the constructor, scaled
-down by the max-pool operator. The heights may be obtained using
-`vgsl.GetLengths(1)`, specifying the index of the y-dimension.
-
-NOTE that currently the only way of collapsing a dimension of unknown size to
-known size (1) is through the use of a summarizing LSTM. A single summarizing
-LSTM will collapse one dimension (x or y), leaving a 1-d sequence. The 1-d
-sequence can then be collapsed in the other dimension to make a 0-d categorical
-(softmax) or embedding (logistic) output.
-
-Using the (parallel) op it is entirely possible to run multiple [series] of ops
-that collapse x first in one and y first in the other, reducing both eventually
-to a single categorical value! For eample, the following description may do
-something useful with ImageNet-like problems:
-
-```python
-[Cr5,5,16 Mp2,2 Cr5,5,64 Mp3,3 ([Lfxs64 Lfys256] [Lfys64 Lfxs256]) Fr512 Fr512]
-```
diff --git a/research/street/python/decoder.py b/research/street/python/decoder.py
deleted file mode 100644
index 715146194c58d577c6b799a15baf8619211bc4cd..0000000000000000000000000000000000000000
--- a/research/street/python/decoder.py
+++ /dev/null
@@ -1,244 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Basic CTC+recoder decoder.
-
-Decodes a sequence of class-ids into UTF-8 text.
-For basic information on CTC See:
-Alex Graves et al. Connectionist Temporal Classification: Labelling Unsegmented
-Sequence Data with Recurrent Neural Networks.
-http://www.cs.toronto.edu/~graves/icml_2006.pdf
-"""
-import collections
-import re
-
-import errorcounter as ec
-from six.moves import xrange
-import tensorflow as tf
-
-# Named tuple Part describes a part of a multi (1 or more) part code that
-# represents a utf-8 string. For example, Chinese character 'x' might be
-# represented by 3 codes of which (utf8='x', index=1, num_codes3) would be the
-# middle part. (The actual code is not stored in the tuple).
-Part = collections.namedtuple('Part', 'utf8 index, num_codes')
-
-
-# Class that decodes a sequence of class-ids into UTF-8 text.
-class Decoder(object):
- """Basic CTC+recoder decoder."""
-
- def __init__(self, filename):
- r"""Constructs a Decoder.
-
- Reads the text file describing the encoding and build the encoder.
- The text file contains lines of the form:
- [,]*\t
- Each line defines a mapping from a sequence of one or more integer codes to
- a corresponding utf-8 string.
- Args:
- filename: Name of file defining the decoding sequences.
- """
- # self.decoder is a list of lists of Part(utf8, index, num_codes).
- # The index to the top-level list is a code. The list given by the code
- # index is a list of the parts represented by that code, Eg if the code 42
- # represents the 2nd (index 1) out of 3 part of Chinese character 'x', then
- # self.decoder[42] = [..., (utf8='x', index=1, num_codes3), ...] where ...
- # means all other uses of the code 42.
- self.decoder = []
- if filename:
- self._InitializeDecoder(filename)
-
- def SoftmaxEval(self, sess, model, num_steps):
- """Evaluate a model in softmax mode.
-
- Adds char, word recall and sequence error rate events to the sw summary
- writer, and returns them as well
- TODO(rays) Add LogisticEval.
- Args:
- sess: A tensor flow Session.
- model: The model to run in the session. Requires a VGSLImageModel or any
- other class that has a using_ctc attribute and a RunAStep(sess) method
- that reurns a softmax result with corresponding labels.
- num_steps: Number of steps to evaluate for.
- Returns:
- ErrorRates named tuple.
- Raises:
- ValueError: If an unsupported number of dimensions is used.
- """
- coord = tf.train.Coordinator()
- threads = tf.train.start_queue_runners(sess=sess, coord=coord)
- # Run the requested number of evaluation steps, gathering the outputs of the
- # softmax and the true labels of the evaluation examples.
- total_label_counts = ec.ErrorCounts(0, 0, 0, 0)
- total_word_counts = ec.ErrorCounts(0, 0, 0, 0)
- sequence_errors = 0
- for _ in xrange(num_steps):
- softmax_result, labels = model.RunAStep(sess)
- # Collapse softmax to same shape as labels.
- predictions = softmax_result.argmax(axis=-1)
- # Exclude batch from num_dims.
- num_dims = len(predictions.shape) - 1
- batch_size = predictions.shape[0]
- null_label = softmax_result.shape[-1] - 1
- for b in xrange(batch_size):
- if num_dims == 2:
- # TODO(rays) Support 2-d data.
- raise ValueError('2-d label data not supported yet!')
- else:
- if num_dims == 1:
- pred_batch = predictions[b, :]
- labels_batch = labels[b, :]
- else:
- pred_batch = [predictions[b]]
- labels_batch = [labels[b]]
- text = self.StringFromCTC(pred_batch, model.using_ctc, null_label)
- truth = self.StringFromCTC(labels_batch, False, null_label)
- # Note that recall_errs is false negatives (fn) aka drops/deletions.
- # Actual recall would be 1-fn/truth_words.
- # Likewise precision_errs is false positives (fp) aka adds/insertions.
- # Actual precision would be 1-fp/ocr_words.
- total_word_counts = ec.AddErrors(total_word_counts,
- ec.CountWordErrors(text, truth))
- total_label_counts = ec.AddErrors(total_label_counts,
- ec.CountErrors(text, truth))
- if text != truth:
- sequence_errors += 1
-
- coord.request_stop()
- coord.join(threads)
- return ec.ComputeErrorRates(total_label_counts, total_word_counts,
- sequence_errors, num_steps * batch_size)
-
- def StringFromCTC(self, ctc_labels, merge_dups, null_label):
- """Decodes CTC output to a string.
-
- Extracts only sequences of codes that are allowed by self.decoder.
- Labels that make illegal code sequences are dropped.
- Note that, by its nature of taking only top choices, this is much weaker
- than a full-blown beam search that considers all the softmax outputs.
- For languages without many multi-code sequences, this doesn't make much
- difference, but for complex scripts the accuracy will be much lower.
- Args:
- ctc_labels: List of class labels including null characters to remove.
- merge_dups: If True, Duplicate labels will be merged
- null_label: Label value to ignore.
-
- Returns:
- Labels decoded to a string.
- """
- # Run regular ctc on the labels, extracting a list of codes.
- codes = self._CodesFromCTC(ctc_labels, merge_dups, null_label)
- length = len(codes)
- if length == 0:
- return ''
- # strings and partials are both indexed by the same index as codes.
- # strings[i] is the best completed string upto position i, and
- # partials[i] is a list of partial code sequences at position i.
- # Warning: memory is squared-order in length.
- strings = []
- partials = []
- for pos in xrange(length):
- code = codes[pos]
- parts = self.decoder[code]
- partials.append([])
- strings.append('')
- # Iterate over the parts that this code can represent.
- for utf8, index, num_codes in parts:
- if index > pos:
- continue
- # We can use code if it is an initial code (index==0) or continues a
- # sequence in the partials list at the previous position.
- if index == 0 or partials[pos - 1].count(
- Part(utf8, index - 1, num_codes)) > 0:
- if index < num_codes - 1:
- # Save the partial sequence.
- partials[-1].append(Part(utf8, index, num_codes))
- elif not strings[-1]:
- # A code sequence is completed. Append to the best string that we
- # had where it started.
- if pos >= num_codes:
- strings[-1] = strings[pos - num_codes] + utf8
- else:
- strings[-1] = utf8
- if not strings[-1] and pos > 0:
- # We didn't get anything here so copy the previous best string, skipping
- # the current code, but it may just be a partial anyway.
- strings[-1] = strings[-2]
- return strings[-1]
-
- def _InitializeDecoder(self, filename):
- """Reads the decoder file and initializes self.decoder from it.
-
- Args:
- filename: Name of text file mapping codes to utf8 strings.
- Raises:
- ValueError: if the input file is not parsed correctly.
- """
- line_re = re.compile(r'(?P\d+(,\d+)*)\t(?P.+)')
- with tf.gfile.GFile(filename) as f:
- for line in f:
- m = line_re.match(line)
- if m is None:
- raise ValueError('Unmatched line:', line)
- # codes is the sequence that maps to the string.
- str_codes = m.groupdict()['codes'].split(',')
- codes = []
- for code in str_codes:
- codes.append(int(code))
- utf8 = m.groupdict()['utf8']
- num_codes = len(codes)
- for index, code in enumerate(codes):
- while code >= len(self.decoder):
- self.decoder.append([])
- self.decoder[code].append(Part(utf8, index, num_codes))
-
- def _CodesFromCTC(self, ctc_labels, merge_dups, null_label):
- """Collapses CTC output to regular output.
-
- Args:
- ctc_labels: List of class labels including null characters to remove.
- merge_dups: If True, Duplicate labels will be merged.
- null_label: Label value to ignore.
-
- All trailing zeros are removed!!
- TODO(rays) This may become a problem with non-CTC models.
- If using charset, this should not be a problem as zero is always space.
- tf.pad can only append zero, so we have to be able to drop them, as a
- non-ctc will have learned to output trailing zeros instead of trailing
- nulls. This is awkward, as the stock ctc loss function requires that the
- null character be num_classes-1.
- Returns:
- (List of) Labels with null characters removed.
- """
- out_labels = []
- prev_label = -1
- zeros_needed = 0
- for label in ctc_labels:
- if label == null_label:
- prev_label = -1
- elif label != prev_label or not merge_dups:
- if label == 0:
- # Count zeros and only emit them when it is clear there is a non-zero
- # after, so as to truncate away all trailing zeros.
- zeros_needed += 1
- else:
- if merge_dups and zeros_needed > 0:
- out_labels.append(0)
- else:
- out_labels += [0] * zeros_needed
- zeros_needed = 0
- out_labels.append(label)
- prev_label = label
- return out_labels
diff --git a/research/street/python/decoder_test.py b/research/street/python/decoder_test.py
deleted file mode 100644
index dc61f8b2a6e10d364e7e89b7d6492c36971015f7..0000000000000000000000000000000000000000
--- a/research/street/python/decoder_test.py
+++ /dev/null
@@ -1,57 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tests for decoder."""
-import os
-
-import tensorflow as tf
-import decoder
-
-
-def _testdata(filename):
- return os.path.join('../testdata/', filename)
-
-
-class DecoderTest(tf.test.TestCase):
-
- def testCodesFromCTC(self):
- """Tests that the simple CTC decoder drops nulls and duplicates.
- """
- ctc_labels = [9, 9, 9, 1, 9, 2, 2, 3, 9, 9, 0, 0, 1, 9, 1, 9, 9, 9]
- decode = decoder.Decoder(filename=None)
- non_null_labels = decode._CodesFromCTC(
- ctc_labels, merge_dups=False, null_label=9)
- self.assertEqual(non_null_labels, [1, 2, 2, 3, 0, 0, 1, 1])
- idempotent_labels = decode._CodesFromCTC(
- non_null_labels, merge_dups=False, null_label=9)
- self.assertEqual(idempotent_labels, non_null_labels)
- collapsed_labels = decode._CodesFromCTC(
- ctc_labels, merge_dups=True, null_label=9)
- self.assertEqual(collapsed_labels, [1, 2, 3, 0, 1, 1])
- non_idempotent_labels = decode._CodesFromCTC(
- collapsed_labels, merge_dups=True, null_label=9)
- self.assertEqual(non_idempotent_labels, [1, 2, 3, 0, 1])
-
- def testStringFromCTC(self):
- """Tests that the decoder can decode sequences including multi-codes.
- """
- # - f - a r - m(1/2)m -junk sp b a r - n -
- ctc_labels = [9, 6, 9, 1, 3, 9, 4, 9, 5, 5, 9, 5, 0, 2, 1, 3, 9, 4, 9]
- decode = decoder.Decoder(filename=_testdata('charset_size_10.txt'))
- text = decode.StringFromCTC(ctc_labels, merge_dups=True, null_label=9)
- self.assertEqual(text, 'farm barn')
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/street/python/errorcounter.py b/research/street/python/errorcounter.py
deleted file mode 100644
index affbf969532e6a1b865bca752705bbd6a2ef8f84..0000000000000000000000000000000000000000
--- a/research/street/python/errorcounter.py
+++ /dev/null
@@ -1,123 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Some simple tools for error counting.
-
-"""
-import collections
-
-# Named tuple Error counts describes the counts needed to accumulate errors
-# over multiple trials:
-# false negatives (aka drops or deletions),
-# false positives: (aka adds or insertions),
-# truth_count: number of elements in ground truth = denominator for fn,
-# test_count: number of elements in test string = denominator for fp,
-# Note that recall = 1 - fn/truth_count, precision = 1 - fp/test_count,
-# accuracy = 1 - (fn + fp) / (truth_count + test_count).
-ErrorCounts = collections.namedtuple('ErrorCounts', ['fn', 'fp', 'truth_count',
- 'test_count'])
-
-# Named tuple for error rates, as a percentage. Accuracies are just 100-error.
-ErrorRates = collections.namedtuple('ErrorRates',
- ['label_error', 'word_recall_error',
- 'word_precision_error', 'sequence_error'])
-
-
-def CountWordErrors(ocr_text, truth_text):
- """Counts the word drop and add errors as a bag of words.
-
- Args:
- ocr_text: OCR text string.
- truth_text: Truth text string.
-
- Returns:
- ErrorCounts named tuple.
- """
- # Convert to lists of words.
- return CountErrors(ocr_text.split(), truth_text.split())
-
-
-def CountErrors(ocr_text, truth_text):
- """Counts the drops and adds between 2 bags of iterables.
-
- Simple bag of objects count returns the number of dropped and added
- elements, regardless of order, from anything that is iterable, eg
- a pair of strings gives character errors, and a pair of word lists give
- word errors.
- Args:
- ocr_text: OCR text iterable (eg string for chars, word list for words).
- truth_text: Truth text iterable.
-
- Returns:
- ErrorCounts named tuple.
- """
- counts = collections.Counter(truth_text)
- counts.subtract(ocr_text)
- drops = sum(c for c in counts.values() if c > 0)
- adds = sum(-c for c in counts.values() if c < 0)
- return ErrorCounts(drops, adds, len(truth_text), len(ocr_text))
-
-
-def AddErrors(counts1, counts2):
- """Adds the counts and returns a new sum tuple.
-
- Args:
- counts1: ErrorCounts named tuples to sum.
- counts2: ErrorCounts named tuples to sum.
- Returns:
- Sum of counts1, counts2.
- """
- return ErrorCounts(counts1.fn + counts2.fn, counts1.fp + counts2.fp,
- counts1.truth_count + counts2.truth_count,
- counts1.test_count + counts2.test_count)
-
-
-def ComputeErrorRates(label_counts, word_counts, seq_errors, num_seqs):
- """Returns an ErrorRates corresponding to the given counts.
-
- Args:
- label_counts: ErrorCounts for the character labels
- word_counts: ErrorCounts for the words
- seq_errors: Number of sequence errors
- num_seqs: Total sequences
- Returns:
- ErrorRates corresponding to the given counts.
- """
- label_errors = label_counts.fn + label_counts.fp
- num_labels = label_counts.truth_count + label_counts.test_count
- return ErrorRates(
- ComputeErrorRate(label_errors, num_labels),
- ComputeErrorRate(word_counts.fn, word_counts.truth_count),
- ComputeErrorRate(word_counts.fp, word_counts.test_count),
- ComputeErrorRate(seq_errors, num_seqs))
-
-
-def ComputeErrorRate(error_count, truth_count):
- """Returns a sanitized percent error rate from the raw counts.
-
- Prevents div by 0 and clips return to 100%.
- Args:
- error_count: Number of errors.
- truth_count: Number to divide by.
-
- Returns:
- 100.0 * error_count / truth_count clipped to 100.
- """
- if truth_count == 0:
- truth_count = 1
- error_count = 1
- elif error_count > truth_count:
- error_count = truth_count
- return error_count * 100.0 / truth_count
diff --git a/research/street/python/errorcounter_test.py b/research/street/python/errorcounter_test.py
deleted file mode 100644
index aeaa36092bf43a4ca4186a136527113f4ebb4a03..0000000000000000000000000000000000000000
--- a/research/street/python/errorcounter_test.py
+++ /dev/null
@@ -1,124 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tests for errorcounter."""
-import tensorflow as tf
-import errorcounter as ec
-
-
-class ErrorcounterTest(tf.test.TestCase):
-
- def testComputeErrorRate(self):
- """Tests that the percent calculation works as expected.
- """
- rate = ec.ComputeErrorRate(error_count=0, truth_count=0)
- self.assertEqual(rate, 100.0)
- rate = ec.ComputeErrorRate(error_count=1, truth_count=0)
- self.assertEqual(rate, 100.0)
- rate = ec.ComputeErrorRate(error_count=10, truth_count=1)
- self.assertEqual(rate, 100.0)
- rate = ec.ComputeErrorRate(error_count=0, truth_count=1)
- self.assertEqual(rate, 0.0)
- rate = ec.ComputeErrorRate(error_count=3, truth_count=12)
- self.assertEqual(rate, 25.0)
-
- def testCountErrors(self):
- """Tests that the error counter works as expected.
- """
- truth_str = 'farm barn'
- counts = ec.CountErrors(ocr_text=truth_str, truth_text=truth_str)
- self.assertEqual(
- counts, ec.ErrorCounts(
- fn=0, fp=0, truth_count=9, test_count=9))
- # With a period on the end, we get a char error.
- dot_str = 'farm barn.'
- counts = ec.CountErrors(ocr_text=dot_str, truth_text=truth_str)
- self.assertEqual(
- counts, ec.ErrorCounts(
- fn=0, fp=1, truth_count=9, test_count=10))
- counts = ec.CountErrors(ocr_text=truth_str, truth_text=dot_str)
- self.assertEqual(
- counts, ec.ErrorCounts(
- fn=1, fp=0, truth_count=10, test_count=9))
- # Space is just another char.
- no_space = 'farmbarn'
- counts = ec.CountErrors(ocr_text=no_space, truth_text=truth_str)
- self.assertEqual(
- counts, ec.ErrorCounts(
- fn=1, fp=0, truth_count=9, test_count=8))
- counts = ec.CountErrors(ocr_text=truth_str, truth_text=no_space)
- self.assertEqual(
- counts, ec.ErrorCounts(
- fn=0, fp=1, truth_count=8, test_count=9))
- # Lose them all.
- counts = ec.CountErrors(ocr_text='', truth_text=truth_str)
- self.assertEqual(
- counts, ec.ErrorCounts(
- fn=9, fp=0, truth_count=9, test_count=0))
- counts = ec.CountErrors(ocr_text=truth_str, truth_text='')
- self.assertEqual(
- counts, ec.ErrorCounts(
- fn=0, fp=9, truth_count=0, test_count=9))
-
- def testCountWordErrors(self):
- """Tests that the error counter works as expected.
- """
- truth_str = 'farm barn'
- counts = ec.CountWordErrors(ocr_text=truth_str, truth_text=truth_str)
- self.assertEqual(
- counts, ec.ErrorCounts(
- fn=0, fp=0, truth_count=2, test_count=2))
- # With a period on the end, we get a word error.
- dot_str = 'farm barn.'
- counts = ec.CountWordErrors(ocr_text=dot_str, truth_text=truth_str)
- self.assertEqual(
- counts, ec.ErrorCounts(
- fn=1, fp=1, truth_count=2, test_count=2))
- counts = ec.CountWordErrors(ocr_text=truth_str, truth_text=dot_str)
- self.assertEqual(
- counts, ec.ErrorCounts(
- fn=1, fp=1, truth_count=2, test_count=2))
- # Space is special.
- no_space = 'farmbarn'
- counts = ec.CountWordErrors(ocr_text=no_space, truth_text=truth_str)
- self.assertEqual(
- counts, ec.ErrorCounts(
- fn=2, fp=1, truth_count=2, test_count=1))
- counts = ec.CountWordErrors(ocr_text=truth_str, truth_text=no_space)
- self.assertEqual(
- counts, ec.ErrorCounts(
- fn=1, fp=2, truth_count=1, test_count=2))
- # Lose them all.
- counts = ec.CountWordErrors(ocr_text='', truth_text=truth_str)
- self.assertEqual(
- counts, ec.ErrorCounts(
- fn=2, fp=0, truth_count=2, test_count=0))
- counts = ec.CountWordErrors(ocr_text=truth_str, truth_text='')
- self.assertEqual(
- counts, ec.ErrorCounts(
- fn=0, fp=2, truth_count=0, test_count=2))
- # With a space in ba rn, there is an extra add.
- sp_str = 'farm ba rn'
- counts = ec.CountWordErrors(ocr_text=sp_str, truth_text=truth_str)
- self.assertEqual(
- counts, ec.ErrorCounts(
- fn=1, fp=2, truth_count=2, test_count=3))
- counts = ec.CountWordErrors(ocr_text=truth_str, truth_text=sp_str)
- self.assertEqual(
- counts, ec.ErrorCounts(
- fn=2, fp=1, truth_count=3, test_count=2))
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/street/python/fsns_urls.py b/research/street/python/fsns_urls.py
deleted file mode 100644
index bea547b9d57315e81ed69d290370f851b17784e0..0000000000000000000000000000000000000000
--- a/research/street/python/fsns_urls.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Creates a text file with URLs to download FSNS dataset using aria2c.
-
-The FSNS dataset has 640 files and takes 158Gb of the disk space. So it is
-highly recommended to use some kind of a download manager to download it.
-
-Aria2c is a powerful download manager which can download multiple files in
-parallel, re-try if encounter an error and continue previously unfinished
-downloads.
-"""
-
-import os
-
-_FSNS_BASE_URL = 'http://download.tensorflow.org/data/fsns-20160927/'
-_SHARDS = {'test': 64, 'train': 512, 'validation':64}
-_OUTPUT_FILE = "fsns_urls.txt"
-_OUTPUT_DIR = "data/fsns"
-
-def fsns_paths():
- paths = ['charset_size=134.txt']
- for name, shards in _SHARDS.items():
- for i in range(shards):
- paths.append('%s/%s-%05d-of-%05d' % (name, name, i, shards))
- return paths
-
-
-if __name__ == "__main__":
- with open(_OUTPUT_FILE, "w") as f:
- for path in fsns_paths():
- url = _FSNS_BASE_URL + path
- dst_path = os.path.join(_OUTPUT_DIR, path)
- f.write("%s\n out=%s\n" % (url, dst_path))
- print("To download FSNS dataset execute:")
- print("aria2c -c -j 20 -i %s" % _OUTPUT_FILE)
- print("The downloaded FSNS dataset will be stored under %s" % _OUTPUT_DIR)
diff --git a/research/street/python/fsns_urls.txt b/research/street/python/fsns_urls.txt
deleted file mode 100644
index 959ffbd5d432105a2964ef2a4be07d046c7ab026..0000000000000000000000000000000000000000
--- a/research/street/python/fsns_urls.txt
+++ /dev/null
@@ -1,1282 +0,0 @@
-http://download.tensorflow.org/data/fsns-20160927/charset_size=134.txt
- out=data/fsns/charset_size=134.txt
-http://download.tensorflow.org/data/fsns-20160927/test/test-00000-of-00064
- out=data/fsns/test/test-00000-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00001-of-00064
- out=data/fsns/test/test-00001-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00002-of-00064
- out=data/fsns/test/test-00002-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00003-of-00064
- out=data/fsns/test/test-00003-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00004-of-00064
- out=data/fsns/test/test-00004-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00005-of-00064
- out=data/fsns/test/test-00005-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00006-of-00064
- out=data/fsns/test/test-00006-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00007-of-00064
- out=data/fsns/test/test-00007-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00008-of-00064
- out=data/fsns/test/test-00008-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00009-of-00064
- out=data/fsns/test/test-00009-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00010-of-00064
- out=data/fsns/test/test-00010-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00011-of-00064
- out=data/fsns/test/test-00011-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00012-of-00064
- out=data/fsns/test/test-00012-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00013-of-00064
- out=data/fsns/test/test-00013-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00014-of-00064
- out=data/fsns/test/test-00014-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00015-of-00064
- out=data/fsns/test/test-00015-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00016-of-00064
- out=data/fsns/test/test-00016-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00017-of-00064
- out=data/fsns/test/test-00017-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00018-of-00064
- out=data/fsns/test/test-00018-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00019-of-00064
- out=data/fsns/test/test-00019-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00020-of-00064
- out=data/fsns/test/test-00020-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00021-of-00064
- out=data/fsns/test/test-00021-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00022-of-00064
- out=data/fsns/test/test-00022-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00023-of-00064
- out=data/fsns/test/test-00023-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00024-of-00064
- out=data/fsns/test/test-00024-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00025-of-00064
- out=data/fsns/test/test-00025-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00026-of-00064
- out=data/fsns/test/test-00026-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00027-of-00064
- out=data/fsns/test/test-00027-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00028-of-00064
- out=data/fsns/test/test-00028-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00029-of-00064
- out=data/fsns/test/test-00029-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00030-of-00064
- out=data/fsns/test/test-00030-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00031-of-00064
- out=data/fsns/test/test-00031-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00032-of-00064
- out=data/fsns/test/test-00032-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00033-of-00064
- out=data/fsns/test/test-00033-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00034-of-00064
- out=data/fsns/test/test-00034-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00035-of-00064
- out=data/fsns/test/test-00035-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00036-of-00064
- out=data/fsns/test/test-00036-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00037-of-00064
- out=data/fsns/test/test-00037-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00038-of-00064
- out=data/fsns/test/test-00038-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00039-of-00064
- out=data/fsns/test/test-00039-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00040-of-00064
- out=data/fsns/test/test-00040-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00041-of-00064
- out=data/fsns/test/test-00041-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00042-of-00064
- out=data/fsns/test/test-00042-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00043-of-00064
- out=data/fsns/test/test-00043-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00044-of-00064
- out=data/fsns/test/test-00044-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00045-of-00064
- out=data/fsns/test/test-00045-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00046-of-00064
- out=data/fsns/test/test-00046-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00047-of-00064
- out=data/fsns/test/test-00047-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00048-of-00064
- out=data/fsns/test/test-00048-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00049-of-00064
- out=data/fsns/test/test-00049-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00050-of-00064
- out=data/fsns/test/test-00050-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00051-of-00064
- out=data/fsns/test/test-00051-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00052-of-00064
- out=data/fsns/test/test-00052-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00053-of-00064
- out=data/fsns/test/test-00053-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00054-of-00064
- out=data/fsns/test/test-00054-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00055-of-00064
- out=data/fsns/test/test-00055-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00056-of-00064
- out=data/fsns/test/test-00056-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00057-of-00064
- out=data/fsns/test/test-00057-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00058-of-00064
- out=data/fsns/test/test-00058-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00059-of-00064
- out=data/fsns/test/test-00059-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00060-of-00064
- out=data/fsns/test/test-00060-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00061-of-00064
- out=data/fsns/test/test-00061-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00062-of-00064
- out=data/fsns/test/test-00062-of-00064
-http://download.tensorflow.org/data/fsns-20160927/test/test-00063-of-00064
- out=data/fsns/test/test-00063-of-00064
-http://download.tensorflow.org/data/fsns-20160927/train/train-00000-of-00512
- out=data/fsns/train/train-00000-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00001-of-00512
- out=data/fsns/train/train-00001-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00002-of-00512
- out=data/fsns/train/train-00002-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00003-of-00512
- out=data/fsns/train/train-00003-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00004-of-00512
- out=data/fsns/train/train-00004-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00005-of-00512
- out=data/fsns/train/train-00005-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00006-of-00512
- out=data/fsns/train/train-00006-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00007-of-00512
- out=data/fsns/train/train-00007-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00008-of-00512
- out=data/fsns/train/train-00008-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00009-of-00512
- out=data/fsns/train/train-00009-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00010-of-00512
- out=data/fsns/train/train-00010-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00011-of-00512
- out=data/fsns/train/train-00011-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00012-of-00512
- out=data/fsns/train/train-00012-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00013-of-00512
- out=data/fsns/train/train-00013-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00014-of-00512
- out=data/fsns/train/train-00014-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00015-of-00512
- out=data/fsns/train/train-00015-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00016-of-00512
- out=data/fsns/train/train-00016-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00017-of-00512
- out=data/fsns/train/train-00017-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00018-of-00512
- out=data/fsns/train/train-00018-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00019-of-00512
- out=data/fsns/train/train-00019-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00020-of-00512
- out=data/fsns/train/train-00020-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00021-of-00512
- out=data/fsns/train/train-00021-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00022-of-00512
- out=data/fsns/train/train-00022-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00023-of-00512
- out=data/fsns/train/train-00023-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00024-of-00512
- out=data/fsns/train/train-00024-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00025-of-00512
- out=data/fsns/train/train-00025-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00026-of-00512
- out=data/fsns/train/train-00026-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00027-of-00512
- out=data/fsns/train/train-00027-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00028-of-00512
- out=data/fsns/train/train-00028-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00029-of-00512
- out=data/fsns/train/train-00029-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00030-of-00512
- out=data/fsns/train/train-00030-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00031-of-00512
- out=data/fsns/train/train-00031-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00032-of-00512
- out=data/fsns/train/train-00032-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00033-of-00512
- out=data/fsns/train/train-00033-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00034-of-00512
- out=data/fsns/train/train-00034-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00035-of-00512
- out=data/fsns/train/train-00035-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00036-of-00512
- out=data/fsns/train/train-00036-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00037-of-00512
- out=data/fsns/train/train-00037-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00038-of-00512
- out=data/fsns/train/train-00038-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00039-of-00512
- out=data/fsns/train/train-00039-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00040-of-00512
- out=data/fsns/train/train-00040-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00041-of-00512
- out=data/fsns/train/train-00041-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00042-of-00512
- out=data/fsns/train/train-00042-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00043-of-00512
- out=data/fsns/train/train-00043-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00044-of-00512
- out=data/fsns/train/train-00044-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00045-of-00512
- out=data/fsns/train/train-00045-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00046-of-00512
- out=data/fsns/train/train-00046-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00047-of-00512
- out=data/fsns/train/train-00047-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00048-of-00512
- out=data/fsns/train/train-00048-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00049-of-00512
- out=data/fsns/train/train-00049-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00050-of-00512
- out=data/fsns/train/train-00050-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00051-of-00512
- out=data/fsns/train/train-00051-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00052-of-00512
- out=data/fsns/train/train-00052-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00053-of-00512
- out=data/fsns/train/train-00053-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00054-of-00512
- out=data/fsns/train/train-00054-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00055-of-00512
- out=data/fsns/train/train-00055-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00056-of-00512
- out=data/fsns/train/train-00056-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00057-of-00512
- out=data/fsns/train/train-00057-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00058-of-00512
- out=data/fsns/train/train-00058-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00059-of-00512
- out=data/fsns/train/train-00059-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00060-of-00512
- out=data/fsns/train/train-00060-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00061-of-00512
- out=data/fsns/train/train-00061-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00062-of-00512
- out=data/fsns/train/train-00062-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00063-of-00512
- out=data/fsns/train/train-00063-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00064-of-00512
- out=data/fsns/train/train-00064-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00065-of-00512
- out=data/fsns/train/train-00065-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00066-of-00512
- out=data/fsns/train/train-00066-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00067-of-00512
- out=data/fsns/train/train-00067-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00068-of-00512
- out=data/fsns/train/train-00068-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00069-of-00512
- out=data/fsns/train/train-00069-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00070-of-00512
- out=data/fsns/train/train-00070-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00071-of-00512
- out=data/fsns/train/train-00071-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00072-of-00512
- out=data/fsns/train/train-00072-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00073-of-00512
- out=data/fsns/train/train-00073-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00074-of-00512
- out=data/fsns/train/train-00074-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00075-of-00512
- out=data/fsns/train/train-00075-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00076-of-00512
- out=data/fsns/train/train-00076-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00077-of-00512
- out=data/fsns/train/train-00077-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00078-of-00512
- out=data/fsns/train/train-00078-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00079-of-00512
- out=data/fsns/train/train-00079-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00080-of-00512
- out=data/fsns/train/train-00080-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00081-of-00512
- out=data/fsns/train/train-00081-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00082-of-00512
- out=data/fsns/train/train-00082-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00083-of-00512
- out=data/fsns/train/train-00083-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00084-of-00512
- out=data/fsns/train/train-00084-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00085-of-00512
- out=data/fsns/train/train-00085-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00086-of-00512
- out=data/fsns/train/train-00086-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00087-of-00512
- out=data/fsns/train/train-00087-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00088-of-00512
- out=data/fsns/train/train-00088-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00089-of-00512
- out=data/fsns/train/train-00089-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00090-of-00512
- out=data/fsns/train/train-00090-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00091-of-00512
- out=data/fsns/train/train-00091-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00092-of-00512
- out=data/fsns/train/train-00092-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00093-of-00512
- out=data/fsns/train/train-00093-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00094-of-00512
- out=data/fsns/train/train-00094-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00095-of-00512
- out=data/fsns/train/train-00095-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00096-of-00512
- out=data/fsns/train/train-00096-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00097-of-00512
- out=data/fsns/train/train-00097-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00098-of-00512
- out=data/fsns/train/train-00098-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00099-of-00512
- out=data/fsns/train/train-00099-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00100-of-00512
- out=data/fsns/train/train-00100-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00101-of-00512
- out=data/fsns/train/train-00101-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00102-of-00512
- out=data/fsns/train/train-00102-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00103-of-00512
- out=data/fsns/train/train-00103-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00104-of-00512
- out=data/fsns/train/train-00104-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00105-of-00512
- out=data/fsns/train/train-00105-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00106-of-00512
- out=data/fsns/train/train-00106-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00107-of-00512
- out=data/fsns/train/train-00107-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00108-of-00512
- out=data/fsns/train/train-00108-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00109-of-00512
- out=data/fsns/train/train-00109-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00110-of-00512
- out=data/fsns/train/train-00110-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00111-of-00512
- out=data/fsns/train/train-00111-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00112-of-00512
- out=data/fsns/train/train-00112-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00113-of-00512
- out=data/fsns/train/train-00113-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00114-of-00512
- out=data/fsns/train/train-00114-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00115-of-00512
- out=data/fsns/train/train-00115-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00116-of-00512
- out=data/fsns/train/train-00116-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00117-of-00512
- out=data/fsns/train/train-00117-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00118-of-00512
- out=data/fsns/train/train-00118-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00119-of-00512
- out=data/fsns/train/train-00119-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00120-of-00512
- out=data/fsns/train/train-00120-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00121-of-00512
- out=data/fsns/train/train-00121-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00122-of-00512
- out=data/fsns/train/train-00122-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00123-of-00512
- out=data/fsns/train/train-00123-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00124-of-00512
- out=data/fsns/train/train-00124-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00125-of-00512
- out=data/fsns/train/train-00125-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00126-of-00512
- out=data/fsns/train/train-00126-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00127-of-00512
- out=data/fsns/train/train-00127-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00128-of-00512
- out=data/fsns/train/train-00128-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00129-of-00512
- out=data/fsns/train/train-00129-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00130-of-00512
- out=data/fsns/train/train-00130-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00131-of-00512
- out=data/fsns/train/train-00131-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00132-of-00512
- out=data/fsns/train/train-00132-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00133-of-00512
- out=data/fsns/train/train-00133-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00134-of-00512
- out=data/fsns/train/train-00134-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00135-of-00512
- out=data/fsns/train/train-00135-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00136-of-00512
- out=data/fsns/train/train-00136-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00137-of-00512
- out=data/fsns/train/train-00137-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00138-of-00512
- out=data/fsns/train/train-00138-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00139-of-00512
- out=data/fsns/train/train-00139-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00140-of-00512
- out=data/fsns/train/train-00140-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00141-of-00512
- out=data/fsns/train/train-00141-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00142-of-00512
- out=data/fsns/train/train-00142-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00143-of-00512
- out=data/fsns/train/train-00143-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00144-of-00512
- out=data/fsns/train/train-00144-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00145-of-00512
- out=data/fsns/train/train-00145-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00146-of-00512
- out=data/fsns/train/train-00146-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00147-of-00512
- out=data/fsns/train/train-00147-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00148-of-00512
- out=data/fsns/train/train-00148-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00149-of-00512
- out=data/fsns/train/train-00149-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00150-of-00512
- out=data/fsns/train/train-00150-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00151-of-00512
- out=data/fsns/train/train-00151-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00152-of-00512
- out=data/fsns/train/train-00152-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00153-of-00512
- out=data/fsns/train/train-00153-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00154-of-00512
- out=data/fsns/train/train-00154-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00155-of-00512
- out=data/fsns/train/train-00155-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00156-of-00512
- out=data/fsns/train/train-00156-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00157-of-00512
- out=data/fsns/train/train-00157-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00158-of-00512
- out=data/fsns/train/train-00158-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00159-of-00512
- out=data/fsns/train/train-00159-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00160-of-00512
- out=data/fsns/train/train-00160-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00161-of-00512
- out=data/fsns/train/train-00161-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00162-of-00512
- out=data/fsns/train/train-00162-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00163-of-00512
- out=data/fsns/train/train-00163-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00164-of-00512
- out=data/fsns/train/train-00164-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00165-of-00512
- out=data/fsns/train/train-00165-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00166-of-00512
- out=data/fsns/train/train-00166-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00167-of-00512
- out=data/fsns/train/train-00167-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00168-of-00512
- out=data/fsns/train/train-00168-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00169-of-00512
- out=data/fsns/train/train-00169-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00170-of-00512
- out=data/fsns/train/train-00170-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00171-of-00512
- out=data/fsns/train/train-00171-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00172-of-00512
- out=data/fsns/train/train-00172-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00173-of-00512
- out=data/fsns/train/train-00173-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00174-of-00512
- out=data/fsns/train/train-00174-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00175-of-00512
- out=data/fsns/train/train-00175-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00176-of-00512
- out=data/fsns/train/train-00176-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00177-of-00512
- out=data/fsns/train/train-00177-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00178-of-00512
- out=data/fsns/train/train-00178-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00179-of-00512
- out=data/fsns/train/train-00179-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00180-of-00512
- out=data/fsns/train/train-00180-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00181-of-00512
- out=data/fsns/train/train-00181-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00182-of-00512
- out=data/fsns/train/train-00182-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00183-of-00512
- out=data/fsns/train/train-00183-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00184-of-00512
- out=data/fsns/train/train-00184-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00185-of-00512
- out=data/fsns/train/train-00185-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00186-of-00512
- out=data/fsns/train/train-00186-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00187-of-00512
- out=data/fsns/train/train-00187-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00188-of-00512
- out=data/fsns/train/train-00188-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00189-of-00512
- out=data/fsns/train/train-00189-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00190-of-00512
- out=data/fsns/train/train-00190-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00191-of-00512
- out=data/fsns/train/train-00191-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00192-of-00512
- out=data/fsns/train/train-00192-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00193-of-00512
- out=data/fsns/train/train-00193-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00194-of-00512
- out=data/fsns/train/train-00194-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00195-of-00512
- out=data/fsns/train/train-00195-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00196-of-00512
- out=data/fsns/train/train-00196-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00197-of-00512
- out=data/fsns/train/train-00197-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00198-of-00512
- out=data/fsns/train/train-00198-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00199-of-00512
- out=data/fsns/train/train-00199-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00200-of-00512
- out=data/fsns/train/train-00200-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00201-of-00512
- out=data/fsns/train/train-00201-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00202-of-00512
- out=data/fsns/train/train-00202-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00203-of-00512
- out=data/fsns/train/train-00203-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00204-of-00512
- out=data/fsns/train/train-00204-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00205-of-00512
- out=data/fsns/train/train-00205-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00206-of-00512
- out=data/fsns/train/train-00206-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00207-of-00512
- out=data/fsns/train/train-00207-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00208-of-00512
- out=data/fsns/train/train-00208-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00209-of-00512
- out=data/fsns/train/train-00209-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00210-of-00512
- out=data/fsns/train/train-00210-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00211-of-00512
- out=data/fsns/train/train-00211-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00212-of-00512
- out=data/fsns/train/train-00212-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00213-of-00512
- out=data/fsns/train/train-00213-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00214-of-00512
- out=data/fsns/train/train-00214-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00215-of-00512
- out=data/fsns/train/train-00215-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00216-of-00512
- out=data/fsns/train/train-00216-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00217-of-00512
- out=data/fsns/train/train-00217-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00218-of-00512
- out=data/fsns/train/train-00218-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00219-of-00512
- out=data/fsns/train/train-00219-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00220-of-00512
- out=data/fsns/train/train-00220-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00221-of-00512
- out=data/fsns/train/train-00221-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00222-of-00512
- out=data/fsns/train/train-00222-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00223-of-00512
- out=data/fsns/train/train-00223-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00224-of-00512
- out=data/fsns/train/train-00224-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00225-of-00512
- out=data/fsns/train/train-00225-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00226-of-00512
- out=data/fsns/train/train-00226-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00227-of-00512
- out=data/fsns/train/train-00227-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00228-of-00512
- out=data/fsns/train/train-00228-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00229-of-00512
- out=data/fsns/train/train-00229-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00230-of-00512
- out=data/fsns/train/train-00230-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00231-of-00512
- out=data/fsns/train/train-00231-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00232-of-00512
- out=data/fsns/train/train-00232-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00233-of-00512
- out=data/fsns/train/train-00233-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00234-of-00512
- out=data/fsns/train/train-00234-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00235-of-00512
- out=data/fsns/train/train-00235-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00236-of-00512
- out=data/fsns/train/train-00236-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00237-of-00512
- out=data/fsns/train/train-00237-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00238-of-00512
- out=data/fsns/train/train-00238-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00239-of-00512
- out=data/fsns/train/train-00239-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00240-of-00512
- out=data/fsns/train/train-00240-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00241-of-00512
- out=data/fsns/train/train-00241-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00242-of-00512
- out=data/fsns/train/train-00242-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00243-of-00512
- out=data/fsns/train/train-00243-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00244-of-00512
- out=data/fsns/train/train-00244-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00245-of-00512
- out=data/fsns/train/train-00245-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00246-of-00512
- out=data/fsns/train/train-00246-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00247-of-00512
- out=data/fsns/train/train-00247-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00248-of-00512
- out=data/fsns/train/train-00248-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00249-of-00512
- out=data/fsns/train/train-00249-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00250-of-00512
- out=data/fsns/train/train-00250-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00251-of-00512
- out=data/fsns/train/train-00251-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00252-of-00512
- out=data/fsns/train/train-00252-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00253-of-00512
- out=data/fsns/train/train-00253-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00254-of-00512
- out=data/fsns/train/train-00254-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00255-of-00512
- out=data/fsns/train/train-00255-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00256-of-00512
- out=data/fsns/train/train-00256-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00257-of-00512
- out=data/fsns/train/train-00257-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00258-of-00512
- out=data/fsns/train/train-00258-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00259-of-00512
- out=data/fsns/train/train-00259-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00260-of-00512
- out=data/fsns/train/train-00260-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00261-of-00512
- out=data/fsns/train/train-00261-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00262-of-00512
- out=data/fsns/train/train-00262-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00263-of-00512
- out=data/fsns/train/train-00263-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00264-of-00512
- out=data/fsns/train/train-00264-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00265-of-00512
- out=data/fsns/train/train-00265-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00266-of-00512
- out=data/fsns/train/train-00266-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00267-of-00512
- out=data/fsns/train/train-00267-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00268-of-00512
- out=data/fsns/train/train-00268-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00269-of-00512
- out=data/fsns/train/train-00269-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00270-of-00512
- out=data/fsns/train/train-00270-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00271-of-00512
- out=data/fsns/train/train-00271-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00272-of-00512
- out=data/fsns/train/train-00272-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00273-of-00512
- out=data/fsns/train/train-00273-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00274-of-00512
- out=data/fsns/train/train-00274-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00275-of-00512
- out=data/fsns/train/train-00275-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00276-of-00512
- out=data/fsns/train/train-00276-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00277-of-00512
- out=data/fsns/train/train-00277-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00278-of-00512
- out=data/fsns/train/train-00278-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00279-of-00512
- out=data/fsns/train/train-00279-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00280-of-00512
- out=data/fsns/train/train-00280-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00281-of-00512
- out=data/fsns/train/train-00281-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00282-of-00512
- out=data/fsns/train/train-00282-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00283-of-00512
- out=data/fsns/train/train-00283-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00284-of-00512
- out=data/fsns/train/train-00284-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00285-of-00512
- out=data/fsns/train/train-00285-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00286-of-00512
- out=data/fsns/train/train-00286-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00287-of-00512
- out=data/fsns/train/train-00287-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00288-of-00512
- out=data/fsns/train/train-00288-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00289-of-00512
- out=data/fsns/train/train-00289-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00290-of-00512
- out=data/fsns/train/train-00290-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00291-of-00512
- out=data/fsns/train/train-00291-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00292-of-00512
- out=data/fsns/train/train-00292-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00293-of-00512
- out=data/fsns/train/train-00293-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00294-of-00512
- out=data/fsns/train/train-00294-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00295-of-00512
- out=data/fsns/train/train-00295-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00296-of-00512
- out=data/fsns/train/train-00296-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00297-of-00512
- out=data/fsns/train/train-00297-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00298-of-00512
- out=data/fsns/train/train-00298-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00299-of-00512
- out=data/fsns/train/train-00299-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00300-of-00512
- out=data/fsns/train/train-00300-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00301-of-00512
- out=data/fsns/train/train-00301-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00302-of-00512
- out=data/fsns/train/train-00302-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00303-of-00512
- out=data/fsns/train/train-00303-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00304-of-00512
- out=data/fsns/train/train-00304-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00305-of-00512
- out=data/fsns/train/train-00305-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00306-of-00512
- out=data/fsns/train/train-00306-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00307-of-00512
- out=data/fsns/train/train-00307-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00308-of-00512
- out=data/fsns/train/train-00308-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00309-of-00512
- out=data/fsns/train/train-00309-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00310-of-00512
- out=data/fsns/train/train-00310-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00311-of-00512
- out=data/fsns/train/train-00311-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00312-of-00512
- out=data/fsns/train/train-00312-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00313-of-00512
- out=data/fsns/train/train-00313-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00314-of-00512
- out=data/fsns/train/train-00314-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00315-of-00512
- out=data/fsns/train/train-00315-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00316-of-00512
- out=data/fsns/train/train-00316-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00317-of-00512
- out=data/fsns/train/train-00317-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00318-of-00512
- out=data/fsns/train/train-00318-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00319-of-00512
- out=data/fsns/train/train-00319-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00320-of-00512
- out=data/fsns/train/train-00320-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00321-of-00512
- out=data/fsns/train/train-00321-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00322-of-00512
- out=data/fsns/train/train-00322-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00323-of-00512
- out=data/fsns/train/train-00323-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00324-of-00512
- out=data/fsns/train/train-00324-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00325-of-00512
- out=data/fsns/train/train-00325-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00326-of-00512
- out=data/fsns/train/train-00326-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00327-of-00512
- out=data/fsns/train/train-00327-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00328-of-00512
- out=data/fsns/train/train-00328-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00329-of-00512
- out=data/fsns/train/train-00329-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00330-of-00512
- out=data/fsns/train/train-00330-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00331-of-00512
- out=data/fsns/train/train-00331-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00332-of-00512
- out=data/fsns/train/train-00332-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00333-of-00512
- out=data/fsns/train/train-00333-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00334-of-00512
- out=data/fsns/train/train-00334-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00335-of-00512
- out=data/fsns/train/train-00335-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00336-of-00512
- out=data/fsns/train/train-00336-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00337-of-00512
- out=data/fsns/train/train-00337-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00338-of-00512
- out=data/fsns/train/train-00338-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00339-of-00512
- out=data/fsns/train/train-00339-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00340-of-00512
- out=data/fsns/train/train-00340-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00341-of-00512
- out=data/fsns/train/train-00341-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00342-of-00512
- out=data/fsns/train/train-00342-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00343-of-00512
- out=data/fsns/train/train-00343-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00344-of-00512
- out=data/fsns/train/train-00344-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00345-of-00512
- out=data/fsns/train/train-00345-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00346-of-00512
- out=data/fsns/train/train-00346-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00347-of-00512
- out=data/fsns/train/train-00347-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00348-of-00512
- out=data/fsns/train/train-00348-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00349-of-00512
- out=data/fsns/train/train-00349-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00350-of-00512
- out=data/fsns/train/train-00350-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00351-of-00512
- out=data/fsns/train/train-00351-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00352-of-00512
- out=data/fsns/train/train-00352-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00353-of-00512
- out=data/fsns/train/train-00353-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00354-of-00512
- out=data/fsns/train/train-00354-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00355-of-00512
- out=data/fsns/train/train-00355-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00356-of-00512
- out=data/fsns/train/train-00356-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00357-of-00512
- out=data/fsns/train/train-00357-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00358-of-00512
- out=data/fsns/train/train-00358-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00359-of-00512
- out=data/fsns/train/train-00359-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00360-of-00512
- out=data/fsns/train/train-00360-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00361-of-00512
- out=data/fsns/train/train-00361-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00362-of-00512
- out=data/fsns/train/train-00362-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00363-of-00512
- out=data/fsns/train/train-00363-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00364-of-00512
- out=data/fsns/train/train-00364-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00365-of-00512
- out=data/fsns/train/train-00365-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00366-of-00512
- out=data/fsns/train/train-00366-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00367-of-00512
- out=data/fsns/train/train-00367-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00368-of-00512
- out=data/fsns/train/train-00368-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00369-of-00512
- out=data/fsns/train/train-00369-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00370-of-00512
- out=data/fsns/train/train-00370-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00371-of-00512
- out=data/fsns/train/train-00371-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00372-of-00512
- out=data/fsns/train/train-00372-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00373-of-00512
- out=data/fsns/train/train-00373-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00374-of-00512
- out=data/fsns/train/train-00374-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00375-of-00512
- out=data/fsns/train/train-00375-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00376-of-00512
- out=data/fsns/train/train-00376-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00377-of-00512
- out=data/fsns/train/train-00377-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00378-of-00512
- out=data/fsns/train/train-00378-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00379-of-00512
- out=data/fsns/train/train-00379-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00380-of-00512
- out=data/fsns/train/train-00380-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00381-of-00512
- out=data/fsns/train/train-00381-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00382-of-00512
- out=data/fsns/train/train-00382-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00383-of-00512
- out=data/fsns/train/train-00383-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00384-of-00512
- out=data/fsns/train/train-00384-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00385-of-00512
- out=data/fsns/train/train-00385-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00386-of-00512
- out=data/fsns/train/train-00386-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00387-of-00512
- out=data/fsns/train/train-00387-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00388-of-00512
- out=data/fsns/train/train-00388-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00389-of-00512
- out=data/fsns/train/train-00389-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00390-of-00512
- out=data/fsns/train/train-00390-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00391-of-00512
- out=data/fsns/train/train-00391-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00392-of-00512
- out=data/fsns/train/train-00392-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00393-of-00512
- out=data/fsns/train/train-00393-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00394-of-00512
- out=data/fsns/train/train-00394-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00395-of-00512
- out=data/fsns/train/train-00395-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00396-of-00512
- out=data/fsns/train/train-00396-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00397-of-00512
- out=data/fsns/train/train-00397-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00398-of-00512
- out=data/fsns/train/train-00398-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00399-of-00512
- out=data/fsns/train/train-00399-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00400-of-00512
- out=data/fsns/train/train-00400-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00401-of-00512
- out=data/fsns/train/train-00401-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00402-of-00512
- out=data/fsns/train/train-00402-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00403-of-00512
- out=data/fsns/train/train-00403-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00404-of-00512
- out=data/fsns/train/train-00404-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00405-of-00512
- out=data/fsns/train/train-00405-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00406-of-00512
- out=data/fsns/train/train-00406-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00407-of-00512
- out=data/fsns/train/train-00407-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00408-of-00512
- out=data/fsns/train/train-00408-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00409-of-00512
- out=data/fsns/train/train-00409-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00410-of-00512
- out=data/fsns/train/train-00410-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00411-of-00512
- out=data/fsns/train/train-00411-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00412-of-00512
- out=data/fsns/train/train-00412-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00413-of-00512
- out=data/fsns/train/train-00413-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00414-of-00512
- out=data/fsns/train/train-00414-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00415-of-00512
- out=data/fsns/train/train-00415-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00416-of-00512
- out=data/fsns/train/train-00416-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00417-of-00512
- out=data/fsns/train/train-00417-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00418-of-00512
- out=data/fsns/train/train-00418-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00419-of-00512
- out=data/fsns/train/train-00419-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00420-of-00512
- out=data/fsns/train/train-00420-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00421-of-00512
- out=data/fsns/train/train-00421-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00422-of-00512
- out=data/fsns/train/train-00422-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00423-of-00512
- out=data/fsns/train/train-00423-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00424-of-00512
- out=data/fsns/train/train-00424-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00425-of-00512
- out=data/fsns/train/train-00425-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00426-of-00512
- out=data/fsns/train/train-00426-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00427-of-00512
- out=data/fsns/train/train-00427-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00428-of-00512
- out=data/fsns/train/train-00428-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00429-of-00512
- out=data/fsns/train/train-00429-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00430-of-00512
- out=data/fsns/train/train-00430-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00431-of-00512
- out=data/fsns/train/train-00431-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00432-of-00512
- out=data/fsns/train/train-00432-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00433-of-00512
- out=data/fsns/train/train-00433-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00434-of-00512
- out=data/fsns/train/train-00434-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00435-of-00512
- out=data/fsns/train/train-00435-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00436-of-00512
- out=data/fsns/train/train-00436-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00437-of-00512
- out=data/fsns/train/train-00437-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00438-of-00512
- out=data/fsns/train/train-00438-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00439-of-00512
- out=data/fsns/train/train-00439-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00440-of-00512
- out=data/fsns/train/train-00440-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00441-of-00512
- out=data/fsns/train/train-00441-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00442-of-00512
- out=data/fsns/train/train-00442-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00443-of-00512
- out=data/fsns/train/train-00443-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00444-of-00512
- out=data/fsns/train/train-00444-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00445-of-00512
- out=data/fsns/train/train-00445-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00446-of-00512
- out=data/fsns/train/train-00446-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00447-of-00512
- out=data/fsns/train/train-00447-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00448-of-00512
- out=data/fsns/train/train-00448-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00449-of-00512
- out=data/fsns/train/train-00449-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00450-of-00512
- out=data/fsns/train/train-00450-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00451-of-00512
- out=data/fsns/train/train-00451-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00452-of-00512
- out=data/fsns/train/train-00452-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00453-of-00512
- out=data/fsns/train/train-00453-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00454-of-00512
- out=data/fsns/train/train-00454-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00455-of-00512
- out=data/fsns/train/train-00455-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00456-of-00512
- out=data/fsns/train/train-00456-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00457-of-00512
- out=data/fsns/train/train-00457-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00458-of-00512
- out=data/fsns/train/train-00458-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00459-of-00512
- out=data/fsns/train/train-00459-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00460-of-00512
- out=data/fsns/train/train-00460-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00461-of-00512
- out=data/fsns/train/train-00461-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00462-of-00512
- out=data/fsns/train/train-00462-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00463-of-00512
- out=data/fsns/train/train-00463-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00464-of-00512
- out=data/fsns/train/train-00464-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00465-of-00512
- out=data/fsns/train/train-00465-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00466-of-00512
- out=data/fsns/train/train-00466-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00467-of-00512
- out=data/fsns/train/train-00467-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00468-of-00512
- out=data/fsns/train/train-00468-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00469-of-00512
- out=data/fsns/train/train-00469-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00470-of-00512
- out=data/fsns/train/train-00470-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00471-of-00512
- out=data/fsns/train/train-00471-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00472-of-00512
- out=data/fsns/train/train-00472-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00473-of-00512
- out=data/fsns/train/train-00473-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00474-of-00512
- out=data/fsns/train/train-00474-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00475-of-00512
- out=data/fsns/train/train-00475-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00476-of-00512
- out=data/fsns/train/train-00476-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00477-of-00512
- out=data/fsns/train/train-00477-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00478-of-00512
- out=data/fsns/train/train-00478-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00479-of-00512
- out=data/fsns/train/train-00479-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00480-of-00512
- out=data/fsns/train/train-00480-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00481-of-00512
- out=data/fsns/train/train-00481-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00482-of-00512
- out=data/fsns/train/train-00482-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00483-of-00512
- out=data/fsns/train/train-00483-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00484-of-00512
- out=data/fsns/train/train-00484-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00485-of-00512
- out=data/fsns/train/train-00485-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00486-of-00512
- out=data/fsns/train/train-00486-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00487-of-00512
- out=data/fsns/train/train-00487-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00488-of-00512
- out=data/fsns/train/train-00488-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00489-of-00512
- out=data/fsns/train/train-00489-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00490-of-00512
- out=data/fsns/train/train-00490-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00491-of-00512
- out=data/fsns/train/train-00491-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00492-of-00512
- out=data/fsns/train/train-00492-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00493-of-00512
- out=data/fsns/train/train-00493-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00494-of-00512
- out=data/fsns/train/train-00494-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00495-of-00512
- out=data/fsns/train/train-00495-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00496-of-00512
- out=data/fsns/train/train-00496-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00497-of-00512
- out=data/fsns/train/train-00497-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00498-of-00512
- out=data/fsns/train/train-00498-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00499-of-00512
- out=data/fsns/train/train-00499-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00500-of-00512
- out=data/fsns/train/train-00500-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00501-of-00512
- out=data/fsns/train/train-00501-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00502-of-00512
- out=data/fsns/train/train-00502-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00503-of-00512
- out=data/fsns/train/train-00503-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00504-of-00512
- out=data/fsns/train/train-00504-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00505-of-00512
- out=data/fsns/train/train-00505-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00506-of-00512
- out=data/fsns/train/train-00506-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00507-of-00512
- out=data/fsns/train/train-00507-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00508-of-00512
- out=data/fsns/train/train-00508-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00509-of-00512
- out=data/fsns/train/train-00509-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00510-of-00512
- out=data/fsns/train/train-00510-of-00512
-http://download.tensorflow.org/data/fsns-20160927/train/train-00511-of-00512
- out=data/fsns/train/train-00511-of-00512
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00000-of-00064
- out=data/fsns/validation/validation-00000-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00001-of-00064
- out=data/fsns/validation/validation-00001-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00002-of-00064
- out=data/fsns/validation/validation-00002-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00003-of-00064
- out=data/fsns/validation/validation-00003-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00004-of-00064
- out=data/fsns/validation/validation-00004-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00005-of-00064
- out=data/fsns/validation/validation-00005-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00006-of-00064
- out=data/fsns/validation/validation-00006-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00007-of-00064
- out=data/fsns/validation/validation-00007-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00008-of-00064
- out=data/fsns/validation/validation-00008-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00009-of-00064
- out=data/fsns/validation/validation-00009-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00010-of-00064
- out=data/fsns/validation/validation-00010-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00011-of-00064
- out=data/fsns/validation/validation-00011-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00012-of-00064
- out=data/fsns/validation/validation-00012-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00013-of-00064
- out=data/fsns/validation/validation-00013-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00014-of-00064
- out=data/fsns/validation/validation-00014-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00015-of-00064
- out=data/fsns/validation/validation-00015-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00016-of-00064
- out=data/fsns/validation/validation-00016-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00017-of-00064
- out=data/fsns/validation/validation-00017-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00018-of-00064
- out=data/fsns/validation/validation-00018-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00019-of-00064
- out=data/fsns/validation/validation-00019-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00020-of-00064
- out=data/fsns/validation/validation-00020-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00021-of-00064
- out=data/fsns/validation/validation-00021-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00022-of-00064
- out=data/fsns/validation/validation-00022-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00023-of-00064
- out=data/fsns/validation/validation-00023-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00024-of-00064
- out=data/fsns/validation/validation-00024-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00025-of-00064
- out=data/fsns/validation/validation-00025-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00026-of-00064
- out=data/fsns/validation/validation-00026-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00027-of-00064
- out=data/fsns/validation/validation-00027-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00028-of-00064
- out=data/fsns/validation/validation-00028-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00029-of-00064
- out=data/fsns/validation/validation-00029-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00030-of-00064
- out=data/fsns/validation/validation-00030-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00031-of-00064
- out=data/fsns/validation/validation-00031-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00032-of-00064
- out=data/fsns/validation/validation-00032-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00033-of-00064
- out=data/fsns/validation/validation-00033-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00034-of-00064
- out=data/fsns/validation/validation-00034-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00035-of-00064
- out=data/fsns/validation/validation-00035-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00036-of-00064
- out=data/fsns/validation/validation-00036-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00037-of-00064
- out=data/fsns/validation/validation-00037-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00038-of-00064
- out=data/fsns/validation/validation-00038-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00039-of-00064
- out=data/fsns/validation/validation-00039-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00040-of-00064
- out=data/fsns/validation/validation-00040-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00041-of-00064
- out=data/fsns/validation/validation-00041-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00042-of-00064
- out=data/fsns/validation/validation-00042-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00043-of-00064
- out=data/fsns/validation/validation-00043-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00044-of-00064
- out=data/fsns/validation/validation-00044-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00045-of-00064
- out=data/fsns/validation/validation-00045-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00046-of-00064
- out=data/fsns/validation/validation-00046-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00047-of-00064
- out=data/fsns/validation/validation-00047-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00048-of-00064
- out=data/fsns/validation/validation-00048-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00049-of-00064
- out=data/fsns/validation/validation-00049-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00050-of-00064
- out=data/fsns/validation/validation-00050-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00051-of-00064
- out=data/fsns/validation/validation-00051-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00052-of-00064
- out=data/fsns/validation/validation-00052-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00053-of-00064
- out=data/fsns/validation/validation-00053-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00054-of-00064
- out=data/fsns/validation/validation-00054-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00055-of-00064
- out=data/fsns/validation/validation-00055-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00056-of-00064
- out=data/fsns/validation/validation-00056-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00057-of-00064
- out=data/fsns/validation/validation-00057-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00058-of-00064
- out=data/fsns/validation/validation-00058-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00059-of-00064
- out=data/fsns/validation/validation-00059-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00060-of-00064
- out=data/fsns/validation/validation-00060-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00061-of-00064
- out=data/fsns/validation/validation-00061-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00062-of-00064
- out=data/fsns/validation/validation-00062-of-00064
-http://download.tensorflow.org/data/fsns-20160927/validation/validation-00063-of-00064
- out=data/fsns/validation/validation-00063-of-00064
diff --git a/research/street/python/nn_ops.py b/research/street/python/nn_ops.py
deleted file mode 100644
index 20c3b502853bbec80f30e9d2aa915477fa674c62..0000000000000000000000000000000000000000
--- a/research/street/python/nn_ops.py
+++ /dev/null
@@ -1,253 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Ops and utilities for neural networks.
-
-For now, just an LSTM layer.
-"""
-import shapes
-import tensorflow as tf
-rnn = tf.load_op_library("../cc/rnn_ops.so")
-
-
-def rnn_helper(inp,
- length,
- cell_type=None,
- direction="forward",
- name=None,
- *args,
- **kwargs):
- """Adds ops for a recurrent neural network layer.
-
- This function calls an actual implementation of a recurrent neural network
- based on `cell_type`.
-
- There are three modes depending on the value of `direction`:
-
- forward: Adds a forward RNN.
- backward: Adds a backward RNN.
- bidirectional: Adds both forward and backward RNNs and creates a
- bidirectional RNN.
-
- Args:
- inp: A 3-D tensor of shape [`batch_size`, `max_length`, `feature_dim`].
- length: A 1-D tensor of shape [`batch_size`] and type int64. Each element
- represents the length of the corresponding sequence in `inp`.
- cell_type: Cell type of RNN. Currently can only be "lstm".
- direction: One of "forward", "backward", "bidirectional".
- name: Name of the op.
- *args: Other arguments to the layer.
- **kwargs: Keyword arugments to the layer.
-
- Returns:
- A 3-D tensor of shape [`batch_size`, `max_length`, `num_nodes`].
- """
-
- assert cell_type is not None
- rnn_func = None
- if cell_type == "lstm":
- rnn_func = lstm_layer
- assert rnn_func is not None
- assert direction in ["forward", "backward", "bidirectional"]
-
- with tf.variable_scope(name):
- if direction in ["forward", "bidirectional"]:
- forward = rnn_func(
- inp=inp,
- length=length,
- backward=False,
- name="forward",
- *args,
- **kwargs)
- if isinstance(forward, tuple):
- # lstm_layer returns a tuple (output, memory). We only need the first
- # element.
- forward = forward[0]
- if direction in ["backward", "bidirectional"]:
- backward = rnn_func(
- inp=inp,
- length=length,
- backward=True,
- name="backward",
- *args,
- **kwargs)
- if isinstance(backward, tuple):
- # lstm_layer returns a tuple (output, memory). We only need the first
- # element.
- backward = backward[0]
- if direction == "forward":
- out = forward
- elif direction == "backward":
- out = backward
- else:
- out = tf.concat(axis=2, values=[forward, backward])
- return out
-
-
-@tf.RegisterShape("VariableLSTM")
-def _variable_lstm_shape(op):
- """Shape function for the VariableLSTM op."""
- input_shape = op.inputs[0].get_shape().with_rank(4)
- state_shape = op.inputs[1].get_shape().with_rank(2)
- memory_shape = op.inputs[2].get_shape().with_rank(2)
- w_m_m_shape = op.inputs[3].get_shape().with_rank(3)
- batch_size = input_shape[0].merge_with(state_shape[0])
- batch_size = input_shape[0].merge_with(memory_shape[0])
- seq_len = input_shape[1]
- gate_num = input_shape[2].merge_with(w_m_m_shape[1])
- output_dim = input_shape[3].merge_with(state_shape[1])
- output_dim = output_dim.merge_with(memory_shape[1])
- output_dim = output_dim.merge_with(w_m_m_shape[0])
- output_dim = output_dim.merge_with(w_m_m_shape[2])
- return [[batch_size, seq_len, output_dim],
- [batch_size, seq_len, gate_num, output_dim],
- [batch_size, seq_len, output_dim]]
-
-
-@tf.RegisterGradient("VariableLSTM")
-def _variable_lstm_grad(op, act_grad, gate_grad, mem_grad):
- """Gradient function for the VariableLSTM op."""
- initial_state = op.inputs[1]
- initial_memory = op.inputs[2]
- w_m_m = op.inputs[3]
- act = op.outputs[0]
- gate_raw_act = op.outputs[1]
- memory = op.outputs[2]
- return rnn.variable_lstm_grad(initial_state, initial_memory, w_m_m, act,
- gate_raw_act, memory, act_grad, gate_grad,
- mem_grad)
-
-
-def lstm_layer(inp,
- length=None,
- state=None,
- memory=None,
- num_nodes=None,
- backward=False,
- clip=50.0,
- reg_func=tf.nn.l2_loss,
- weight_reg=False,
- weight_collection="LSTMWeights",
- bias_reg=False,
- stddev=None,
- seed=None,
- decode=False,
- use_native_weights=False,
- name=None):
- """Adds ops for an LSTM layer.
-
- This adds ops for the following operations:
-
- input => (forward-LSTM|backward-LSTM) => output
-
- The direction of the LSTM is determined by `backward`. If it is false, the
- forward LSTM is used, the backward one otherwise.
-
- Args:
- inp: A 3-D tensor of shape [`batch_size`, `max_length`, `feature_dim`].
- length: A 1-D tensor of shape [`batch_size`] and type int64. Each element
- represents the length of the corresponding sequence in `inp`.
- state: If specified, uses it as the initial state.
- memory: If specified, uses it as the initial memory.
- num_nodes: The number of LSTM cells.
- backward: If true, reverses the `inp` before adding the ops. The output is
- also reversed so that the direction is the same as `inp`.
- clip: Value used to clip the cell values.
- reg_func: Function used for the weight regularization such as
- `tf.nn.l2_loss`.
- weight_reg: If true, regularize the filter weights with `reg_func`.
- weight_collection: Collection to add the weights to for regularization.
- bias_reg: If true, regularize the bias vector with `reg_func`.
- stddev: Standard deviation used to initialize the variables.
- seed: Seed used to initialize the variables.
- decode: If true, does not add ops which are not used for inference.
- use_native_weights: If true, uses weights in the same format as the native
- implementations.
- name: Name of the op.
-
- Returns:
- A 3-D tensor of shape [`batch_size`, `max_length`, `num_nodes`].
- """
- with tf.variable_scope(name):
- if backward:
- if length is None:
- inp = tf.reverse(inp, [1])
- else:
- inp = tf.reverse_sequence(inp, length, 1, 0)
-
- num_prev = inp.get_shape()[2]
- if stddev:
- initializer = tf.truncated_normal_initializer(stddev=stddev, seed=seed)
- else:
- initializer = tf.uniform_unit_scaling_initializer(seed=seed)
-
- if use_native_weights:
- with tf.variable_scope("LSTMCell"):
- w = tf.get_variable(
- "W_0",
- shape=[num_prev + num_nodes, 4 * num_nodes],
- initializer=initializer,
- dtype=tf.float32)
- w_i_m = tf.slice(w, [0, 0], [num_prev, 4 * num_nodes], name="w_i_m")
- w_m_m = tf.reshape(
- tf.slice(w, [num_prev, 0], [num_nodes, 4 * num_nodes]),
- [num_nodes, 4, num_nodes],
- name="w_m_m")
- else:
- w_i_m = tf.get_variable("w_i_m", [num_prev, 4 * num_nodes],
- initializer=initializer)
- w_m_m = tf.get_variable("w_m_m", [num_nodes, 4, num_nodes],
- initializer=initializer)
-
- if not decode and weight_reg:
- tf.add_to_collection(weight_collection, reg_func(w_i_m, name="w_i_m_reg"))
- tf.add_to_collection(weight_collection, reg_func(w_m_m, name="w_m_m_reg"))
-
- batch_size = shapes.tensor_dim(inp, dim=0)
- num_frames = shapes.tensor_dim(inp, dim=1)
- prev = tf.reshape(inp, tf.stack([batch_size * num_frames, num_prev]))
-
- if use_native_weights:
- with tf.variable_scope("LSTMCell"):
- b = tf.get_variable(
- "B",
- shape=[4 * num_nodes],
- initializer=tf.zeros_initializer(),
- dtype=tf.float32)
- biases = tf.identity(b, name="biases")
- else:
- biases = tf.get_variable(
- "biases", [4 * num_nodes], initializer=tf.constant_initializer(0.0))
- if not decode and bias_reg:
- tf.add_to_collection(
- weight_collection, reg_func(
- biases, name="biases_reg"))
- prev = tf.nn.xw_plus_b(prev, w_i_m, biases)
-
- prev = tf.reshape(prev, tf.stack([batch_size, num_frames, 4, num_nodes]))
- if state is None:
- state = tf.fill(tf.stack([batch_size, num_nodes]), 0.0)
- if memory is None:
- memory = tf.fill(tf.stack([batch_size, num_nodes]), 0.0)
-
- out, _, mem = rnn.variable_lstm(prev, state, memory, w_m_m, clip=clip)
-
- if backward:
- if length is None:
- out = tf.reverse(out, [1])
- else:
- out = tf.reverse_sequence(out, length, 1, 0)
-
- return out, mem
diff --git a/research/street/python/shapes.py b/research/street/python/shapes.py
deleted file mode 100644
index 1f56ef05d5c59b6c626eabffa680999a777301fc..0000000000000000000000000000000000000000
--- a/research/street/python/shapes.py
+++ /dev/null
@@ -1,217 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Shape manipulation functions.
-
-rotate_dimensions: prepares for a rotating transpose by returning a rotated
- list of dimension indices.
-transposing_reshape: allows a dimension to be factorized, with one of the pieces
- transferred to another dimension, or to transpose factors within a single
- dimension.
-tensor_dim: gets a shape dimension as a constant integer if known otherwise a
- runtime usable tensor value.
-tensor_shape: returns the full shape of a tensor as the tensor_dim.
-"""
-from six.moves import xrange
-import tensorflow as tf
-
-
-def rotate_dimensions(num_dims, src_dim, dest_dim):
- """Returns a list of dimension indices that will rotate src_dim to dest_dim.
-
- src_dim is moved to dest_dim, with all intervening dimensions shifted towards
- the hole left by src_dim. Eg:
- num_dims = 4, src_dim=3, dest_dim=1
- Returned list=[0, 3, 1, 2]
- For a tensor with dims=[5, 4, 3, 2] a transpose would yield [5, 2, 4, 3].
- Args:
- num_dims: The number of dimensions to handle.
- src_dim: The dimension to move.
- dest_dim: The dimension to move src_dim to.
-
- Returns:
- A list of rotated dimension indices.
- """
- # List of dimensions for transpose.
- dim_list = range(num_dims)
- # Shuffle src_dim to dest_dim by swapping to shuffle up the other dims.
- step = 1 if dest_dim > src_dim else -1
- for x in xrange(src_dim, dest_dim, step):
- dim_list[x], dim_list[x + step] = dim_list[x + step], dim_list[x]
- return dim_list
-
-
-def transposing_reshape(tensor,
- src_dim,
- part_a,
- part_b,
- dest_dim_a,
- dest_dim_b,
- name=None):
- """Splits src_dim and sends one of the pieces to another dim.
-
- Terminology:
- A matrix is often described as 'row-major' or 'column-major', which doesn't
- help if you can't remember which is the row index and which is the column,
- even if you know what 'major' means, so here is a simpler explanation of it:
- When TF stores a tensor of size [d0, d1, d2, d3] indexed by [i0, i1, i2, i3],
- the memory address of an element is calculated using:
- ((i0 * d1 + i1) * d2 + i2) * d3 + i3, so, d0 is the MOST SIGNIFICANT dimension
- and d3 the LEAST SIGNIFICANT, just like in the decimal number 1234, 1 is the
- most significant digit and 4 the least significant. In both cases the most
- significant is multiplied by the largest number to determine its 'value'.
- Furthermore, if we reshape the tensor to [d0'=d0, d1'=d1 x d2, d2'=d3], then
- the MOST SIGNIFICANT part of d1' is d1 and the LEAST SIGNIFICANT part of d1'
- is d2.
-
- Action:
- transposing_reshape splits src_dim into factors [part_a, part_b], and sends
- the most significant part (of size part_a) to be the most significant part of
- dest_dim_a*(Exception: see NOTE 2), and the least significant part (of size
- part_b) to be the most significant part of dest_dim_b.
- This is basically a combination of reshape, rotating transpose, reshape.
- NOTE1: At least one of dest_dim_a and dest_dim_b must equal src_dim, ie one of
- the parts always stays put, so src_dim is never totally destroyed and the
- output number of dimensions is always the same as the input.
- NOTE2: If dest_dim_a == dest_dim_b == src_dim, then parts a and b are simply
- transposed within src_dim to become part_b x part_a, so the most significant
- part becomes the least significant part and vice versa. Thus if you really
- wanted to make one of the parts the least significant side of the destiantion,
- the destination dimension can be internally transposed with a second call to
- transposing_reshape.
- NOTE3: One of part_a and part_b may be -1 to allow src_dim to be of unknown
- size with one known-size factor. Otherwise part_a * part_b must equal the size
- of src_dim.
- NOTE4: The reshape preserves as many known-at-graph-build-time dimension sizes
- as are available.
-
- Example:
- Input dims=[5, 2, 6, 2]
- tensor=[[[[0, 1][2, 3][4, 5][6, 7][8, 9][10, 11]]
- [[12, 13][14, 15][16, 17][18, 19][20, 21][22, 23]]
- [[[24, 25]...
- src_dim=2, part_a=2, part_b=3, dest_dim_a=3, dest_dim_b=2
- output dims =[5, 2, 3, 4]
- output tensor=[[[[0, 1, 6, 7][2, 3, 8, 9][4, 5, 10, 11]]
- [[12, 13, 18, 19][14, 15, 20, 21][16, 17, 22, 23]]]
- [[[24, 26, 28]...
- Example2:
- Input dims=[phrases, words, letters]=[2, 6, x]
- tensor=[[[the][cat][sat][on][the][mat]]
- [[a][stitch][in][time][saves][nine]]]
- We can factorize the 6 words into 3x2 = [[the][cat]][[sat][on]][[the][mat]]
- or 2x3=[[the][cat][sat]][[on][the][mat]] and
- src_dim=1, part_a=3, part_b=2, dest_dim_a=1, dest_dim_b=1
- would yield:
- [[[the][sat][the][cat][on][mat]]
- [[a][in][saves][stitch][time][nine]]], but
- src_dim=1, part_a=2, part_b=3, dest_dim_a=1, dest_dim_b=1
- would yield:
- [[[the][on][cat][the][sat][mat]]
- [[a][time][stitch][saves][in][nine]]], and
- src_dim=1, part_a=2, part_b=3, dest_dim_a=0, dest_dim_b=1
- would yield:
- [[[the][cat][sat]]
- [[a][stitch][in]]
- [[on][the][mat]]
- [[time][saves][nine]]]
- Now remember that the words above represent any least-significant subset of
- the input dimensions.
-
- Args:
- tensor: A tensor to reshape.
- src_dim: The dimension to split.
- part_a: The first factor of the split.
- part_b: The second factor of the split.
- dest_dim_a: The dimension to move part_a of src_dim to.
- dest_dim_b: The dimension to move part_b of src_dim to.
- name: Optional base name for all the ops.
-
- Returns:
- Reshaped tensor.
-
- Raises:
- ValueError: If the args are invalid.
- """
- if dest_dim_a != src_dim and dest_dim_b != src_dim:
- raise ValueError(
- 'At least one of dest_dim_a, dest_dim_b must equal src_dim!')
- if part_a == 0 or part_b == 0:
- raise ValueError('Zero not allowed for part_a or part_b!')
- if part_a < 0 and part_b < 0:
- raise ValueError('At least one of part_a and part_b must be positive!')
- if not name:
- name = 'transposing_reshape'
- prev_shape = tensor_shape(tensor)
- expanded = tf.reshape(
- tensor,
- prev_shape[:src_dim] + [part_a, part_b] + prev_shape[src_dim + 1:],
- name=name + '_reshape_in')
- dest = dest_dim_b
- if dest_dim_a != src_dim:
- # We are just moving part_a to dest_dim_a.
- dest = dest_dim_a
- else:
- # We are moving part_b to dest_dim_b.
- src_dim += 1
- dim_list = rotate_dimensions(len(expanded.get_shape()), src_dim, dest)
- expanded = tf.transpose(expanded, dim_list, name=name + '_rot_transpose')
- # Reshape identity except dest,dest+1, which get merged.
- ex_shape = tensor_shape(expanded)
- combined = ex_shape[dest] * ex_shape[dest + 1]
- return tf.reshape(
- expanded,
- ex_shape[:dest] + [combined] + ex_shape[dest + 2:],
- name=name + '_reshape_out')
-
-
-def tensor_dim(tensor, dim):
- """Returns int dimension if known at a graph build time else a tensor.
-
- If the size of the dim of tensor is known at graph building time, then that
- known value is returned, otherwise (instead of None), a Tensor that will give
- the size of the dimension when the graph is run. The return value will be
- accepted by tf.reshape in multiple (or even all) dimensions, even when the
- sizes are not known at graph building time, unlike -1, which can only be used
- in one dimension. It is a bad idea to use tf.shape all the time, as some ops
- demand a known (at graph build time) size. This function therefore returns
- the best available, most useful dimension size.
- Args:
- tensor: Input tensor.
- dim: Dimension to find the size of.
-
- Returns:
- An integer if shape is known at build time, otherwise a tensor of int32.
- """
- result = tensor.get_shape().as_list()[dim]
- if result is None:
- result = tf.shape(tensor)[dim]
- return result
-
-
-def tensor_shape(tensor):
- """Returns a heterogeneous list of tensor_dim for the tensor.
-
- See tensor_dim for a more detailed explanation.
- Args:
- tensor: Input tensor.
-
- Returns:
- A heterogeneous list of integers and int32 tensors.
- """
- result = []
- for d in xrange(len(tensor.get_shape())):
- result.append(tensor_dim(tensor, d))
- return result
diff --git a/research/street/python/shapes_test.py b/research/street/python/shapes_test.py
deleted file mode 100644
index 87b3c737fb0946dc4cf9596d3a04ddab754ca39a..0000000000000000000000000000000000000000
--- a/research/street/python/shapes_test.py
+++ /dev/null
@@ -1,171 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tests for shapes."""
-
-import numpy as np
-import tensorflow as tf
-import shapes
-
-
-def _rand(*size):
- return np.random.uniform(size=size).astype('f')
-
-
-class ShapesTest(tf.test.TestCase):
- """Tests just the shapes from a call to transposing_reshape."""
-
- def __init__(self, other):
- super(ShapesTest, self).__init__(other)
- self.batch_size = 4
- self.im_height = 24
- self.im_width = 36
- self.depth = 20
-
- def testReshapeTile(self):
- """Tests that a tiled input can be reshaped to the batch dimension."""
- fake = tf.placeholder(
- tf.float32, shape=(None, None, None, self.depth), name='inputs')
- real = _rand(self.batch_size, self.im_height, self.im_width, self.depth)
- with self.test_session() as sess:
- outputs = shapes.transposing_reshape(
- fake, src_dim=2, part_a=3, part_b=-1, dest_dim_a=0, dest_dim_b=2)
- res_image = sess.run([outputs], feed_dict={fake: real})
- self.assertEqual(
- tuple(res_image[0].shape),
- (self.batch_size * 3, self.im_height, self.im_width / 3, self.depth))
-
- def testReshapeDepth(self):
- """Tests that depth can be reshaped to the x dimension."""
- fake = tf.placeholder(
- tf.float32, shape=(None, None, None, self.depth), name='inputs')
- real = _rand(self.batch_size, self.im_height, self.im_width, self.depth)
- with self.test_session() as sess:
- outputs = shapes.transposing_reshape(
- fake, src_dim=3, part_a=4, part_b=-1, dest_dim_a=2, dest_dim_b=3)
- res_image = sess.run([outputs], feed_dict={fake: real})
- self.assertEqual(
- tuple(res_image[0].shape),
- (self.batch_size, self.im_height, self.im_width * 4, self.depth / 4))
-
-
-class DataTest(tf.test.TestCase):
- """Tests that the data is moved correctly in a call to transposing_reshape.
-
- """
-
- def testTransposingReshape_2_2_3_2_1(self):
- """Case: dest_a == src, dest_b < src: Split with Least sig part going left.
- """
- with self.test_session() as sess:
- fake = tf.placeholder(
- tf.float32, shape=(None, None, None, 2), name='inputs')
- outputs = shapes.transposing_reshape(
- fake, src_dim=2, part_a=2, part_b=3, dest_dim_a=2, dest_dim_b=1)
- # Make real inputs. The tensor looks like this:
- # tensor=[[[[0, 1][2, 3][4, 5][6, 7][8, 9][10, 11]]
- # [[12, 13][14, 15][16, 17][18, 19][20, 21][22, 23]]
- # [[[24, 25]...
- real = np.arange(120).reshape((5, 2, 6, 2))
- np_array = sess.run([outputs], feed_dict={fake: real})[0]
- self.assertEqual(tuple(np_array.shape), (5, 6, 2, 2))
- self.assertAllEqual(np_array[0, :, :, :],
- [[[0, 1], [6, 7]], [[12, 13], [18, 19]],
- [[2, 3], [8, 9]], [[14, 15], [20, 21]],
- [[4, 5], [10, 11]], [[16, 17], [22, 23]]])
-
- def testTransposingReshape_2_2_3_2_3(self):
- """Case: dest_a == src, dest_b > src: Split with Least sig part going right.
- """
- with self.test_session() as sess:
- fake = tf.placeholder(
- tf.float32, shape=(None, None, None, 2), name='inputs')
- outputs = shapes.transposing_reshape(
- fake, src_dim=2, part_a=2, part_b=3, dest_dim_a=2, dest_dim_b=3)
- # Make real inputs. The tensor looks like this:
- # tensor=[[[[0, 1][2, 3][4, 5][6, 7][8, 9][10, 11]]
- # [[12, 13][14, 15][16, 17][18, 19][20, 21][22, 23]]
- # [[[24, 25]...
- real = np.arange(120).reshape((5, 2, 6, 2))
- np_array = sess.run([outputs], feed_dict={fake: real})[0]
- self.assertEqual(tuple(np_array.shape), (5, 2, 2, 6))
- self.assertAllEqual(
- np_array[0, :, :, :],
- [[[0, 1, 2, 3, 4, 5], [6, 7, 8, 9, 10, 11]],
- [[12, 13, 14, 15, 16, 17], [18, 19, 20, 21, 22, 23]]])
-
- def testTransposingReshape_2_2_3_2_2(self):
- """Case: dest_a == src, dest_b == src. Transpose within dimension 2.
- """
- with self.test_session() as sess:
- fake = tf.placeholder(
- tf.float32, shape=(None, None, None, 2), name='inputs')
- outputs = shapes.transposing_reshape(
- fake, src_dim=2, part_a=2, part_b=3, dest_dim_a=2, dest_dim_b=2)
- # Make real inputs. The tensor looks like this:
- # tensor=[[[[0, 1][2, 3][4, 5][6, 7][8, 9][10, 11]]
- # [[12, 13][14, 15][16, 17][18, 19][20, 21][22, 23]]
- # [[[24, 25]...
- real = np.arange(120).reshape((5, 2, 6, 2))
- np_array = sess.run([outputs], feed_dict={fake: real})[0]
- self.assertEqual(tuple(np_array.shape), (5, 2, 6, 2))
- self.assertAllEqual(
- np_array[0, :, :, :],
- [[[0, 1], [6, 7], [2, 3], [8, 9], [4, 5], [10, 11]],
- [[12, 13], [18, 19], [14, 15], [20, 21], [16, 17], [22, 23]]])
-
- def testTransposingReshape_2_2_3_1_2(self):
- """Case: dest_a < src, dest_b == src. Split with Most sig part going left.
- """
- with self.test_session() as sess:
- fake = tf.placeholder(
- tf.float32, shape=(None, None, None, 2), name='inputs')
- outputs = shapes.transposing_reshape(
- fake, src_dim=2, part_a=2, part_b=3, dest_dim_a=1, dest_dim_b=2)
- # Make real inputs. The tensor looks like this:
- # tensor=[[[[0, 1][2, 3][4, 5][6, 7][8, 9][10, 11]]
- # [[12, 13][14, 15][16, 17][18, 19][20, 21][22, 23]]
- # [[[24, 25]...
- real = np.arange(120).reshape((5, 2, 6, 2))
- np_array = sess.run([outputs], feed_dict={fake: real})[0]
- self.assertEqual(tuple(np_array.shape), (5, 4, 3, 2))
- self.assertAllEqual(np_array[0, :, :, :],
- [[[0, 1], [2, 3], [4, 5]],
- [[12, 13], [14, 15], [16, 17]],
- [[6, 7], [8, 9], [10, 11]],
- [[18, 19], [20, 21], [22, 23]]])
-
- def testTransposingReshape_2_2_3_3_2(self):
- """Case: dest_a < src, dest_b == src. Split with Most sig part going right.
- """
- with self.test_session() as sess:
- fake = tf.placeholder(
- tf.float32, shape=(None, None, None, 2), name='inputs')
- outputs = shapes.transposing_reshape(
- fake, src_dim=2, part_a=2, part_b=3, dest_dim_a=3, dest_dim_b=2)
- # Make real inputs. The tensor looks like this:
- # tensor=[[[[0, 1][2, 3][4, 5][6, 7][8, 9][10, 11]]
- # [[12, 13][14, 15][16, 17][18, 19][20, 21][22, 23]]
- # [[[24, 25]...
- real = np.arange(120).reshape((5, 2, 6, 2))
- np_array = sess.run([outputs], feed_dict={fake: real})[0]
- self.assertEqual(tuple(np_array.shape), (5, 2, 3, 4))
- self.assertAllEqual(
- np_array[0, :, :, :],
- [[[0, 1, 6, 7], [2, 3, 8, 9], [4, 5, 10, 11]],
- [[12, 13, 18, 19], [14, 15, 20, 21], [16, 17, 22, 23]]])
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/street/python/vgsl_eval.py b/research/street/python/vgsl_eval.py
deleted file mode 100644
index 7db00d6f067b24f9222a1d490f817116c5121726..0000000000000000000000000000000000000000
--- a/research/street/python/vgsl_eval.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Model eval separate from training."""
-from tensorflow import app
-from tensorflow.python.platform import flags
-
-import vgsl_model
-
-flags.DEFINE_string('eval_dir', '/tmp/mdir/eval',
- 'Directory where to write event logs.')
-flags.DEFINE_string('graph_def_file', None,
- 'Output eval graph definition file.')
-flags.DEFINE_string('train_dir', '/tmp/mdir',
- 'Directory where to find training checkpoints.')
-flags.DEFINE_string('model_str',
- '1,150,600,3[S2(4x150)0,2 Ct5,5,16 Mp2,2 Ct5,5,64 Mp3,3'
- '([Lrys64 Lbx128][Lbys64 Lbx128][Lfys64 Lbx128])S3(3x0)2,3'
- 'Lfx128 Lrx128 S0(1x4)0,3 Do Lfx256]O1c134',
- 'Network description.')
-flags.DEFINE_integer('num_steps', 1000, 'Number of steps to run evaluation.')
-flags.DEFINE_integer('eval_interval_secs', 60,
- 'Time interval between eval runs.')
-flags.DEFINE_string('eval_data', None, 'Evaluation data filepattern')
-flags.DEFINE_string('decoder', None, 'Charset decoder')
-
-FLAGS = flags.FLAGS
-
-
-def main(argv):
- del argv
- vgsl_model.Eval(FLAGS.train_dir, FLAGS.eval_dir, FLAGS.model_str,
- FLAGS.eval_data, FLAGS.decoder, FLAGS.num_steps,
- FLAGS.graph_def_file, FLAGS.eval_interval_secs)
-
-
-if __name__ == '__main__':
- app.run()
diff --git a/research/street/python/vgsl_input.py b/research/street/python/vgsl_input.py
deleted file mode 100644
index e4495c680aa7c757d87e6cfe2fefc1e62bc7ae6f..0000000000000000000000000000000000000000
--- a/research/street/python/vgsl_input.py
+++ /dev/null
@@ -1,150 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""String network description language to define network layouts."""
-import collections
-import tensorflow as tf
-from tensorflow.python.ops import parsing_ops
-
-# Named tuple for the standard tf image tensor Shape.
-# batch_size: Number of images to batch-up for training.
-# height: Fixed height of image or None for variable.
-# width: Fixed width of image or None for variable.
-# depth: Desired depth in bytes per pixel of input images.
-ImageShape = collections.namedtuple('ImageTensorDims',
- ['batch_size', 'height', 'width', 'depth'])
-
-
-def ImageInput(input_pattern, num_threads, shape, using_ctc, reader=None):
- """Creates an input image tensor from the input_pattern filenames.
-
- TODO(rays) Expand for 2-d labels, 0-d labels, and logistic targets.
- Args:
- input_pattern: Filenames of the dataset(s) to read.
- num_threads: Number of preprocessing threads.
- shape: ImageShape with the desired shape of the input.
- using_ctc: Take the unpadded_class labels instead of padded.
- reader: Function that returns an actual reader to read Examples from
- input files. If None, uses tf.TFRecordReader().
- Returns:
- images: Float Tensor containing the input image scaled to [-1.28, 1.27].
- heights: Tensor int64 containing the heights of the images.
- widths: Tensor int64 containing the widths of the images.
- labels: Serialized SparseTensor containing the int64 labels.
- sparse_labels: Serialized SparseTensor containing the int64 labels.
- truths: Tensor string of the utf8 truth texts.
- Raises:
- ValueError: if the optimizer type is unrecognized.
- """
- data_files = tf.gfile.Glob(input_pattern)
- assert data_files, 'no files found for dataset ' + input_pattern
- queue_capacity = shape.batch_size * num_threads * 2
- filename_queue = tf.train.string_input_producer(
- data_files, capacity=queue_capacity)
-
- # Create a subgraph with its own reader (but sharing the
- # filename_queue) for each preprocessing thread.
- images_and_label_lists = []
- for _ in range(num_threads):
- image, height, width, labels, text = _ReadExamples(filename_queue, shape,
- using_ctc, reader)
- images_and_label_lists.append([image, height, width, labels, text])
- # Create a queue that produces the examples in batches.
- images, heights, widths, labels, truths = tf.train.batch_join(
- images_and_label_lists,
- batch_size=shape.batch_size,
- capacity=16 * shape.batch_size,
- dynamic_pad=True)
- # Deserialize back to sparse, because the batcher doesn't do sparse.
- labels = tf.deserialize_many_sparse(labels, tf.int64)
- sparse_labels = tf.cast(labels, tf.int32)
- labels = tf.sparse_tensor_to_dense(labels)
- labels = tf.reshape(labels, [shape.batch_size, -1], name='Labels')
- # Crush the other shapes to just the batch dimension.
- heights = tf.reshape(heights, [-1], name='Heights')
- widths = tf.reshape(widths, [-1], name='Widths')
- truths = tf.reshape(truths, [-1], name='Truths')
- # Give the images a nice name as well.
- images = tf.identity(images, name='Images')
-
- tf.summary.image('Images', images)
- return images, heights, widths, labels, sparse_labels, truths
-
-
-def _ReadExamples(filename_queue, shape, using_ctc, reader=None):
- """Builds network input tensor ops for TF Example.
-
- Args:
- filename_queue: Queue of filenames, from tf.train.string_input_producer
- shape: ImageShape with the desired shape of the input.
- using_ctc: Take the unpadded_class labels instead of padded.
- reader: Function that returns an actual reader to read Examples from
- input files. If None, uses tf.TFRecordReader().
- Returns:
- image: Float Tensor containing the input image scaled to [-1.28, 1.27].
- height: Tensor int64 containing the height of the image.
- width: Tensor int64 containing the width of the image.
- labels: Serialized SparseTensor containing the int64 labels.
- text: Tensor string of the utf8 truth text.
- """
- if reader:
- reader = reader()
- else:
- reader = tf.TFRecordReader()
- _, example_serialized = reader.read(filename_queue)
- example_serialized = tf.reshape(example_serialized, shape=[])
- features = tf.parse_single_example(
- example_serialized,
- {'image/encoded': parsing_ops.FixedLenFeature(
- [1], dtype=tf.string, default_value=''),
- 'image/text': parsing_ops.FixedLenFeature(
- [1], dtype=tf.string, default_value=''),
- 'image/class': parsing_ops.VarLenFeature(dtype=tf.int64),
- 'image/unpadded_class': parsing_ops.VarLenFeature(dtype=tf.int64),
- 'image/height': parsing_ops.FixedLenFeature(
- [1], dtype=tf.int64, default_value=1),
- 'image/width': parsing_ops.FixedLenFeature(
- [1], dtype=tf.int64, default_value=1)})
- if using_ctc:
- labels = features['image/unpadded_class']
- else:
- labels = features['image/class']
- labels = tf.serialize_sparse(labels)
- image = tf.reshape(features['image/encoded'], shape=[], name='encoded')
- image = _ImageProcessing(image, shape)
- height = tf.reshape(features['image/height'], [-1])
- width = tf.reshape(features['image/width'], [-1])
- text = tf.reshape(features['image/text'], shape=[])
-
- return image, height, width, labels, text
-
-
-def _ImageProcessing(image_buffer, shape):
- """Convert a PNG string into an input tensor.
-
- We allow for fixed and variable sizes.
- Does fixed conversion to floats in the range [-1.28, 1.27].
- Args:
- image_buffer: Tensor containing a PNG encoded image.
- shape: ImageShape with the desired shape of the input.
- Returns:
- image: Decoded, normalized image in the range [-1.28, 1.27].
- """
- image = tf.image.decode_png(image_buffer, channels=shape.depth)
- image.set_shape([shape.height, shape.width, shape.depth])
- image = tf.cast(image, tf.float32)
- image = tf.subtract(image, 128.0)
- image = tf.multiply(image, 1 / 100.0)
- return image
diff --git a/research/street/python/vgsl_model.py b/research/street/python/vgsl_model.py
deleted file mode 100644
index 7533cd8d5bb781102e9e9b58c4a3259b79404fd2..0000000000000000000000000000000000000000
--- a/research/street/python/vgsl_model.py
+++ /dev/null
@@ -1,601 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""String network description language to define network layouts."""
-from __future__ import print_function
-
-import re
-import time
-
-import decoder
-import errorcounter as ec
-import shapes
-import tensorflow as tf
-import vgsl_input
-import vgslspecs
-import tensorflow.contrib.slim as slim
-from tensorflow.core.framework import summary_pb2
-from tensorflow.python.platform import tf_logging as logging
-
-
-# Parameters for rate decay.
-# We divide the learning_rate_halflife by DECAY_STEPS_FACTOR and use DECAY_RATE
-# as the decay factor for the learning rate, ie we use the DECAY_STEPS_FACTORth
-# root of 2 as the decay rate every halflife/DECAY_STEPS_FACTOR to achieve the
-# desired halflife.
-DECAY_STEPS_FACTOR = 16
-DECAY_RATE = pow(0.5, 1.0 / DECAY_STEPS_FACTOR)
-
-
-def Train(train_dir,
- model_str,
- train_data,
- max_steps,
- master='',
- task=0,
- ps_tasks=0,
- initial_learning_rate=0.001,
- final_learning_rate=0.001,
- learning_rate_halflife=160000,
- optimizer_type='Adam',
- num_preprocess_threads=1,
- reader=None):
- """Testable trainer with no dependence on FLAGS.
-
- Args:
- train_dir: Directory to write checkpoints.
- model_str: Network specification string.
- train_data: Training data file pattern.
- max_steps: Number of training steps to run.
- master: Name of the TensorFlow master to use.
- task: Task id of this replica running the training. (0 will be master).
- ps_tasks: Number of tasks in ps job, or 0 if no ps job.
- initial_learning_rate: Learing rate at start of training.
- final_learning_rate: Asymptotic minimum learning rate.
- learning_rate_halflife: Number of steps over which to halve the difference
- between initial and final learning rate.
- optimizer_type: One of 'GradientDescent', 'AdaGrad', 'Momentum', 'Adam'.
- num_preprocess_threads: Number of input threads.
- reader: Function that returns an actual reader to read Examples from input
- files. If None, uses tf.TFRecordReader().
- """
- if master.startswith('local'):
- device = tf.ReplicaDeviceSetter(ps_tasks)
- else:
- device = '/cpu:0'
- with tf.Graph().as_default():
- with tf.device(device):
- model = InitNetwork(train_data, model_str, 'train', initial_learning_rate,
- final_learning_rate, learning_rate_halflife,
- optimizer_type, num_preprocess_threads, reader)
-
- # Create a Supervisor. It will take care of initialization, summaries,
- # checkpoints, and recovery.
- #
- # When multiple replicas of this program are running, the first one,
- # identified by --task=0 is the 'chief' supervisor. It is the only one
- # that takes case of initialization, etc.
- sv = tf.train.Supervisor(
- logdir=train_dir,
- is_chief=(task == 0),
- saver=model.saver,
- save_summaries_secs=10,
- save_model_secs=30,
- recovery_wait_secs=5)
-
- step = 0
- while step < max_steps:
- try:
- # Get an initialized, and possibly recovered session. Launch the
- # services: Checkpointing, Summaries, step counting.
- with sv.managed_session(master) as sess:
- while step < max_steps:
- _, step = model.TrainAStep(sess)
- if sv.coord.should_stop():
- break
- except tf.errors.AbortedError as e:
- logging.error('Received error:%s', e)
- continue
-
-
-def Eval(train_dir,
- eval_dir,
- model_str,
- eval_data,
- decoder_file,
- num_steps,
- graph_def_file=None,
- eval_interval_secs=0,
- reader=None):
- """Restores a model from a checkpoint and evaluates it.
-
- Args:
- train_dir: Directory to find checkpoints.
- eval_dir: Directory to write summary events.
- model_str: Network specification string.
- eval_data: Evaluation data file pattern.
- decoder_file: File to read to decode the labels.
- num_steps: Number of eval steps to run.
- graph_def_file: File to write graph definition to for freezing.
- eval_interval_secs: How often to run evaluations, or once if 0.
- reader: Function that returns an actual reader to read Examples from input
- files. If None, uses tf.TFRecordReader().
- Returns:
- (char error rate, word recall error rate, sequence error rate) as percent.
- Raises:
- ValueError: If unimplemented feature is used.
- """
- decode = None
- if decoder_file:
- decode = decoder.Decoder(decoder_file)
-
- # Run eval.
- rates = ec.ErrorRates(
- label_error=None,
- word_recall_error=None,
- word_precision_error=None,
- sequence_error=None)
- with tf.Graph().as_default():
- model = InitNetwork(eval_data, model_str, 'eval', reader=reader)
- sw = tf.summary.FileWriter(eval_dir)
-
- while True:
- sess = tf.Session('')
- if graph_def_file is not None:
- # Write the eval version of the graph to a file for freezing.
- if not tf.gfile.Exists(graph_def_file):
- with tf.gfile.FastGFile(graph_def_file, 'w') as f:
- f.write(
- sess.graph.as_graph_def(add_shapes=True).SerializeToString())
- ckpt = tf.train.get_checkpoint_state(train_dir)
- if ckpt and ckpt.model_checkpoint_path:
- step = model.Restore(ckpt.model_checkpoint_path, sess)
- if decode:
- rates = decode.SoftmaxEval(sess, model, num_steps)
- _AddRateToSummary('Label error rate', rates.label_error, step, sw)
- _AddRateToSummary('Word recall error rate', rates.word_recall_error,
- step, sw)
- _AddRateToSummary('Word precision error rate',
- rates.word_precision_error, step, sw)
- _AddRateToSummary('Sequence error rate', rates.sequence_error, step,
- sw)
- sw.flush()
- print('Error rates=', rates)
- else:
- raise ValueError('Non-softmax decoder evaluation not implemented!')
- if eval_interval_secs:
- time.sleep(eval_interval_secs)
- else:
- break
- return rates
-
-
-def InitNetwork(input_pattern,
- model_spec,
- mode='eval',
- initial_learning_rate=0.00005,
- final_learning_rate=0.00005,
- halflife=1600000,
- optimizer_type='Adam',
- num_preprocess_threads=1,
- reader=None):
- """Constructs a python tensor flow model defined by model_spec.
-
- Args:
- input_pattern: File pattern of the data in tfrecords of Example.
- model_spec: Concatenation of input spec, model spec and output spec.
- See Build below for input/output spec. For model spec, see vgslspecs.py
- mode: One of 'train', 'eval'
- initial_learning_rate: Initial learning rate for the network.
- final_learning_rate: Final learning rate for the network.
- halflife: Number of steps over which to halve the difference between
- initial and final learning rate for the network.
- optimizer_type: One of 'GradientDescent', 'AdaGrad', 'Momentum', 'Adam'.
- num_preprocess_threads: Number of threads to use for image processing.
- reader: Function that returns an actual reader to read Examples from input
- files. If None, uses tf.TFRecordReader().
- Eval tasks need only specify input_pattern and model_spec.
-
- Returns:
- A VGSLImageModel class.
-
- Raises:
- ValueError: if the model spec syntax is incorrect.
- """
- model = VGSLImageModel(mode, model_spec, initial_learning_rate,
- final_learning_rate, halflife)
- left_bracket = model_spec.find('[')
- right_bracket = model_spec.rfind(']')
- if left_bracket < 0 or right_bracket < 0:
- raise ValueError('Failed to find [] in model spec! ', model_spec)
- input_spec = model_spec[:left_bracket]
- layer_spec = model_spec[left_bracket:right_bracket + 1]
- output_spec = model_spec[right_bracket + 1:]
- model.Build(input_pattern, input_spec, layer_spec, output_spec,
- optimizer_type, num_preprocess_threads, reader)
- return model
-
-
-class VGSLImageModel(object):
- """Class that builds a tensor flow model for training or evaluation.
- """
-
- def __init__(self, mode, model_spec, initial_learning_rate,
- final_learning_rate, halflife):
- """Constructs a VGSLImageModel.
-
- Args:
- mode: One of "train", "eval"
- model_spec: Full model specification string, for reference only.
- initial_learning_rate: Initial learning rate for the network.
- final_learning_rate: Final learning rate for the network.
- halflife: Number of steps over which to halve the difference between
- initial and final learning rate for the network.
- """
- # The string that was used to build this model.
- self.model_spec = model_spec
- # The layers between input and output.
- self.layers = None
- # The train/eval mode.
- self.mode = mode
- # The initial learning rate.
- self.initial_learning_rate = initial_learning_rate
- self.final_learning_rate = final_learning_rate
- self.decay_steps = halflife / DECAY_STEPS_FACTOR
- self.decay_rate = DECAY_RATE
- # Tensor for the labels.
- self.labels = None
- self.sparse_labels = None
- # Debug data containing the truth text.
- self.truths = None
- # Tensor for loss
- self.loss = None
- # Train operation
- self.train_op = None
- # Tensor for the global step counter
- self.global_step = None
- # Tensor for the output predictions (usually softmax)
- self.output = None
- # True if we are using CTC training mode.
- self.using_ctc = False
- # Saver object to load or restore the variables.
- self.saver = None
-
- def Build(self, input_pattern, input_spec, model_spec, output_spec,
- optimizer_type, num_preprocess_threads, reader):
- """Builds the model from the separate input/layers/output spec strings.
-
- Args:
- input_pattern: File pattern of the data in tfrecords of TF Example format.
- input_spec: Specification of the input layer:
- batchsize,height,width,depth (4 comma-separated integers)
- Training will run with batches of batchsize images, but runtime can
- use any batch size.
- height and/or width can be 0 or -1, indicating variable size,
- otherwise all images must be the given size.
- depth must be 1 or 3 to indicate greyscale or color.
- NOTE 1-d image input, treating the y image dimension as depth, can
- be achieved using S1(1x0)1,3 as the first op in the model_spec, but
- the y-size of the input must then be fixed.
- model_spec: Model definition. See vgslspecs.py
- output_spec: Output layer definition:
- O(2|1|0)(l|s|c)n output layer with n classes.
- 2 (heatmap) Output is a 2-d vector map of the input (possibly at
- different scale).
- 1 (sequence) Output is a 1-d sequence of vector values.
- 0 (value) Output is a 0-d single vector value.
- l uses a logistic non-linearity on the output, allowing multiple
- hot elements in any output vector value.
- s uses a softmax non-linearity, with one-hot output in each value.
- c uses a softmax with CTC. Can only be used with s (sequence).
- NOTE Only O1s and O1c are currently supported.
- optimizer_type: One of 'GradientDescent', 'AdaGrad', 'Momentum', 'Adam'.
- num_preprocess_threads: Number of threads to use for image processing.
- reader: Function that returns an actual reader to read Examples from input
- files. If None, uses tf.TFRecordReader().
- """
- self.global_step = tf.Variable(0, name='global_step', trainable=False)
- shape = _ParseInputSpec(input_spec)
- out_dims, out_func, num_classes = _ParseOutputSpec(output_spec)
- self.using_ctc = out_func == 'c'
- images, heights, widths, labels, sparse, _ = vgsl_input.ImageInput(
- input_pattern, num_preprocess_threads, shape, self.using_ctc, reader)
- self.labels = labels
- self.sparse_labels = sparse
- self.layers = vgslspecs.VGSLSpecs(widths, heights, self.mode == 'train')
- last_layer = self.layers.Build(images, model_spec)
- self._AddOutputs(last_layer, out_dims, out_func, num_classes)
- if self.mode == 'train':
- self._AddOptimizer(optimizer_type)
-
- # For saving the model across training and evaluation
- self.saver = tf.train.Saver()
-
- def TrainAStep(self, sess):
- """Runs a training step in the session.
-
- Args:
- sess: Session in which to train the model.
- Returns:
- loss, global_step.
- """
- _, loss, step = sess.run([self.train_op, self.loss, self.global_step])
- return loss, step
-
- def Restore(self, checkpoint_path, sess):
- """Restores the model from the given checkpoint path into the session.
-
- Args:
- checkpoint_path: File pathname of the checkpoint.
- sess: Session in which to restore the model.
- Returns:
- global_step of the model.
- """
- self.saver.restore(sess, checkpoint_path)
- return tf.train.global_step(sess, self.global_step)
-
- def RunAStep(self, sess):
- """Runs a step for eval in the session.
-
- Args:
- sess: Session in which to run the model.
- Returns:
- output tensor result, labels tensor result.
- """
- return sess.run([self.output, self.labels])
-
- def _AddOutputs(self, prev_layer, out_dims, out_func, num_classes):
- """Adds the output layer and loss function.
-
- Args:
- prev_layer: Output of last layer of main network.
- out_dims: Number of output dimensions, 0, 1 or 2.
- out_func: Output non-linearity. 's' or 'c'=softmax, 'l'=logistic.
- num_classes: Number of outputs/size of last output dimension.
- """
- height_in = shapes.tensor_dim(prev_layer, dim=1)
- logits, outputs = self._AddOutputLayer(prev_layer, out_dims, out_func,
- num_classes)
- if self.mode == 'train':
- # Setup loss for training.
- self.loss = self._AddLossFunction(logits, height_in, out_dims, out_func)
- tf.summary.scalar('loss', self.loss)
- elif out_dims == 0:
- # Be sure the labels match the output, even in eval mode.
- self.labels = tf.slice(self.labels, [0, 0], [-1, 1])
- self.labels = tf.reshape(self.labels, [-1])
-
- logging.info('Final output=%s', outputs)
- logging.info('Labels tensor=%s', self.labels)
- self.output = outputs
-
- def _AddOutputLayer(self, prev_layer, out_dims, out_func, num_classes):
- """Add the fully-connected logits and SoftMax/Logistic output Layer.
-
- Args:
- prev_layer: Output of last layer of main network.
- out_dims: Number of output dimensions, 0, 1 or 2.
- out_func: Output non-linearity. 's' or 'c'=softmax, 'l'=logistic.
- num_classes: Number of outputs/size of last output dimension.
-
- Returns:
- logits: Pre-softmax/logistic fully-connected output shaped to out_dims.
- outputs: Post-softmax/logistic shaped to out_dims.
-
- Raises:
- ValueError: if syntax is incorrect.
- """
- # Reduce dimensionality appropriate to the output dimensions.
- batch_in = shapes.tensor_dim(prev_layer, dim=0)
- height_in = shapes.tensor_dim(prev_layer, dim=1)
- width_in = shapes.tensor_dim(prev_layer, dim=2)
- depth_in = shapes.tensor_dim(prev_layer, dim=3)
- if out_dims:
- # Combine any remaining height and width with batch and unpack after.
- shaped = tf.reshape(prev_layer, [-1, depth_in])
- else:
- # Everything except batch goes to depth, and therefore has to be known.
- shaped = tf.reshape(prev_layer, [-1, height_in * width_in * depth_in])
- logits = slim.fully_connected(shaped, num_classes, activation_fn=None)
- if out_func == 'l':
- raise ValueError('Logistic not yet supported!')
- else:
- output = tf.nn.softmax(logits)
- # Reshape to the dessired output.
- if out_dims == 2:
- output_shape = [batch_in, height_in, width_in, num_classes]
- elif out_dims == 1:
- output_shape = [batch_in, height_in * width_in, num_classes]
- else:
- output_shape = [batch_in, num_classes]
- output = tf.reshape(output, output_shape, name='Output')
- logits = tf.reshape(logits, output_shape)
- return logits, output
-
- def _AddLossFunction(self, logits, height_in, out_dims, out_func):
- """Add the appropriate loss function.
-
- Args:
- logits: Pre-softmax/logistic fully-connected output shaped to out_dims.
- height_in: Height of logits before going into the softmax layer.
- out_dims: Number of output dimensions, 0, 1 or 2.
- out_func: Output non-linearity. 's' or 'c'=softmax, 'l'=logistic.
-
- Returns:
- loss: That which is to be minimized.
-
- Raises:
- ValueError: if logistic is used.
- """
- if out_func == 'c':
- # Transpose batch to the middle.
- ctc_input = tf.transpose(logits, [1, 0, 2])
- # Compute the widths of each batch element from the input widths.
- widths = self.layers.GetLengths(dim=2, factor=height_in)
- cross_entropy = tf.nn.ctc_loss(ctc_input, self.sparse_labels, widths)
- elif out_func == 's':
- if out_dims == 2:
- self.labels = _PadLabels3d(logits, self.labels)
- elif out_dims == 1:
- self.labels = _PadLabels2d(
- shapes.tensor_dim(
- logits, dim=1), self.labels)
- else:
- self.labels = tf.slice(self.labels, [0, 0], [-1, 1])
- self.labels = tf.reshape(self.labels, [-1])
- cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
- logits=logits, labels=self.labels, name='xent')
- else:
- # TODO(rays) Labels need an extra dimension for logistic, so different
- # padding functions are needed, as well as a different loss function.
- raise ValueError('Logistic not yet supported!')
- return tf.reduce_sum(cross_entropy)
-
- def _AddOptimizer(self, optimizer_type):
- """Adds an optimizer with learning rate decay to minimize self.loss.
-
- Args:
- optimizer_type: One of 'GradientDescent', 'AdaGrad', 'Momentum', 'Adam'.
- Raises:
- ValueError: if the optimizer type is unrecognized.
- """
- learn_rate_delta = self.initial_learning_rate - self.final_learning_rate
- learn_rate_dec = tf.add(
- tf.train.exponential_decay(learn_rate_delta, self.global_step,
- self.decay_steps, self.decay_rate),
- self.final_learning_rate)
- if optimizer_type == 'GradientDescent':
- opt = tf.train.GradientDescentOptimizer(learn_rate_dec)
- elif optimizer_type == 'AdaGrad':
- opt = tf.train.AdagradOptimizer(learn_rate_dec)
- elif optimizer_type == 'Momentum':
- opt = tf.train.MomentumOptimizer(learn_rate_dec, momentum=0.9)
- elif optimizer_type == 'Adam':
- opt = tf.train.AdamOptimizer(learning_rate=learn_rate_dec)
- else:
- raise ValueError('Invalid optimizer type: ' + optimizer_type)
- tf.summary.scalar('learn_rate', learn_rate_dec)
-
- self.train_op = opt.minimize(
- self.loss, global_step=self.global_step, name='train')
-
-
-def _PadLabels3d(logits, labels):
- """Pads or slices 3-d labels to match logits.
-
- Covers the case of 2-d softmax output, when labels is [batch, height, width]
- and logits is [batch, height, width, onehot]
- Args:
- logits: 4-d Pre-softmax fully-connected output.
- labels: 3-d, but not necessarily matching in size.
-
- Returns:
- labels: Resized by padding or clipping to match logits.
- """
- logits_shape = shapes.tensor_shape(logits)
- labels_shape = shapes.tensor_shape(labels)
- labels = tf.reshape(labels, [-1, labels_shape[2]])
- labels = _PadLabels2d(logits_shape[2], labels)
- labels = tf.reshape(labels, [labels_shape[0], -1])
- labels = _PadLabels2d(logits_shape[1] * logits_shape[2], labels)
- return tf.reshape(labels, [labels_shape[0], logits_shape[1], logits_shape[2]])
-
-
-def _PadLabels2d(logits_size, labels):
- """Pads or slices the 2nd dimension of 2-d labels to match logits_size.
-
- Covers the case of 1-d softmax output, when labels is [batch, seq] and
- logits is [batch, seq, onehot]
- Args:
- logits_size: Tensor returned from tf.shape giving the target size.
- labels: 2-d, but not necessarily matching in size.
-
- Returns:
- labels: Resized by padding or clipping the last dimension to logits_size.
- """
- pad = logits_size - tf.shape(labels)[1]
-
- def _PadFn():
- return tf.pad(labels, [[0, 0], [0, pad]])
-
- def _SliceFn():
- return tf.slice(labels, [0, 0], [-1, logits_size])
-
- return tf.cond(tf.greater(pad, 0), _PadFn, _SliceFn)
-
-
-def _ParseInputSpec(input_spec):
- """Parses input_spec and returns the numbers obtained therefrom.
-
- Args:
- input_spec: Specification of the input layer. See Build.
-
- Returns:
- shape: ImageShape with the desired shape of the input.
-
- Raises:
- ValueError: if syntax is incorrect.
- """
- pattern = re.compile(R'(\d+),(\d+),(\d+),(\d+)')
- m = pattern.match(input_spec)
- if m is None:
- raise ValueError('Failed to parse input spec:' + input_spec)
- batch_size = int(m.group(1))
- y_size = int(m.group(2)) if int(m.group(2)) > 0 else None
- x_size = int(m.group(3)) if int(m.group(3)) > 0 else None
- depth = int(m.group(4))
- if depth not in [1, 3]:
- raise ValueError('Depth must be 1 or 3, had:', depth)
- return vgsl_input.ImageShape(batch_size, y_size, x_size, depth)
-
-
-def _ParseOutputSpec(output_spec):
- """Parses the output spec.
-
- Args:
- output_spec: Output layer definition. See Build.
-
- Returns:
- out_dims: 2|1|0 for 2-d, 1-d, 0-d.
- out_func: l|s|c for logistic, softmax, softmax+CTC
- num_classes: Number of classes in output.
-
- Raises:
- ValueError: if syntax is incorrect.
- """
- pattern = re.compile(R'(O)(0|1|2)(l|s|c)(\d+)')
- m = pattern.match(output_spec)
- if m is None:
- raise ValueError('Failed to parse output spec:' + output_spec)
- out_dims = int(m.group(2))
- out_func = m.group(3)
- if out_func == 'c' and out_dims != 1:
- raise ValueError('CTC can only be used with a 1-D sequence!')
- num_classes = int(m.group(4))
- return out_dims, out_func, num_classes
-
-
-def _AddRateToSummary(tag, rate, step, sw):
- """Adds the given rate to the summary with the given tag.
-
- Args:
- tag: Name for this value.
- rate: Value to add to the summary. Perhaps an error rate.
- step: Global step of the graph for the x-coordinate of the summary.
- sw: Summary writer to which to write the rate value.
- """
- sw.add_summary(
- summary_pb2.Summary(value=[summary_pb2.Summary.Value(
- tag=tag, simple_value=rate)]), step)
diff --git a/research/street/python/vgsl_model_test.py b/research/street/python/vgsl_model_test.py
deleted file mode 100644
index fd23961592a77136539f8110f82f1ada64a5eacf..0000000000000000000000000000000000000000
--- a/research/street/python/vgsl_model_test.py
+++ /dev/null
@@ -1,248 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tests for vgsl_model."""
-import os
-
-import numpy as np
-import tensorflow as tf
-import vgsl_input
-import vgsl_model
-
-
-def _testdata(filename):
- return os.path.join('../testdata/', filename)
-
-
-def _rand(*size):
- return np.random.uniform(size=size).astype('f')
-
-
-class VgslModelTest(tf.test.TestCase):
-
- def testParseInputSpec(self):
- """The parser must return the numbers in the correct order.
- """
- shape = vgsl_model._ParseInputSpec(input_spec='32,42,256,3')
- self.assertEqual(
- shape,
- vgsl_input.ImageShape(
- batch_size=32, height=42, width=256, depth=3))
- # Nones must be inserted for zero sizes.
- shape = vgsl_model._ParseInputSpec(input_spec='1,0,0,3')
- self.assertEqual(
- shape,
- vgsl_input.ImageShape(
- batch_size=1, height=None, width=None, depth=3))
-
- def testParseOutputSpec(self):
- """The parser must return the correct args in the correct order.
- """
- out_dims, out_func, num_classes = vgsl_model._ParseOutputSpec(
- output_spec='O1c142')
- self.assertEqual(out_dims, 1)
- self.assertEqual(out_func, 'c')
- self.assertEqual(num_classes, 142)
- out_dims, out_func, num_classes = vgsl_model._ParseOutputSpec(
- output_spec='O2s99')
- self.assertEqual(out_dims, 2)
- self.assertEqual(out_func, 's')
- self.assertEqual(num_classes, 99)
- out_dims, out_func, num_classes = vgsl_model._ParseOutputSpec(
- output_spec='O0l12')
- self.assertEqual(out_dims, 0)
- self.assertEqual(out_func, 'l')
- self.assertEqual(num_classes, 12)
-
- def testPadLabels2d(self):
- """Must pad timesteps in labels to match logits.
- """
- with self.test_session() as sess:
- # Make placeholders for logits and labels.
- ph_logits = tf.placeholder(tf.float32, shape=(None, None, 42))
- ph_labels = tf.placeholder(tf.int64, shape=(None, None))
- padded_labels = vgsl_model._PadLabels2d(tf.shape(ph_logits)[1], ph_labels)
- # Make actual inputs.
- real_logits = _rand(4, 97, 42)
- real_labels = _rand(4, 85)
- np_array = sess.run([padded_labels],
- feed_dict={ph_logits: real_logits,
- ph_labels: real_labels})[0]
- self.assertEqual(tuple(np_array.shape), (4, 97))
- real_labels = _rand(4, 97)
- np_array = sess.run([padded_labels],
- feed_dict={ph_logits: real_logits,
- ph_labels: real_labels})[0]
- self.assertEqual(tuple(np_array.shape), (4, 97))
- real_labels = _rand(4, 100)
- np_array = sess.run([padded_labels],
- feed_dict={ph_logits: real_logits,
- ph_labels: real_labels})[0]
- self.assertEqual(tuple(np_array.shape), (4, 97))
-
- def testPadLabels3d(self):
- """Must pad height and width in labels to match logits.
-
- The tricky thing with 3-d is that the rows and columns need to remain
- intact, so we'll test it with small known data.
- """
- with self.test_session() as sess:
- # Make placeholders for logits and labels.
- ph_logits = tf.placeholder(tf.float32, shape=(None, None, None, 42))
- ph_labels = tf.placeholder(tf.int64, shape=(None, None, None))
- padded_labels = vgsl_model._PadLabels3d(ph_logits, ph_labels)
- # Make actual inputs.
- real_logits = _rand(1, 3, 4, 42)
- # Test all 9 combinations of height x width in [small, ok, big]
- real_labels = np.arange(6).reshape((1, 2, 3)) # Height small, width small
- np_array = sess.run([padded_labels],
- feed_dict={ph_logits: real_logits,
- ph_labels: real_labels})[0]
- self.assertEqual(tuple(np_array.shape), (1, 3, 4))
- self.assertAllEqual(np_array[0, :, :],
- [[0, 1, 2, 0], [3, 4, 5, 0], [0, 0, 0, 0]])
- real_labels = np.arange(8).reshape((1, 2, 4)) # Height small, width ok
- np_array = sess.run([padded_labels],
- feed_dict={ph_logits: real_logits,
- ph_labels: real_labels})[0]
- self.assertEqual(tuple(np_array.shape), (1, 3, 4))
- self.assertAllEqual(np_array[0, :, :],
- [[0, 1, 2, 3], [4, 5, 6, 7], [0, 0, 0, 0]])
- real_labels = np.arange(10).reshape((1, 2, 5)) # Height small, width big
- np_array = sess.run([padded_labels],
- feed_dict={ph_logits: real_logits,
- ph_labels: real_labels})[0]
- self.assertEqual(tuple(np_array.shape), (1, 3, 4))
- self.assertAllEqual(np_array[0, :, :],
- [[0, 1, 2, 3], [5, 6, 7, 8], [0, 0, 0, 0]])
- real_labels = np.arange(9).reshape((1, 3, 3)) # Height ok, width small
- np_array = sess.run([padded_labels],
- feed_dict={ph_logits: real_logits,
- ph_labels: real_labels})[0]
- self.assertEqual(tuple(np_array.shape), (1, 3, 4))
- self.assertAllEqual(np_array[0, :, :],
- [[0, 1, 2, 0], [3, 4, 5, 0], [6, 7, 8, 0]])
- real_labels = np.arange(12).reshape((1, 3, 4)) # Height ok, width ok
- np_array = sess.run([padded_labels],
- feed_dict={ph_logits: real_logits,
- ph_labels: real_labels})[0]
- self.assertEqual(tuple(np_array.shape), (1, 3, 4))
- self.assertAllEqual(np_array[0, :, :],
- [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]])
- real_labels = np.arange(15).reshape((1, 3, 5)) # Height ok, width big
- np_array = sess.run([padded_labels],
- feed_dict={ph_logits: real_logits,
- ph_labels: real_labels})[0]
- self.assertEqual(tuple(np_array.shape), (1, 3, 4))
- self.assertAllEqual(np_array[0, :, :],
- [[0, 1, 2, 3], [5, 6, 7, 8], [10, 11, 12, 13]])
- real_labels = np.arange(12).reshape((1, 4, 3)) # Height big, width small
- np_array = sess.run([padded_labels],
- feed_dict={ph_logits: real_logits,
- ph_labels: real_labels})[0]
- self.assertEqual(tuple(np_array.shape), (1, 3, 4))
- self.assertAllEqual(np_array[0, :, :],
- [[0, 1, 2, 0], [3, 4, 5, 0], [6, 7, 8, 0]])
- real_labels = np.arange(16).reshape((1, 4, 4)) # Height big, width ok
- np_array = sess.run([padded_labels],
- feed_dict={ph_logits: real_logits,
- ph_labels: real_labels})[0]
- self.assertEqual(tuple(np_array.shape), (1, 3, 4))
- self.assertAllEqual(np_array[0, :, :],
- [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]])
- real_labels = np.arange(20).reshape((1, 4, 5)) # Height big, width big
- np_array = sess.run([padded_labels],
- feed_dict={ph_logits: real_logits,
- ph_labels: real_labels})[0]
- self.assertEqual(tuple(np_array.shape), (1, 3, 4))
- self.assertAllEqual(np_array[0, :, :],
- [[0, 1, 2, 3], [5, 6, 7, 8], [10, 11, 12, 13]])
-
- def testEndToEndSizes0d(self):
- """Tests that the output sizes match when training/running real 0d data.
-
- Uses mnist with dual summarizing LSTMs to reduce to a single value.
- """
- filename = _testdata('mnist-tiny')
- with self.test_session() as sess:
- model = vgsl_model.InitNetwork(
- filename,
- model_spec='4,0,0,1[Cr5,5,16 Mp3,3 Lfys16 Lfxs16]O0s12',
- mode='train')
- tf.global_variables_initializer().run(session=sess)
- coord = tf.train.Coordinator()
- tf.train.start_queue_runners(sess=sess, coord=coord)
- _, step = model.TrainAStep(sess)
- self.assertEqual(step, 1)
- output, labels = model.RunAStep(sess)
- self.assertEqual(len(output.shape), 2)
- self.assertEqual(len(labels.shape), 1)
- self.assertEqual(output.shape[0], labels.shape[0])
- self.assertEqual(output.shape[1], 12)
-
- # TODO(rays) Support logistic and test with Imagenet (as 0d, multi-object.)
-
- def testEndToEndSizes1dCTC(self):
- """Tests that the output sizes match when training with CTC.
-
- Basic bidi LSTM on top of convolution and summarizing LSTM with CTC.
- """
- filename = _testdata('arial-32-tiny')
- with self.test_session() as sess:
- model = vgsl_model.InitNetwork(
- filename,
- model_spec='2,0,0,1[Cr5,5,16 Mp3,3 Lfys16 Lbx100]O1c105',
- mode='train')
- tf.global_variables_initializer().run(session=sess)
- coord = tf.train.Coordinator()
- tf.train.start_queue_runners(sess=sess, coord=coord)
- _, step = model.TrainAStep(sess)
- self.assertEqual(step, 1)
- output, labels = model.RunAStep(sess)
- self.assertEqual(len(output.shape), 3)
- self.assertEqual(len(labels.shape), 2)
- self.assertEqual(output.shape[0], labels.shape[0])
- # This is ctc - the only cast-iron guarantee is labels <= output.
- self.assertLessEqual(labels.shape[1], output.shape[1])
- self.assertEqual(output.shape[2], 105)
-
- def testEndToEndSizes1dFixed(self):
- """Tests that the output sizes match when training/running 1 data.
-
- Convolution, summarizing LSTM with fwd rev fwd to allow no CTC.
- """
- filename = _testdata('numbers-16-tiny')
- with self.test_session() as sess:
- model = vgsl_model.InitNetwork(
- filename,
- model_spec='8,0,0,1[Cr5,5,16 Mp3,3 Lfys16 Lfx64 Lrx64 Lfx64]O1s12',
- mode='train')
- tf.global_variables_initializer().run(session=sess)
- coord = tf.train.Coordinator()
- tf.train.start_queue_runners(sess=sess, coord=coord)
- _, step = model.TrainAStep(sess)
- self.assertEqual(step, 1)
- output, labels = model.RunAStep(sess)
- self.assertEqual(len(output.shape), 3)
- self.assertEqual(len(labels.shape), 2)
- self.assertEqual(output.shape[0], labels.shape[0])
- # Not CTC, output lengths match.
- self.assertEqual(output.shape[1], labels.shape[1])
- self.assertEqual(output.shape[2], 12)
-
- # TODO(rays) Get a 2-d dataset and support 2d (heat map) outputs.
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/street/python/vgsl_train.py b/research/street/python/vgsl_train.py
deleted file mode 100644
index 8dd83089730a7af93513204d5bf1630e68d11bf7..0000000000000000000000000000000000000000
--- a/research/street/python/vgsl_train.py
+++ /dev/null
@@ -1,55 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Model trainer for single or multi-replica training."""
-from tensorflow import app
-from tensorflow.python.platform import flags
-
-import vgsl_model
-
-flags.DEFINE_string('master', '', 'Name of the TensorFlow master to use.')
-flags.DEFINE_string('train_dir', '/tmp/mdir',
- 'Directory where to write event logs.')
-flags.DEFINE_string('model_str',
- '1,150,600,3[S2(4x150)0,2 Ct5,5,16 Mp2,2 Ct5,5,64 Mp3,3'
- '([Lrys64 Lbx128][Lbys64 Lbx128][Lfys64 Lbx128])S3(3x0)2,3'
- 'Lfx128 Lrx128 S0(1x4)0,3 Do Lfx256]O1c134',
- 'Network description.')
-flags.DEFINE_integer('max_steps', 10000, 'Number of steps to train for.')
-flags.DEFINE_integer('task', 0, 'Task id of the replica running the training.')
-flags.DEFINE_integer('ps_tasks', 0, 'Number of tasks in the ps job.'
- 'If 0 no ps job is used.')
-flags.DEFINE_string('train_data', None, 'Training data filepattern')
-flags.DEFINE_float('initial_learning_rate', 0.00002, 'Initial learning rate')
-flags.DEFINE_float('final_learning_rate', 0.00002, 'Final learning rate')
-flags.DEFINE_integer('learning_rate_halflife', 1600000,
- 'Halflife of learning rate')
-flags.DEFINE_string('optimizer_type', 'Adam',
- 'Optimizer from:GradientDescent, AdaGrad, Momentum, Adam')
-flags.DEFINE_integer('num_preprocess_threads', 4, 'Number of input threads')
-
-FLAGS = flags.FLAGS
-
-
-def main(argv):
- del argv
- vgsl_model.Train(FLAGS.train_dir, FLAGS.model_str, FLAGS.train_data,
- FLAGS.max_steps, FLAGS.master, FLAGS.task, FLAGS.ps_tasks,
- FLAGS.initial_learning_rate, FLAGS.final_learning_rate,
- FLAGS.learning_rate_halflife, FLAGS.optimizer_type,
- FLAGS.num_preprocess_threads)
-
-
-if __name__ == '__main__':
- app.run()
diff --git a/research/street/python/vgslspecs.py b/research/street/python/vgslspecs.py
deleted file mode 100644
index 36b5c668a3e5c6b11cf51f899d2a2dd358cca8b2..0000000000000000000000000000000000000000
--- a/research/street/python/vgslspecs.py
+++ /dev/null
@@ -1,534 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""String network description language mapping to TF-Slim calls where possible.
-
-See vglspecs.md for detailed description.
-"""
-
-import re
-from string import maketrans
-
-import nn_ops
-import shapes
-from six.moves import xrange
-import tensorflow as tf
-import tensorflow.contrib.slim as slim
-
-
-# Class that builds a set of ops to manipulate variable-sized images.
-class VGSLSpecs(object):
- """Layers that can be built from a string definition."""
-
- def __init__(self, widths, heights, is_training):
- """Constructs a VGSLSpecs.
-
- Args:
- widths: Tensor of size batch_size of the widths of the inputs.
- heights: Tensor of size batch_size of the heights of the inputs.
- is_training: True if the graph should be build for training.
- """
- # The string that was used to build this model.
- self.model_str = None
- # True if we are training
- self.is_training = is_training
- # Tensor for the size of the images, of size batch_size.
- self.widths = widths
- self.heights = heights
- # Overall reduction factors of this model so far for each dimension.
- # TODO(rays) consider building a graph from widths and heights instead of
- # computing a scale factor.
- self.reduction_factors = [1.0, 1.0, 1.0, 1.0]
- # List of Op parsers.
- # TODO(rays) add more Op types as needed.
- self.valid_ops = [self.AddSeries, self.AddParallel, self.AddConvLayer,
- self.AddMaxPool, self.AddDropout, self.AddReShape,
- self.AddFCLayer, self.AddLSTMLayer]
- # Translation table to convert unacceptable characters that may occur
- # in op strings that cannot be used as names.
- self.transtab = maketrans('(,)', '___')
-
- def Build(self, prev_layer, model_str):
- """Builds a network with input prev_layer from a VGSLSpecs description.
-
- Args:
- prev_layer: The input tensor.
- model_str: Model definition similar to Tesseract as follows:
- ============ FUNCTIONAL OPS ============
- C(s|t|r|l|m)[{name}],, Convolves using a y,x window, with no
- shrinkage, SAME infill, d outputs, with s|t|r|l|m non-linear layer.
- (s|t|r|l|m) specifies the type of non-linearity:
- s = sigmoid
- t = tanh
- r = relu
- l = linear (i.e., None)
- m = softmax
- F(s|t|r|l|m)[{name}] Fully-connected with s|t|r|l|m non-linearity and
- d outputs. Reduces height, width to 1. Input height and width must be
- constant.
- L(f|r|b)(x|y)[s][{name}] LSTM cell with n outputs.
- f runs the LSTM forward only.
- r runs the LSTM reversed only.
- b runs the LSTM bidirectionally.
- x runs the LSTM in the x-dimension (on data with or without the
- y-dimension).
- y runs the LSTM in the y-dimension (data must have a y dimension).
- s (optional) summarizes the output in the requested dimension,
- outputting only the final step, collapsing the dimension to a
- single element.
- Examples:
- Lfx128 runs a forward-only LSTM in the x-dimension with 128
- outputs, treating any y dimension independently.
- Lfys64 runs a forward-only LSTM in the y-dimension with 64 outputs
- and collapses the y-dimension to 1 element.
- NOTE that Lbxsn is implemented as (LfxsnLrxsn) since the summaries
- need to be taken from opposite ends of the output
- Do[{name}] Insert a dropout layer.
- ============ PLUMBING OPS ============
- [...] Execute ... networks in series (layers).
- (...) Execute ... networks in parallel, with their output concatenated
- in depth.
- S[{name}](x), Splits one dimension, moves one part to
- another dimension.
- Splits input dimension d into a x b, sending the high part (a) to the
- high side of dimension e, and the low part (b) to the high side of
- dimension f. Exception: if d=e=f, then then dimension d is internally
- transposed to bxa.
- Either a or b can be zero, meaning whatever is left after taking out
- the other, allowing dimensions to be of variable size.
- Eg. S3(3x50)2,3 will split the 150-element depth into 3x50, with the 3
- going to the most significant part of the width, and the 50 part
- staying in depth.
- This will rearrange a 3x50 output parallel operation to spread the 3
- output sets over width.
- Mp[{name}], Maxpool the input, reducing the (y,x) rectangle to a
- single vector value.
-
- Returns:
- Output tensor
- """
- self.model_str = model_str
- final_layer, _ = self.BuildFromString(prev_layer, 0)
- return final_layer
-
- def GetLengths(self, dim=2, factor=1):
- """Returns the lengths of the batch of elements in the given dimension.
-
- WARNING: The returned sizes may not exactly match TF's calculation.
- Args:
- dim: dimension to get the sizes of, in [1,2]. batch, depth not allowed.
- factor: A scalar value to multiply by.
-
- Returns:
- The original heights/widths scaled by the current scaling of the model and
- the given factor.
-
- Raises:
- ValueError: If the args are invalid.
- """
- if dim == 1:
- lengths = self.heights
- elif dim == 2:
- lengths = self.widths
- else:
- raise ValueError('Invalid dimension given to GetLengths')
- lengths = tf.cast(lengths, tf.float32)
- if self.reduction_factors[dim] is not None:
- lengths = tf.div(lengths, self.reduction_factors[dim])
- else:
- lengths = tf.ones_like(lengths)
- if factor != 1:
- lengths = tf.multiply(lengths, tf.cast(factor, tf.float32))
- return tf.cast(lengths, tf.int32)
-
- def BuildFromString(self, prev_layer, index):
- """Adds the layers defined by model_str[index:] to the model.
-
- Args:
- prev_layer: Input tensor.
- index: Position in model_str to start parsing
-
- Returns:
- Output tensor, next model_str index.
-
- Raises:
- ValueError: If the model string is unrecognized.
- """
- index = self._SkipWhitespace(index)
- for op in self.valid_ops:
- output_layer, next_index = op(prev_layer, index)
- if output_layer is not None:
- return output_layer, next_index
- if output_layer is not None:
- return output_layer, next_index
- raise ValueError('Unrecognized model string:' + self.model_str[index:])
-
- def AddSeries(self, prev_layer, index):
- """Builds a sequence of layers for a VGSLSpecs model.
-
- Args:
- prev_layer: Input tensor.
- index: Position in model_str to start parsing
-
- Returns:
- Output tensor of the series, end index in model_str.
-
- Raises:
- ValueError: If [] are unbalanced.
- """
- if self.model_str[index] != '[':
- return None, None
- index += 1
- while index < len(self.model_str) and self.model_str[index] != ']':
- prev_layer, index = self.BuildFromString(prev_layer, index)
- if index == len(self.model_str):
- raise ValueError('Missing ] at end of series!' + self.model_str)
- return prev_layer, index + 1
-
- def AddParallel(self, prev_layer, index):
- """tf.concats outputs of layers that run on the same inputs.
-
- Args:
- prev_layer: Input tensor.
- index: Position in model_str to start parsing
-
- Returns:
- Output tensor of the parallel, end index in model_str.
-
- Raises:
- ValueError: If () are unbalanced or the elements don't match.
- """
- if self.model_str[index] != '(':
- return None, None
- index += 1
- layers = []
- num_dims = 0
- # Each parallel must output the same, including any reduction factor, in
- # all dimensions except depth.
- # We have to save the starting factors, so they don't get reduced by all
- # the elements of the parallel, only once.
- original_factors = self.reduction_factors
- final_factors = None
- while index < len(self.model_str) and self.model_str[index] != ')':
- self.reduction_factors = original_factors
- layer, index = self.BuildFromString(prev_layer, index)
- if num_dims == 0:
- num_dims = len(layer.get_shape())
- elif num_dims != len(layer.get_shape()):
- raise ValueError('All elements of parallel must return same num dims')
- layers.append(layer)
- if final_factors:
- if final_factors != self.reduction_factors:
- raise ValueError('All elements of parallel must scale the same')
- else:
- final_factors = self.reduction_factors
- if index == len(self.model_str):
- raise ValueError('Missing ) at end of parallel!' + self.model_str)
- return tf.concat(axis=num_dims - 1, values=layers), index + 1
-
- def AddConvLayer(self, prev_layer, index):
- """Add a single standard convolutional layer.
-
- Args:
- prev_layer: Input tensor.
- index: Position in model_str to start parsing
-
- Returns:
- Output tensor, end index in model_str.
- """
- pattern = re.compile(R'(C)(s|t|r|l|m)({\w+})?(\d+),(\d+),(\d+)')
- m = pattern.match(self.model_str, index)
- if m is None:
- return None, None
- name = self._GetLayerName(m.group(0), index, m.group(3))
- width = int(m.group(4))
- height = int(m.group(5))
- depth = int(m.group(6))
- fn = self._NonLinearity(m.group(2))
- return slim.conv2d(
- prev_layer, depth, [height, width], activation_fn=fn,
- scope=name), m.end()
-
- def AddMaxPool(self, prev_layer, index):
- """Add a maxpool layer.
-
- Args:
- prev_layer: Input tensor.
- index: Position in model_str to start parsing
-
- Returns:
- Output tensor, end index in model_str.
- """
- pattern = re.compile(R'(Mp)({\w+})?(\d+),(\d+)(?:,(\d+),(\d+))?')
- m = pattern.match(self.model_str, index)
- if m is None:
- return None, None
- name = self._GetLayerName(m.group(0), index, m.group(2))
- height = int(m.group(3))
- width = int(m.group(4))
- y_stride = height if m.group(5) is None else m.group(5)
- x_stride = width if m.group(6) is None else m.group(6)
- self.reduction_factors[1] *= y_stride
- self.reduction_factors[2] *= x_stride
- return slim.max_pool2d(
- prev_layer, [height, width], [y_stride, x_stride],
- padding='SAME',
- scope=name), m.end()
-
- def AddDropout(self, prev_layer, index):
- """Adds a dropout layer.
-
- Args:
- prev_layer: Input tensor.
- index: Position in model_str to start parsing
-
- Returns:
- Output tensor, end index in model_str.
- """
- pattern = re.compile(R'(Do)({\w+})?')
- m = pattern.match(self.model_str, index)
- if m is None:
- return None, None
- name = self._GetLayerName(m.group(0), index, m.group(2))
- layer = slim.dropout(
- prev_layer, 0.5, is_training=self.is_training, scope=name)
- return layer, m.end()
-
- def AddReShape(self, prev_layer, index):
- """Reshapes the input tensor by moving each (x_scale,y_scale) rectangle to.
-
- the depth dimension. NOTE that the TF convention is that inputs are
- [batch, y, x, depth].
-
- Args:
- prev_layer: Input tensor.
- index: Position in model_str to start parsing
-
- Returns:
- Output tensor, end index in model_str.
- """
- pattern = re.compile(R'(S)(?:{(\w)})?(\d+)\((\d+)x(\d+)\)(\d+),(\d+)')
- m = pattern.match(self.model_str, index)
- if m is None:
- return None, None
- name = self._GetLayerName(m.group(0), index, m.group(2))
- src_dim = int(m.group(3))
- part_a = int(m.group(4))
- part_b = int(m.group(5))
- dest_dim_a = int(m.group(6))
- dest_dim_b = int(m.group(7))
- if part_a == 0:
- part_a = -1
- if part_b == 0:
- part_b = -1
- prev_shape = tf.shape(prev_layer)
- layer = shapes.transposing_reshape(
- prev_layer, src_dim, part_a, part_b, dest_dim_a, dest_dim_b, name=name)
- # Compute scale factors.
- result_shape = tf.shape(layer)
- for i in xrange(len(self.reduction_factors)):
- if self.reduction_factors[i] is not None:
- factor1 = tf.cast(self.reduction_factors[i], tf.float32)
- factor2 = tf.cast(prev_shape[i], tf.float32)
- divisor = tf.cast(result_shape[i], tf.float32)
- self.reduction_factors[i] = tf.div(tf.multiply(factor1, factor2), divisor)
- return layer, m.end()
-
- def AddFCLayer(self, prev_layer, index):
- """Parse expression and add Fully Connected Layer.
-
- Args:
- prev_layer: Input tensor.
- index: Position in model_str to start parsing
-
- Returns:
- Output tensor, end index in model_str.
- """
- pattern = re.compile(R'(F)(s|t|r|l|m)({\w+})?(\d+)')
- m = pattern.match(self.model_str, index)
- if m is None:
- return None, None
- fn = self._NonLinearity(m.group(2))
- name = self._GetLayerName(m.group(0), index, m.group(3))
- depth = int(m.group(4))
- input_depth = shapes.tensor_dim(prev_layer, 1) * shapes.tensor_dim(
- prev_layer, 2) * shapes.tensor_dim(prev_layer, 3)
- # The slim fully connected is actually a 1x1 conv, so we have to crush the
- # dimensions on input.
- # Everything except batch goes to depth, and therefore has to be known.
- shaped = tf.reshape(
- prev_layer, [-1, input_depth], name=name + '_reshape_in')
- output = slim.fully_connected(shaped, depth, activation_fn=fn, scope=name)
- # Width and height are collapsed to 1.
- self.reduction_factors[1] = None
- self.reduction_factors[2] = None
- return tf.reshape(
- output, [shapes.tensor_dim(prev_layer, 0), 1, 1, depth],
- name=name + '_reshape_out'), m.end()
-
- def AddLSTMLayer(self, prev_layer, index):
- """Parse expression and add LSTM Layer.
-
- Args:
- prev_layer: Input tensor.
- index: Position in model_str to start parsing
-
- Returns:
- Output tensor, end index in model_str.
- """
- pattern = re.compile(R'(L)(f|r|b)(x|y)(s)?({\w+})?(\d+)')
- m = pattern.match(self.model_str, index)
- if m is None:
- return None, None
- direction = m.group(2)
- dim = m.group(3)
- summarize = m.group(4) == 's'
- name = self._GetLayerName(m.group(0), index, m.group(5))
- depth = int(m.group(6))
- if direction == 'b' and summarize:
- fwd = self._LSTMLayer(prev_layer, 'forward', dim, True, depth,
- name + '_forward')
- back = self._LSTMLayer(prev_layer, 'backward', dim, True, depth,
- name + '_reverse')
- return tf.concat(axis=3, values=[fwd, back], name=name + '_concat'), m.end()
- if direction == 'f':
- direction = 'forward'
- elif direction == 'r':
- direction = 'backward'
- else:
- direction = 'bidirectional'
- outputs = self._LSTMLayer(prev_layer, direction, dim, summarize, depth,
- name)
- if summarize:
- # The x or y dimension is getting collapsed.
- if dim == 'x':
- self.reduction_factors[2] = None
- else:
- self.reduction_factors[1] = None
- return outputs, m.end()
-
- def _LSTMLayer(self, prev_layer, direction, dim, summarize, depth, name):
- """Adds an LSTM layer with the given pre-parsed attributes.
-
- Always maps 4-D to 4-D regardless of summarize.
- Args:
- prev_layer: Input tensor.
- direction: 'forward' 'backward' or 'bidirectional'
- dim: 'x' or 'y', dimension to consider as time.
- summarize: True if we are to return only the last timestep.
- depth: Output depth.
- name: Some string naming the op.
-
- Returns:
- Output tensor.
- """
- # If the target dimension is y, we need to transpose.
- if dim == 'x':
- lengths = self.GetLengths(2, 1)
- inputs = prev_layer
- else:
- lengths = self.GetLengths(1, 1)
- inputs = tf.transpose(prev_layer, [0, 2, 1, 3], name=name + '_ytrans_in')
- input_batch = shapes.tensor_dim(inputs, 0)
- num_slices = shapes.tensor_dim(inputs, 1)
- num_steps = shapes.tensor_dim(inputs, 2)
- input_depth = shapes.tensor_dim(inputs, 3)
- # Reshape away the other dimension.
- inputs = tf.reshape(
- inputs, [-1, num_steps, input_depth], name=name + '_reshape_in')
- # We need to replicate the lengths by the size of the other dimension, and
- # any changes that have been made to the batch dimension.
- tile_factor = tf.to_float(input_batch *
- num_slices) / tf.to_float(tf.shape(lengths)[0])
- lengths = tf.tile(lengths, [tf.cast(tile_factor, tf.int32)])
- lengths = tf.cast(lengths, tf.int64)
- outputs = nn_ops.rnn_helper(
- inputs,
- lengths,
- cell_type='lstm',
- num_nodes=depth,
- direction=direction,
- name=name,
- stddev=0.1)
- # Output depth is doubled if bi-directional.
- if direction == 'bidirectional':
- output_depth = depth * 2
- else:
- output_depth = depth
- # Restore the other dimension.
- if summarize:
- outputs = tf.slice(
- outputs, [0, num_steps - 1, 0], [-1, 1, -1], name=name + '_sum_slice')
- outputs = tf.reshape(
- outputs, [input_batch, num_slices, 1, output_depth],
- name=name + '_reshape_out')
- else:
- outputs = tf.reshape(
- outputs, [input_batch, num_slices, num_steps, output_depth],
- name=name + '_reshape_out')
- if dim == 'y':
- outputs = tf.transpose(outputs, [0, 2, 1, 3], name=name + '_ytrans_out')
- return outputs
-
- def _NonLinearity(self, code):
- """Returns the non-linearity function pointer for the given string code.
-
- For forwards compatibility, allows the full names for stand-alone
- non-linearities, as well as the single-letter names used in ops like C,F.
- Args:
- code: String code representing a non-linearity function.
- Returns:
- non-linearity function represented by the code.
- """
- if code in ['s', 'Sig']:
- return tf.sigmoid
- elif code in ['t', 'Tanh']:
- return tf.tanh
- elif code in ['r', 'Relu']:
- return tf.nn.relu
- elif code in ['m', 'Smax']:
- return tf.nn.softmax
- return None
-
- def _GetLayerName(self, op_str, index, name_str):
- """Generates a name for the op, using a user-supplied name if possible.
-
- Args:
- op_str: String representing the parsed op.
- index: Position in model_str of the start of the op.
- name_str: User-supplied {name} with {} that need removing or None.
-
- Returns:
- Selected name.
- """
- if name_str:
- return name_str[1:-1]
- else:
- return op_str.translate(self.transtab) + '_' + str(index)
-
- def _SkipWhitespace(self, index):
- """Skips any leading whitespace in the model description.
-
- Args:
- index: Position in model_str to start parsing
-
- Returns:
- end index in model_str of whitespace.
- """
- pattern = re.compile(R'([ \t\n]+)')
- m = pattern.match(self.model_str, index)
- if m is None:
- return index
- return m.end()
diff --git a/research/street/python/vgslspecs_test.py b/research/street/python/vgslspecs_test.py
deleted file mode 100644
index 69ea28bf75c13700f063b1dc4303af6c0982889c..0000000000000000000000000000000000000000
--- a/research/street/python/vgslspecs_test.py
+++ /dev/null
@@ -1,122 +0,0 @@
-# Copyright 2016 The TensorFlow Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-"""Tests for vgslspecs."""
-
-import numpy as np
-import tensorflow as tf
-import vgslspecs
-
-
-def _rand(*size):
- return np.random.uniform(size=size).astype('f')
-
-
-class VgslspecsTest(tf.test.TestCase):
-
- def __init__(self, other):
- super(VgslspecsTest, self).__init__(other)
- self.max_width = 36
- self.max_height = 24
- self.batch_size = 4
-
- def SetupInputs(self):
- # Make placeholders for standard inputs.
- # Everything is variable in the input, except the depth.
- self.ph_image = tf.placeholder(
- tf.float32, shape=(None, None, None, 3), name='inputs')
- self.ph_widths = tf.placeholder(tf.int64, shape=(None,), name='w')
- self.ph_heights = tf.placeholder(tf.int64, shape=(None,), name='h')
- # Make actual inputs.
- self.in_image = _rand(self.batch_size, self.max_height, self.max_width, 3)
- self.in_widths = [24, 12, self.max_width, 30]
- self.in_heights = [self.max_height, 18, 12, 6]
-
- def ExpectScaledSize(self, spec, target_shape, factor=1):
- """Tests that the output of the graph of the given spec has target_shape."""
- with tf.Graph().as_default():
- with self.test_session() as sess:
- self.SetupInputs()
- # Only the placeholders are given at construction time.
- vgsl = vgslspecs.VGSLSpecs(self.ph_widths, self.ph_heights, True)
- outputs = vgsl.Build(self.ph_image, spec)
- # Compute the expected output widths from the given scale factor.
- target_widths = tf.div(self.in_widths, factor).eval()
- target_heights = tf.div(self.in_heights, factor).eval()
- # Run with the 'real' data.
- tf.global_variables_initializer().run()
- res_image, res_widths, res_heights = sess.run(
- [outputs, vgsl.GetLengths(2), vgsl.GetLengths(1)],
- feed_dict={self.ph_image: self.in_image,
- self.ph_widths: self.in_widths,
- self.ph_heights: self.in_heights})
- self.assertEqual(tuple(res_image.shape), target_shape)
- if target_shape[1] > 1:
- self.assertEqual(tuple(res_heights), tuple(target_heights))
- if target_shape[2] > 1:
- self.assertEqual(tuple(res_widths), tuple(target_widths))
-
- def testSameSizeConv(self):
- """Test all types of Conv. There is no scaling."""
- self.ExpectScaledSize(
- '[Cs{MyConv}5,5,16 Ct3,3,12 Cr4,4,24 Cl5,5,64]',
- (self.batch_size, self.max_height, self.max_width, 64))
-
- def testSameSizeLSTM(self):
- """Test all non-reducing LSTMs. Output depth is doubled with BiDi."""
- self.ExpectScaledSize('[Lfx16 Lrx8 Do Lbx24 Lfy12 Do{MyDo} Lry7 Lby32]',
- (self.batch_size, self.max_height, self.max_width,
- 64))
-
- def testSameSizeParallel(self):
- """Parallel affects depth, but not scale."""
- self.ExpectScaledSize('[Cs5,5,16 (Lfx{MyLSTM}32 Lrx32 Lbx16)]',
- (self.batch_size, self.max_height, self.max_width,
- 96))
-
- def testScalingOps(self):
- """Test a heterogeneous series with scaling."""
- self.ExpectScaledSize('[Cs5,5,16 Mp{MyPool}2,2 Ct3,3,32 Mp3,3 Lfx32 Lry64]',
- (self.batch_size, self.max_height / 6,
- self.max_width / 6, 64), 6)
-
- def testXReduction(self):
- """Test a heterogeneous series with reduction of x-dimension."""
- self.ExpectScaledSize('[Cr5,5,16 Mp2,2 Ct3,3,32 Mp3,3 Lfxs32 Lry64]',
- (self.batch_size, self.max_height / 6, 1, 64), 6)
-
- def testYReduction(self):
- """Test a heterogeneous series with reduction of y-dimension."""
- self.ExpectScaledSize('[Cl5,5,16 Mp2,2 Ct3,3,32 Mp3,3 Lfys32 Lfx64]',
- (self.batch_size, 1, self.max_width / 6, 64), 6)
-
- def testXYReduction(self):
- """Test a heterogeneous series with reduction to 0-d."""
- self.ExpectScaledSize(
- '[Cr5,5,16 Lfys32 Lfxs64 Fr{MyFC}16 Ft20 Fl12 Fs32 Fm40]',
- (self.batch_size, 1, 1, 40))
-
- def testReshapeTile(self):
- """Tests that a tiled input can be reshaped to the batch dimension."""
- self.ExpectScaledSize('[S2(3x0)0,2 Cr5,5,16 Lfys16]',
- (self.batch_size * 3, 1, self.max_width / 3, 16), 3)
-
- def testReshapeDepth(self):
- """Tests that depth can be reshaped to the x dimension."""
- self.ExpectScaledSize('[Cl5,5,16 Mp3,3 (Lrys32 Lbys16 Lfys32) S3(3x0)2,3]',
- (self.batch_size, 1, self.max_width, 32))
-
-
-if __name__ == '__main__':
- tf.test.main()
diff --git a/research/street/testdata/arial-32-tiny b/research/street/testdata/arial-32-tiny
deleted file mode 100644
index b551e2bde5fbfe10648af75bb90275d50fa6f201..0000000000000000000000000000000000000000
Binary files a/research/street/testdata/arial-32-tiny and /dev/null differ
diff --git a/research/street/testdata/arial.charset_size=105.txt b/research/street/testdata/arial.charset_size=105.txt
deleted file mode 100644
index feec47e0aabc60fca462570ea20ac525be761797..0000000000000000000000000000000000000000
--- a/research/street/testdata/arial.charset_size=105.txt
+++ /dev/null
@@ -1,112 +0,0 @@
-0
-104
-1 G
-2 r
-3 a
-4 s
-5 l
-6 n
-7 d
-8 .
-9 B
-10 C
-11 O
-12 W
-13 Y
-14 ,
-15 (
-16 u
-17 z
-18 i
-19 e
-20 )
-21 1
-22 9
-23 2
-24 -
-25 6
-26 o
-27 L
-28 P
-29 '
-30 t
-31 m
-32 K
-33 c
-34 k
-35 V
-36 S
-37 D
-38 J
-39 h
-40 M
-41 x
-42 E
-43 q
-44 ;
-45 A
-46 y
-47 f
-48 5
-49 7
-50 b
-51 4
-52 0
-53 3
-54 N
-55 I
-56 T
-57 /
-58 p
-59 w
-60 g
-61 H
-62 “
-63 F
-62 ”
-62 "
-29 ’
-64 R
-24 —
-65 8
-66 v
-67 ?
-68 é
-69 %
-70 :
-71 j
-72 \
-73 {
-74 }
-75 |
-76 U
-77 $
-78 °
-79 *
-80 !
-81 ]
-82 Q
-29 ‘
-83 Z
-84 X
-85 [
-86 =
-87 +
-88 §
-89 _
-90 £
-91 &
-92 #
-93 >
-94 <
-95 ~
-96 €
-97 @
-98 ¢
-99 »
-100 «
-47,5 fl
-47,18 fi
-101 ®
-102 ©
-103 ¥
diff --git a/research/street/testdata/charset_size=134.txt b/research/street/testdata/charset_size=134.txt
deleted file mode 100644
index 5c7fcde2ae0ab679f279a083d6de1c50d33ff90b..0000000000000000000000000000000000000000
--- a/research/street/testdata/charset_size=134.txt
+++ /dev/null
@@ -1,139 +0,0 @@
-0
-133
-1 l
-2 ’
-3 é
-4 t
-5 e
-6 i
-7 n
-8 s
-9 x
-10 g
-11 u
-12 o
-13 1
-14 8
-15 7
-16 0
-17 -
-18 .
-19 p
-20 a
-21 r
-22 è
-23 d
-24 c
-25 V
-26 v
-27 b
-28 m
-29 )
-30 C
-31 z
-32 S
-33 y
-34 ,
-35 k
-36 É
-37 A
-38 h
-39 E
-40 »
-41 D
-42 /
-43 H
-44 M
-45 (
-46 G
-47 P
-48 ç
-2 '
-49 R
-50 f
-51 "
-52 2
-53 j
-54 |
-55 N
-56 6
-57 °
-58 5
-59 T
-60 O
-61 U
-62 3
-63 %
-64 9
-65 q
-66 Z
-67 B
-68 K
-69 w
-70 W
-71 :
-72 4
-73 L
-74 F
-75 ]
-76 ï
-2 ‘
-77 I
-78 J
-79 ä
-80 î
-81 ;
-82 à
-83 ê
-84 X
-85 ü
-86 Y
-87 ô
-88 =
-89 +
-90 \
-91 {
-92 }
-93 _
-94 Q
-95 œ
-96 ñ
-97 *
-98 !
-99 Ü
-51 “
-100 â
-101 Ç
-102 Œ
-103 û
-104 ?
-105 $
-106 ë
-107 «
-108 €
-109 &
-110 <
-51 ”
-111 æ
-112 #
-113 ®
-114 Â
-115 È
-116 >
-117 [
-17 —
-118 Æ
-119 ù
-120 Î
-121 Ô
-122 ÿ
-123 À
-124 Ê
-125 @
-126 Ï
-127 ©
-128 Ë
-129 Ù
-130 £
-131 Ÿ
-132 Û
diff --git a/research/street/testdata/charset_size_10.txt b/research/street/testdata/charset_size_10.txt
deleted file mode 100644
index 93fffbd0f26d2a23f319f8765133a43fb25b7f46..0000000000000000000000000000000000000000
--- a/research/street/testdata/charset_size_10.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-0
-9
-1 a
-2 b
-3 r
-4 n
-4,5 m
-6 f
-7 .
-8 ,
diff --git a/research/street/testdata/mnist-tiny b/research/street/testdata/mnist-tiny
deleted file mode 100644
index 1470119aff9891557dcef02981c40ae958e6bd11..0000000000000000000000000000000000000000
Binary files a/research/street/testdata/mnist-tiny and /dev/null differ
diff --git a/research/street/testdata/numbers-16-tiny b/research/street/testdata/numbers-16-tiny
deleted file mode 100644
index bb0c11fcd034fad1cf650b386bf94476c9c1ccd1..0000000000000000000000000000000000000000
Binary files a/research/street/testdata/numbers-16-tiny and /dev/null differ
diff --git a/research/street/testdata/numbers.charset_size=12.txt b/research/street/testdata/numbers.charset_size=12.txt
deleted file mode 100644
index 12fdc77ded0c74b05d0624bc9f690e7384bc5038..0000000000000000000000000000000000000000
--- a/research/street/testdata/numbers.charset_size=12.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-0
-11
-1 9
-2 8
-3 7
-4 6
-5 1
-6 4
-7 0
-8 3
-9 5
-10 2
diff --git a/research/struct2depth/BUILD b/research/struct2depth/BUILD
deleted file mode 100644
index ffd0fb0cdc5bc3ecb62d3cbb5b502b353073615f..0000000000000000000000000000000000000000
--- a/research/struct2depth/BUILD
+++ /dev/null
@@ -1 +0,0 @@
-package(default_visibility = ["//visibility:public"])
diff --git a/research/struct2depth/README.md b/research/struct2depth/README.md
deleted file mode 100644
index de1d7e7f2a8864897ed0fdbe71a42171e47da5da..0000000000000000000000000000000000000000
--- a/research/struct2depth/README.md
+++ /dev/null
@@ -1,151 +0,0 @@
-
-
-
-
-# struct2depth
-
-This a method for unsupervised learning of depth and egomotion from monocular video, achieving new state-of-the-art results on both tasks by explicitly modeling 3D object motion, performing on-line refinement and improving quality for moving objects by novel loss formulations. It will appear in the following paper:
-
-**V. Casser, S. Pirk, R. Mahjourian, A. Angelova, Depth Prediction Without the Sensors: Leveraging Structure for Unsupervised Learning from Monocular Videos, AAAI Conference on Artificial Intelligence, 2019**
-https://arxiv.org/pdf/1811.06152.pdf
-
-This code is implemented and supported by Vincent Casser (git username: VincentCa) and Anelia Angelova (git username: AneliaAngelova). Please contact anelia@google.com for questions.
-
-Project website: https://sites.google.com/view/struct2depth.
-
-## Quick start: Running training
-
-Before running training, run gen_data_* script for the respective dataset in order to generate the data in the appropriate format for KITTI or Cityscapes. It is assumed that motion masks are already generated and stored as images.
-Models are trained from an Imagenet pretrained model.
-
-```shell
-
-ckpt_dir="your/checkpoint/folder"
-data_dir="KITTI_SEQ2_LR/" # Set for KITTI
-data_dir="CITYSCAPES_SEQ2_LR/" # Set for Cityscapes
-imagenet_ckpt="resnet_pretrained/model.ckpt"
-
-python train.py \
- --logtostderr \
- --checkpoint_dir $ckpt_dir \
- --data_dir $data_dir \
- --architecture resnet \
- --imagenet_ckpt $imagenet_ckpt \
- --imagenet_norm true \
- --joint_encoder false
-```
-
-
-
-## Running depth/egomotion inference on an image folder
-
-KITTI is trained on the raw image data (resized to 416 x 128), but inputs are standardized before feeding them, and Cityscapes images are cropped using the following cropping parameters: (192, 1856, 256, 768). If using a different crop, it is likely that additional training is necessary. Therefore, please follow the inference example shown below when using one of the models. The right choice might depend on a variety of factors. For example, if a checkpoint should be used for odometry, be aware that for improved odometry on motion models, using segmentation masks could be advantageous (setting *use_masks=true* for inference). On the other hand, all models can be used for single-frame depth estimation without any additional information.
-
-
-```shell
-
-input_dir="your/image/folder"
-output_dir="your/output/folder"
-model_checkpoint="your/model/checkpoint"
-
-python inference.py \
- --logtostderr \
- --file_extension png \
- --depth \
- --egomotion true \
- --input_dir $input_dir \
- --output_dir $output_dir \
- --model_ckpt $model_checkpoint
-```
-
-Note that the egomotion prediction expects the files in the input directory to be a consecutive sequence, and that sorting the filenames alphabetically is putting them in the right order.
-
-One can also run inference on KITTI by providing
-
-```shell
---input_list_file ~/kitti-raw-uncompressed/test_files_eigen.txt
-```
-
-and on Cityscapes by passing
-
-```shell
---input_list_file CITYSCAPES_FULL/test_files_cityscapes.txt
-```
-
-instead of *input_dir*.
-Alternatively inference can also be ran on pre-processed images.
-
-
-
-## Running on-line refinement
-
-On-line refinement is executed on top of an existing inference folder, so make sure to run regular inference first. Then you can run the on-line fusion procedure as follows:
-
-```shell
-
-prediction_dir="some/prediction/dir"
-model_ckpt="checkpoints/checkpoints_baseline/model-199160"
-handle_motion="false"
-size_constraint_weight="0" # This must be zero when not handling motion.
-
-# If running on KITTI, set as follows:
-data_dir="KITTI_SEQ2_LR_EIGEN/"
-triplet_list_file="$data_dir/test_files_eigen_triplets.txt"
-triplet_list_file_remains="$data_dir/test_files_eigen_triplets_remains.txt"
-ft_name="kitti"
-
-# If running on Cityscapes, set as follows:
-data_dir="CITYSCAPES_SEQ2_LR_TEST/" # Set for Cityscapes
-triplet_list_file="/CITYSCAPES_SEQ2_LR_TEST/test_files_cityscapes_triplets.txt"
-triplet_list_file_remains="CITYSCAPES_SEQ2_LR_TEST/test_files_cityscapes_triplets_remains.txt"
-ft_name="cityscapes"
-
-python optimize.py \
- --logtostderr \
- --output_dir $prediction_dir \
- --data_dir $data_dir \
- --triplet_list_file $triplet_list_file \
- --triplet_list_file_remains $triplet_list_file_remains \
- --ft_name $ft_name \
- --model_ckpt $model_ckpt \
- --file_extension png \
- --handle_motion $handle_motion \
- --size_constraint_weight $size_constraint_weight
-```
-
-
-
-## Running evaluation
-
-```shell
-
-prediction_dir="some/prediction/dir"
-
-# Use these settings for KITTI:
-eval_list_file="KITTI_FULL/kitti-raw-uncompressed/test_files_eigen.txt"
-eval_crop="garg"
-eval_mode="kitti"
-
-# Use these settings for Cityscapes:
-eval_list_file="CITYSCAPES_FULL/test_files_cityscapes.txt"
-eval_crop="none"
-eval_mode="cityscapes"
-
-python evaluate.py \
- --logtostderr \
- --prediction_dir $prediction_dir \
- --eval_list_file $eval_list_file \
- --eval_crop $eval_crop \
- --eval_mode $eval_mode
-```
-
-
-
-## Credits
-
-This code is implemented and supported by Vincent Casser and Anelia Angelova and can be found at
-https://sites.google.com/view/struct2depth.
-The core implementation is derived from [https://github.com/tensorflow/models/tree/master/research/vid2depth)](https://github.com/tensorflow/models/tree/master/research/vid2depth)
-by [Reza Mahjourian](rezama@google.com), which in turn is based on [SfMLearner
-(https://github.com/tinghuiz/SfMLearner)](https://github.com/tinghuiz/SfMLearner)
-by [Tinghui Zhou](https://github.com/tinghuiz).
diff --git a/research/struct2depth/alignment.py b/research/struct2depth/alignment.py
deleted file mode 100644
index 0e9417d482e2a243af45faa40230ad38da9b1b89..0000000000000000000000000000000000000000
--- a/research/struct2depth/alignment.py
+++ /dev/null
@@ -1,54 +0,0 @@
-
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Common utilities for data pre-processing, e.g. matching moving object across frames."""
-
-import numpy as np
-
-def compute_overlap(mask1, mask2):
- # Use IoU here.
- return np.sum(mask1 & mask2)/np.sum(mask1 | mask2)
-
-def align(seg_img1, seg_img2, seg_img3, threshold_same=0.3):
- res_img1 = np.zeros_like(seg_img1)
- res_img2 = np.zeros_like(seg_img2)
- res_img3 = np.zeros_like(seg_img3)
- remaining_objects2 = list(np.unique(seg_img2.flatten()))
- remaining_objects3 = list(np.unique(seg_img3.flatten()))
- for seg_id in np.unique(seg_img1):
- # See if we can find correspondences to seg_id in seg_img2.
- max_overlap2 = float('-inf')
- max_segid2 = -1
- for seg_id2 in remaining_objects2:
- overlap = compute_overlap(seg_img1==seg_id, seg_img2==seg_id2)
- if overlap>max_overlap2:
- max_overlap2 = overlap
- max_segid2 = seg_id2
- if max_overlap2 > threshold_same:
- max_overlap3 = float('-inf')
- max_segid3 = -1
- for seg_id3 in remaining_objects3:
- overlap = compute_overlap(seg_img2==max_segid2, seg_img3==seg_id3)
- if overlap>max_overlap3:
- max_overlap3 = overlap
- max_segid3 = seg_id3
- if max_overlap3 > threshold_same:
- res_img1[seg_img1==seg_id] = seg_id
- res_img2[seg_img2==max_segid2] = seg_id
- res_img3[seg_img3==max_segid3] = seg_id
- remaining_objects2.remove(max_segid2)
- remaining_objects3.remove(max_segid3)
- return res_img1, res_img2, res_img3
diff --git a/research/struct2depth/gen_data_city.py b/research/struct2depth/gen_data_city.py
deleted file mode 100644
index 7e18fe5acb978fe89a686b1ff8f44d030a62777d..0000000000000000000000000000000000000000
--- a/research/struct2depth/gen_data_city.py
+++ /dev/null
@@ -1,158 +0,0 @@
-
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-""" Offline data generation for the Cityscapes dataset."""
-
-import os
-from absl import app
-from absl import flags
-from absl import logging
-import numpy as np
-import cv2
-import os, glob
-
-import alignment
-from alignment import compute_overlap
-from alignment import align
-
-
-SKIP = 2
-WIDTH = 416
-HEIGHT = 128
-SUB_FOLDER = 'train'
-INPUT_DIR = '/usr/local/google/home/anelia/struct2depth/CITYSCAPES_FULL/'
-OUTPUT_DIR = '/usr/local/google/home/anelia/struct2depth/CITYSCAPES_Processed/'
-
-def crop(img, segimg, fx, fy, cx, cy):
- # Perform center cropping, preserving 50% vertically.
- middle_perc = 0.50
- left = 1 - middle_perc
- half = left / 2
- a = img[int(img.shape[0]*(half)):int(img.shape[0]*(1-half)), :]
- aseg = segimg[int(segimg.shape[0]*(half)):int(segimg.shape[0]*(1-half)), :]
- cy /= (1 / middle_perc)
-
- # Resize to match target height while preserving aspect ratio.
- wdt = int((float(HEIGHT)*a.shape[1]/a.shape[0]))
- x_scaling = float(wdt)/a.shape[1]
- y_scaling = float(HEIGHT)/a.shape[0]
- b = cv2.resize(a, (wdt, HEIGHT))
- bseg = cv2.resize(aseg, (wdt, HEIGHT))
-
- # Adjust intrinsics.
- fx*=x_scaling
- fy*=y_scaling
- cx*=x_scaling
- cy*=y_scaling
-
- # Perform center cropping horizontally.
- remain = b.shape[1] - WIDTH
- cx /= (b.shape[1] / WIDTH)
- c = b[:, int(remain/2):b.shape[1]-int(remain/2)]
- cseg = bseg[:, int(remain/2):b.shape[1]-int(remain/2)]
-
- return c, cseg, fx, fy, cx, cy
-
-
-def run_all():
- dir_name=INPUT_DIR + '/leftImg8bit_sequence/' + SUB_FOLDER + '/*'
- print('Processing directory', dir_name)
- for location in glob.glob(INPUT_DIR + '/leftImg8bit_sequence/' + SUB_FOLDER + '/*'):
- location_name = os.path.basename(location)
- print('Processing location', location_name)
- files = sorted(glob.glob(location + '/*.png'))
- files = [file for file in files if '-seg.png' not in file]
- # Break down into sequences
- sequences = {}
- seq_nr = 0
- last_seq = ''
- last_imgnr = -1
-
- for i in range(len(files)):
- seq = os.path.basename(files[i]).split('_')[1]
- nr = int(os.path.basename(files[i]).split('_')[2])
- if seq!=last_seq or last_imgnr+1!=nr:
- seq_nr+=1
- last_imgnr = nr
- last_seq = seq
- if not seq_nr in sequences:
- sequences[seq_nr] = []
- sequences[seq_nr].append(files[i])
-
- for (k,v) in sequences.items():
- print('Processing sequence', k, 'with', len(v), 'elements...')
- output_dir = OUTPUT_DIR + '/' + location_name + '_' + str(k)
- if not os.path.isdir(output_dir):
- os.mkdir(output_dir)
- files = sorted(v)
- triplet = []
- seg_triplet = []
- ct = 1
-
- # Find applicable intrinsics.
- for j in range(len(files)):
- osegname = os.path.basename(files[j]).split('_')[1]
- oimgnr = os.path.basename(files[j]).split('_')[2]
- applicable_intrinsics = INPUT_DIR + '/camera/' + SUB_FOLDER + '/' + location_name + '/' + location_name + '_' + osegname + '_' + oimgnr + '_camera.json'
- # Get the intrinsics for one of the file of the sequence.
- if os.path.isfile(applicable_intrinsics):
- f = open(applicable_intrinsics, 'r')
- lines = f.readlines()
- f.close()
- lines = [line.rstrip() for line in lines]
-
- fx = float(lines[11].split(': ')[1].replace(',', ''))
- fy = float(lines[12].split(': ')[1].replace(',', ''))
- cx = float(lines[13].split(': ')[1].replace(',', ''))
- cy = float(lines[14].split(': ')[1].replace(',', ''))
-
- for j in range(0, len(files), SKIP):
- img = cv2.imread(files[j])
- segimg = cv2.imread(files[j].replace('.png', '-seg.png'))
-
- smallimg, segimg, fx_this, fy_this, cx_this, cy_this = crop(img, segimg, fx, fy, cx, cy)
- triplet.append(smallimg)
- seg_triplet.append(segimg)
- if len(triplet)==3:
- cmb = np.hstack(triplet)
- align1, align2, align3 = align(seg_triplet[0], seg_triplet[1], seg_triplet[2])
- cmb_seg = np.hstack([align1, align2, align3])
- cv2.imwrite(os.path.join(output_dir, str(ct).zfill(10) + '.png'), cmb)
- cv2.imwrite(os.path.join(output_dir, str(ct).zfill(10) + '-fseg.png'), cmb_seg)
- f = open(os.path.join(output_dir, str(ct).zfill(10) + '_cam.txt'), 'w')
- f.write(str(fx_this) + ',0.0,' + str(cx_this) + ',0.0,' + str(fy_this) + ',' + str(cy_this) + ',0.0,0.0,1.0')
- f.close()
- del triplet[0]
- del seg_triplet[0]
- ct+=1
-
-# Create file list for training. Be careful as it collects and includes all files recursively.
-fn = open(OUTPUT_DIR + '/' + SUB_FOLDER + '.txt', 'w')
-for f in glob.glob(OUTPUT_DIR + '/*/*.png'):
- if '-seg.png' in f or '-fseg.png' in f:
- continue
- folder_name = f.split('/')[-2]
- img_name = f.split('/')[-1].replace('.png', '')
- fn.write(folder_name + ' ' + img_name + '\n')
-fn.close()
-
-
-def main(_):
- run_all()
-
-
-if __name__ == '__main__':
- app.run(main)
diff --git a/research/struct2depth/gen_data_kitti.py b/research/struct2depth/gen_data_kitti.py
deleted file mode 100644
index 8577c4c677383d29e074f922f56fd1abaef23543..0000000000000000000000000000000000000000
--- a/research/struct2depth/gen_data_kitti.py
+++ /dev/null
@@ -1,149 +0,0 @@
-
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-""" Offline data generation for the KITTI dataset."""
-
-import os
-from absl import app
-from absl import flags
-from absl import logging
-import numpy as np
-import cv2
-import os, glob
-
-import alignment
-from alignment import compute_overlap
-from alignment import align
-
-
-SEQ_LENGTH = 3
-WIDTH = 416
-HEIGHT = 128
-STEPSIZE = 1
-INPUT_DIR = '/usr/local/google/home/anelia/struct2depth/KITTI_FULL/kitti-raw-uncompressed'
-OUTPUT_DIR = '/usr/local/google/home/anelia/struct2depth/KITTI_procesed/'
-
-
-def get_line(file, start):
- file = open(file, 'r')
- lines = file.readlines()
- lines = [line.rstrip() for line in lines]
- ret = None
- for line in lines:
- nline = line.split(': ')
- if nline[0]==start:
- ret = nline[1].split(' ')
- ret = np.array([float(r) for r in ret], dtype=float)
- ret = ret.reshape((3,4))[0:3, 0:3]
- break
- file.close()
- return ret
-
-
-def crop(img, segimg, fx, fy, cx, cy):
- # Perform center cropping, preserving 50% vertically.
- middle_perc = 0.50
- left = 1-middle_perc
- half = left/2
- a = img[int(img.shape[0]*(half)):int(img.shape[0]*(1-half)), :]
- aseg = segimg[int(segimg.shape[0]*(half)):int(segimg.shape[0]*(1-half)), :]
- cy /= (1/middle_perc)
-
- # Resize to match target height while preserving aspect ratio.
- wdt = int((128*a.shape[1]/a.shape[0]))
- x_scaling = float(wdt)/a.shape[1]
- y_scaling = 128.0/a.shape[0]
- b = cv2.resize(a, (wdt, 128))
- bseg = cv2.resize(aseg, (wdt, 128))
-
- # Adjust intrinsics.
- fx*=x_scaling
- fy*=y_scaling
- cx*=x_scaling
- cy*=y_scaling
-
- # Perform center cropping horizontally.
- remain = b.shape[1] - 416
- cx /= (b.shape[1]/416)
- c = b[:, int(remain/2):b.shape[1]-int(remain/2)]
- cseg = bseg[:, int(remain/2):b.shape[1]-int(remain/2)]
-
- return c, cseg, fx, fy, cx, cy
-
-
-def run_all():
- ct = 0
-if not OUTPUT_DIR.endswith('/'):
- OUTPUT_DIR = OUTPUT_DIR + '/'
-
-for d in glob.glob(INPUT_DIR + '/*/'):
- date = d.split('/')[-2]
- file_calibration = d + 'calib_cam_to_cam.txt'
- calib_raw = [get_line(file_calibration, 'P_rect_02'), get_line(file_calibration, 'P_rect_03')]
-
- for d2 in glob.glob(d + '*/'):
- seqname = d2.split('/')[-2]
- print('Processing sequence', seqname)
- for subfolder in ['image_02/data', 'image_03/data']:
- ct = 1
- seqname = d2.split('/')[-2] + subfolder.replace('image', '').replace('/data', '')
- if not os.path.exists(OUTPUT_DIR + seqname):
- os.mkdir(OUTPUT_DIR + seqname)
-
- calib_camera = calib_raw[0] if subfolder=='image_02/data' else calib_raw[1]
- folder = d2 + subfolder
- files = glob.glob(folder + '/*.png')
- files = [file for file in files if not 'disp' in file and not 'flip' in file and not 'seg' in file]
- files = sorted(files)
- for i in range(SEQ_LENGTH, len(files)+1, STEPSIZE):
- imgnum = str(ct).zfill(10)
- if os.path.exists(OUTPUT_DIR + seqname + '/' + imgnum + '.png'):
- ct+=1
- continue
- big_img = np.zeros(shape=(HEIGHT, WIDTH*SEQ_LENGTH, 3))
- wct = 0
-
- for j in range(i-SEQ_LENGTH, i): # Collect frames for this sample.
- img = cv2.imread(files[j])
- ORIGINAL_HEIGHT, ORIGINAL_WIDTH, _ = img.shape
-
- zoom_x = WIDTH/ORIGINAL_WIDTH
- zoom_y = HEIGHT/ORIGINAL_HEIGHT
-
- # Adjust intrinsics.
- calib_current = calib_camera.copy()
- calib_current[0, 0] *= zoom_x
- calib_current[0, 2] *= zoom_x
- calib_current[1, 1] *= zoom_y
- calib_current[1, 2] *= zoom_y
-
- calib_representation = ','.join([str(c) for c in calib_current.flatten()])
-
- img = cv2.resize(img, (WIDTH, HEIGHT))
- big_img[:,wct*WIDTH:(wct+1)*WIDTH] = img
- wct+=1
- cv2.imwrite(OUTPUT_DIR + seqname + '/' + imgnum + '.png', big_img)
- f = open(OUTPUT_DIR + seqname + '/' + imgnum + '_cam.txt', 'w')
- f.write(calib_representation)
- f.close()
- ct+=1
-
-def main(_):
- run_all()
-
-
-if __name__ == '__main__':
- app.run(main)
diff --git a/research/struct2depth/inference.py b/research/struct2depth/inference.py
deleted file mode 100644
index 042e2be17f736aa99235651452ca27931a83c9bd..0000000000000000000000000000000000000000
--- a/research/struct2depth/inference.py
+++ /dev/null
@@ -1,416 +0,0 @@
-
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Runs struct2depth at inference. Produces depth estimates, ego-motion and object motion."""
-
-# Example usage:
-#
-# python inference.py \
-# --input_dir ~/struct2depth/kitti-raw-uncompressed/ \
-# --output_dir ~/struct2depth/output \
-# --model_ckpt ~/struct2depth/model/model-199160
-# --file_extension png \
-# --depth \
-# --egomotion true \
-
-
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-from absl import app
-from absl import flags
-from absl import logging
-#import matplotlib.pyplot as plt
-import model
-import numpy as np
-import fnmatch
-import tensorflow as tf
-import nets
-import util
-
-gfile = tf.gfile
-
-# CMAP = 'plasma'
-
-INFERENCE_MODE_SINGLE = 'single' # Take plain single-frame input.
-INFERENCE_MODE_TRIPLETS = 'triplets' # Take image triplets as input.
-# For KITTI, we just resize input images and do not perform cropping. For
-# Cityscapes, the car hood and more image content has been cropped in order
-# to fit aspect ratio, and remove static content from the images. This has to be
-# kept at inference time.
-INFERENCE_CROP_NONE = 'none'
-INFERENCE_CROP_CITYSCAPES = 'cityscapes'
-
-
-flags.DEFINE_string('output_dir', None, 'Directory to store predictions.')
-flags.DEFINE_string('file_extension', 'png', 'Image data file extension of '
- 'files provided with input_dir. Also determines the output '
- 'file format of depth prediction images.')
-flags.DEFINE_bool('depth', True, 'Determines if the depth prediction network '
- 'should be executed and its predictions be saved.')
-flags.DEFINE_bool('egomotion', False, 'Determines if the egomotion prediction '
- 'network should be executed and its predictions be saved. If '
- 'inference is run in single inference mode, it is assumed '
- 'that files in the same directory belong in the same '
- 'sequence, and sorting them alphabetically establishes the '
- 'right temporal order.')
-flags.DEFINE_string('model_ckpt', None, 'Model checkpoint to evaluate.')
-flags.DEFINE_string('input_dir', None, 'Directory containing image files to '
- 'evaluate. This crawls recursively for images in the '
- 'directory, mirroring relative subdirectory structures '
- 'into the output directory.')
-flags.DEFINE_string('input_list_file', None, 'Text file containing paths to '
- 'image files to process. Paths should be relative with '
- 'respect to the list file location. Relative path '
- 'structures will be mirrored in the output directory.')
-flags.DEFINE_integer('batch_size', 1, 'The size of a sample batch')
-flags.DEFINE_integer('img_height', 128, 'Input frame height.')
-flags.DEFINE_integer('img_width', 416, 'Input frame width.')
-flags.DEFINE_integer('seq_length', 3, 'Number of frames in sequence.')
-flags.DEFINE_enum('architecture', nets.RESNET, nets.ARCHITECTURES,
- 'Defines the architecture to use for the depth prediction '
- 'network. Defaults to ResNet-based encoder and accompanying '
- 'decoder.')
-flags.DEFINE_boolean('imagenet_norm', True, 'Whether to normalize the input '
- 'images channel-wise so that they match the distribution '
- 'most ImageNet-models were trained on.')
-flags.DEFINE_bool('use_skip', True, 'Whether to use skip connections in the '
- 'encoder-decoder architecture.')
-flags.DEFINE_bool('joint_encoder', False, 'Whether to share parameters '
- 'between the depth and egomotion networks by using a joint '
- 'encoder architecture. The egomotion network is then '
- 'operating only on the hidden representation provided by the '
- 'joint encoder.')
-flags.DEFINE_bool('shuffle', False, 'Whether to shuffle the order in which '
- 'images are processed.')
-flags.DEFINE_bool('flip', False, 'Whether images should be flipped as well as '
- 'resulting predictions (for test-time augmentation). This '
- 'currently applies to the depth network only.')
-flags.DEFINE_enum('inference_mode', INFERENCE_MODE_SINGLE,
- [INFERENCE_MODE_SINGLE,
- INFERENCE_MODE_TRIPLETS],
- 'Whether to use triplet mode for inference, which accepts '
- 'triplets instead of single frames.')
-flags.DEFINE_enum('inference_crop', INFERENCE_CROP_NONE,
- [INFERENCE_CROP_NONE,
- INFERENCE_CROP_CITYSCAPES],
- 'Whether to apply a Cityscapes-specific crop on the input '
- 'images first before running inference.')
-flags.DEFINE_bool('use_masks', False, 'Whether to mask out potentially '
- 'moving objects when feeding image input to the egomotion '
- 'network. This might improve odometry results when using '
- 'a motion model. For this, pre-computed segmentation '
- 'masks have to be available for every image, with the '
- 'background being zero.')
-
-FLAGS = flags.FLAGS
-
-flags.mark_flag_as_required('output_dir')
-flags.mark_flag_as_required('model_ckpt')
-
-
-def _run_inference(output_dir=None,
- file_extension='png',
- depth=True,
- egomotion=False,
- model_ckpt=None,
- input_dir=None,
- input_list_file=None,
- batch_size=1,
- img_height=128,
- img_width=416,
- seq_length=3,
- architecture=nets.RESNET,
- imagenet_norm=True,
- use_skip=True,
- joint_encoder=True,
- shuffle=False,
- flip_for_depth=False,
- inference_mode=INFERENCE_MODE_SINGLE,
- inference_crop=INFERENCE_CROP_NONE,
- use_masks=False):
- """Runs inference. Refer to flags in inference.py for details."""
- inference_model = model.Model(is_training=False,
- batch_size=batch_size,
- img_height=img_height,
- img_width=img_width,
- seq_length=seq_length,
- architecture=architecture,
- imagenet_norm=imagenet_norm,
- use_skip=use_skip,
- joint_encoder=joint_encoder)
- vars_to_restore = util.get_vars_to_save_and_restore(model_ckpt)
- saver = tf.train.Saver(vars_to_restore)
- sv = tf.train.Supervisor(logdir='/tmp/', saver=None)
- with sv.managed_session() as sess:
- saver.restore(sess, model_ckpt)
- if not gfile.Exists(output_dir):
- gfile.MakeDirs(output_dir)
- logging.info('Predictions will be saved in %s.', output_dir)
-
- # Collect all images to run inference on.
- im_files, basepath_in = collect_input_images(input_dir, input_list_file,
- file_extension)
- if shuffle:
- logging.info('Shuffling data...')
- np.random.shuffle(im_files)
- logging.info('Running inference on %d files.', len(im_files))
-
- # Create missing output folders and pre-compute target directories.
- output_dirs = create_output_dirs(im_files, basepath_in, output_dir)
-
- # Run depth prediction network.
- if depth:
- im_batch = []
- for i in range(len(im_files)):
- if i % 100 == 0:
- logging.info('%s of %s files processed.', i, len(im_files))
-
- # Read image and run inference.
- if inference_mode == INFERENCE_MODE_SINGLE:
- if inference_crop == INFERENCE_CROP_NONE:
- im = util.load_image(im_files[i], resize=(img_width, img_height))
- elif inference_crop == INFERENCE_CROP_CITYSCAPES:
- im = util.crop_cityscapes(util.load_image(im_files[i]),
- resize=(img_width, img_height))
- elif inference_mode == INFERENCE_MODE_TRIPLETS:
- im = util.load_image(im_files[i], resize=(img_width * 3, img_height))
- im = im[:, img_width:img_width*2]
- if flip_for_depth:
- im = np.flip(im, axis=1)
- im_batch.append(im)
-
- if len(im_batch) == batch_size or i == len(im_files) - 1:
- # Call inference on batch.
- for _ in range(batch_size - len(im_batch)): # Fill up batch.
- im_batch.append(np.zeros(shape=(img_height, img_width, 3),
- dtype=np.float32))
- im_batch = np.stack(im_batch, axis=0)
- est_depth = inference_model.inference_depth(im_batch, sess)
- if flip_for_depth:
- est_depth = np.flip(est_depth, axis=2)
- im_batch = np.flip(im_batch, axis=2)
-
- for j in range(len(im_batch)):
- color_map = util.normalize_depth_for_display(
- np.squeeze(est_depth[j]))
- visualization = np.concatenate((im_batch[j], color_map), axis=0)
- # Save raw prediction and color visualization. Extract filename
- # without extension from full path: e.g. path/to/input_dir/folder1/
- # file1.png -> file1
- k = i - len(im_batch) + 1 + j
- filename_root = os.path.splitext(os.path.basename(im_files[k]))[0]
- pref = '_flip' if flip_for_depth else ''
- output_raw = os.path.join(
- output_dirs[k], filename_root + pref + '.npy')
- output_vis = os.path.join(
- output_dirs[k], filename_root + pref + '.png')
- with gfile.Open(output_raw, 'wb') as f:
- np.save(f, est_depth[j])
- util.save_image(output_vis, visualization, file_extension)
- im_batch = []
-
- # Run egomotion network.
- if egomotion:
- if inference_mode == INFERENCE_MODE_SINGLE:
- # Run regular egomotion inference loop.
- input_image_seq = []
- input_seg_seq = []
- current_sequence_dir = None
- current_output_handle = None
- for i in range(len(im_files)):
- sequence_dir = os.path.dirname(im_files[i])
- if sequence_dir != current_sequence_dir:
- # Assume start of a new sequence, since this image lies in a
- # different directory than the previous ones.
- # Clear egomotion input buffer.
- output_filepath = os.path.join(output_dirs[i], 'egomotion.txt')
- if current_output_handle is not None:
- current_output_handle.close()
- current_sequence_dir = sequence_dir
- logging.info('Writing egomotion sequence to %s.', output_filepath)
- current_output_handle = gfile.Open(output_filepath, 'w')
- input_image_seq = []
- im = util.load_image(im_files[i], resize=(img_width, img_height))
- input_image_seq.append(im)
- if use_masks:
- im_seg_path = im_files[i].replace('.%s' % file_extension,
- '-seg.%s' % file_extension)
- if not gfile.Exists(im_seg_path):
- raise ValueError('No segmentation mask %s has been found for '
- 'image %s. If none are available, disable '
- 'use_masks.' % (im_seg_path, im_files[i]))
- input_seg_seq.append(util.load_image(im_seg_path,
- resize=(img_width, img_height),
- interpolation='nn'))
-
- if len(input_image_seq) < seq_length: # Buffer not filled yet.
- continue
- if len(input_image_seq) > seq_length: # Remove oldest entry.
- del input_image_seq[0]
- if use_masks:
- del input_seg_seq[0]
-
- input_image_stack = np.concatenate(input_image_seq, axis=2)
- input_image_stack = np.expand_dims(input_image_stack, axis=0)
- if use_masks:
- input_image_stack = mask_image_stack(input_image_stack,
- input_seg_seq)
- est_egomotion = np.squeeze(inference_model.inference_egomotion(
- input_image_stack, sess))
- egomotion_str = []
- for j in range(seq_length - 1):
- egomotion_str.append(','.join([str(d) for d in est_egomotion[j]]))
- current_output_handle.write(
- str(i) + ' ' + ' '.join(egomotion_str) + '\n')
- if current_output_handle is not None:
- current_output_handle.close()
- elif inference_mode == INFERENCE_MODE_TRIPLETS:
- written_before = []
- for i in range(len(im_files)):
- im = util.load_image(im_files[i], resize=(img_width * 3, img_height))
- input_image_stack = np.concatenate(
- [im[:, :img_width], im[:, img_width:img_width*2],
- im[:, img_width*2:]], axis=2)
- input_image_stack = np.expand_dims(input_image_stack, axis=0)
- if use_masks:
- im_seg_path = im_files[i].replace('.%s' % file_extension,
- '-seg.%s' % file_extension)
- if not gfile.Exists(im_seg_path):
- raise ValueError('No segmentation mask %s has been found for '
- 'image %s. If none are available, disable '
- 'use_masks.' % (im_seg_path, im_files[i]))
- seg = util.load_image(im_seg_path,
- resize=(img_width * 3, img_height),
- interpolation='nn')
- input_seg_seq = [seg[:, :img_width], seg[:, img_width:img_width*2],
- seg[:, img_width*2:]]
- input_image_stack = mask_image_stack(input_image_stack,
- input_seg_seq)
- est_egomotion = inference_model.inference_egomotion(
- input_image_stack, sess)
- est_egomotion = np.squeeze(est_egomotion)
- egomotion_1_2 = ','.join([str(d) for d in est_egomotion[0]])
- egomotion_2_3 = ','.join([str(d) for d in est_egomotion[1]])
-
- output_filepath = os.path.join(output_dirs[i], 'egomotion.txt')
- file_mode = 'w' if output_filepath not in written_before else 'a'
- with gfile.Open(output_filepath, file_mode) as current_output_handle:
- current_output_handle.write(str(i) + ' ' + egomotion_1_2 + ' ' +
- egomotion_2_3 + '\n')
- written_before.append(output_filepath)
- logging.info('Done.')
-
-
-def mask_image_stack(input_image_stack, input_seg_seq):
- """Masks out moving image contents by using the segmentation masks provided.
-
- This can lead to better odometry accuracy for motion models, but is optional
- to use. Is only called if use_masks is enabled.
- Args:
- input_image_stack: The input image stack of shape (1, H, W, seq_length).
- input_seg_seq: List of segmentation masks with seq_length elements of shape
- (H, W, C) for some number of channels C.
-
- Returns:
- Input image stack with detections provided by segmentation mask removed.
- """
- background = [mask == 0 for mask in input_seg_seq]
- background = reduce(lambda m1, m2: m1 & m2, background)
- # If masks are RGB, assume all channels to be the same. Reduce to the first.
- if background.ndim == 3 and background.shape[2] > 1:
- background = np.expand_dims(background[:, :, 0], axis=2)
- elif background.ndim == 2: # Expand.
- background = np.expand_dism(background, axis=2)
- # background is now of shape (H, W, 1).
- background_stack = np.tile(background, [1, 1, input_image_stack.shape[3]])
- return np.multiply(input_image_stack, background_stack)
-
-
-def collect_input_images(input_dir, input_list_file, file_extension):
- """Collects all input images that are to be processed."""
- if input_dir is not None:
- im_files = _recursive_glob(input_dir, '*.' + file_extension)
- basepath_in = os.path.normpath(input_dir)
- elif input_list_file is not None:
- im_files = util.read_text_lines(input_list_file)
- basepath_in = os.path.dirname(input_list_file)
- im_files = [os.path.join(basepath_in, f) for f in im_files]
- im_files = [f for f in im_files if 'disp' not in f and '-seg' not in f and
- '-fseg' not in f and '-flip' not in f]
- return sorted(im_files), basepath_in
-
-
-def create_output_dirs(im_files, basepath_in, output_dir):
- """Creates required directories, and returns output dir for each file."""
- output_dirs = []
- for i in range(len(im_files)):
- relative_folder_in = os.path.relpath(
- os.path.dirname(im_files[i]), basepath_in)
- absolute_folder_out = os.path.join(output_dir, relative_folder_in)
- if not gfile.IsDirectory(absolute_folder_out):
- gfile.MakeDirs(absolute_folder_out)
- output_dirs.append(absolute_folder_out)
- return output_dirs
-
-
-def _recursive_glob(treeroot, pattern):
- results = []
- for base, _, files in os.walk(treeroot):
- files = fnmatch.filter(files, pattern)
- results.extend(os.path.join(base, f) for f in files)
- return results
-
-
-def main(_):
- #if (flags.input_dir is None) == (flags.input_list_file is None):
- # raise ValueError('Exactly one of either input_dir or input_list_file has '
- # 'to be provided.')
- #if not flags.depth and not flags.egomotion:
- # raise ValueError('At least one of the depth and egomotion network has to '
- # 'be called for inference.')
- #if (flags.inference_mode == inference_lib.INFERENCE_MODE_TRIPLETS and
- # flags.seq_length != 3):
- # raise ValueError('For sequence lengths other than three, single inference '
- # 'mode has to be used.')
-
- _run_inference(output_dir=FLAGS.output_dir,
- file_extension=FLAGS.file_extension,
- depth=FLAGS.depth,
- egomotion=FLAGS.egomotion,
- model_ckpt=FLAGS.model_ckpt,
- input_dir=FLAGS.input_dir,
- input_list_file=FLAGS.input_list_file,
- batch_size=FLAGS.batch_size,
- img_height=FLAGS.img_height,
- img_width=FLAGS.img_width,
- seq_length=FLAGS.seq_length,
- architecture=FLAGS.architecture,
- imagenet_norm=FLAGS.imagenet_norm,
- use_skip=FLAGS.use_skip,
- joint_encoder=FLAGS.joint_encoder,
- shuffle=FLAGS.shuffle,
- flip_for_depth=FLAGS.flip,
- inference_mode=FLAGS.inference_mode,
- inference_crop=FLAGS.inference_crop,
- use_masks=FLAGS.use_masks)
-
-
-if __name__ == '__main__':
- app.run(main)
diff --git a/research/struct2depth/model.py b/research/struct2depth/model.py
deleted file mode 100644
index 873be26bb941626c93a7bdbdc9052ede51aeaa8c..0000000000000000000000000000000000000000
--- a/research/struct2depth/model.py
+++ /dev/null
@@ -1,848 +0,0 @@
-
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Build model for inference or training."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from absl import logging
-import numpy as np
-import tensorflow as tf
-
-import nets
-import project
-import reader
-import util
-
-gfile = tf.gfile
-slim = tf.contrib.slim
-
-NUM_SCALES = 4
-
-
-class Model(object):
- """Model code based on SfMLearner."""
-
- def __init__(self,
- data_dir=None,
- file_extension='png',
- is_training=True,
- learning_rate=0.0002,
- beta1=0.9,
- reconstr_weight=0.85,
- smooth_weight=0.05,
- ssim_weight=0.15,
- icp_weight=0.0,
- batch_size=4,
- img_height=128,
- img_width=416,
- seq_length=3,
- architecture=nets.RESNET,
- imagenet_norm=True,
- weight_reg=0.05,
- exhaustive_mode=False,
- random_scale_crop=False,
- flipping_mode=reader.FLIP_RANDOM,
- random_color=True,
- depth_upsampling=True,
- depth_normalization=True,
- compute_minimum_loss=True,
- use_skip=True,
- joint_encoder=True,
- build_sum=True,
- shuffle=True,
- input_file='train',
- handle_motion=False,
- equal_weighting=False,
- size_constraint_weight=0.0,
- train_global_scale_var=True):
- self.data_dir = data_dir
- self.file_extension = file_extension
- self.is_training = is_training
- self.learning_rate = learning_rate
- self.reconstr_weight = reconstr_weight
- self.smooth_weight = smooth_weight
- self.ssim_weight = ssim_weight
- self.icp_weight = icp_weight
- self.beta1 = beta1
- self.batch_size = batch_size
- self.img_height = img_height
- self.img_width = img_width
- self.seq_length = seq_length
- self.architecture = architecture
- self.imagenet_norm = imagenet_norm
- self.weight_reg = weight_reg
- self.exhaustive_mode = exhaustive_mode
- self.random_scale_crop = random_scale_crop
- self.flipping_mode = flipping_mode
- self.random_color = random_color
- self.depth_upsampling = depth_upsampling
- self.depth_normalization = depth_normalization
- self.compute_minimum_loss = compute_minimum_loss
- self.use_skip = use_skip
- self.joint_encoder = joint_encoder
- self.build_sum = build_sum
- self.shuffle = shuffle
- self.input_file = input_file
- self.handle_motion = handle_motion
- self.equal_weighting = equal_weighting
- self.size_constraint_weight = size_constraint_weight
- self.train_global_scale_var = train_global_scale_var
-
- logging.info('data_dir: %s', data_dir)
- logging.info('file_extension: %s', file_extension)
- logging.info('is_training: %s', is_training)
- logging.info('learning_rate: %s', learning_rate)
- logging.info('reconstr_weight: %s', reconstr_weight)
- logging.info('smooth_weight: %s', smooth_weight)
- logging.info('ssim_weight: %s', ssim_weight)
- logging.info('icp_weight: %s', icp_weight)
- logging.info('size_constraint_weight: %s', size_constraint_weight)
- logging.info('beta1: %s', beta1)
- logging.info('batch_size: %s', batch_size)
- logging.info('img_height: %s', img_height)
- logging.info('img_width: %s', img_width)
- logging.info('seq_length: %s', seq_length)
- logging.info('architecture: %s', architecture)
- logging.info('imagenet_norm: %s', imagenet_norm)
- logging.info('weight_reg: %s', weight_reg)
- logging.info('exhaustive_mode: %s', exhaustive_mode)
- logging.info('random_scale_crop: %s', random_scale_crop)
- logging.info('flipping_mode: %s', flipping_mode)
- logging.info('random_color: %s', random_color)
- logging.info('depth_upsampling: %s', depth_upsampling)
- logging.info('depth_normalization: %s', depth_normalization)
- logging.info('compute_minimum_loss: %s', compute_minimum_loss)
- logging.info('use_skip: %s', use_skip)
- logging.info('joint_encoder: %s', joint_encoder)
- logging.info('build_sum: %s', build_sum)
- logging.info('shuffle: %s', shuffle)
- logging.info('input_file: %s', input_file)
- logging.info('handle_motion: %s', handle_motion)
- logging.info('equal_weighting: %s', equal_weighting)
- logging.info('train_global_scale_var: %s', train_global_scale_var)
-
- if self.size_constraint_weight > 0 or not is_training:
- self.global_scale_var = tf.Variable(
- 0.1, name='global_scale_var',
- trainable=self.is_training and train_global_scale_var,
- dtype=tf.float32,
- constraint=lambda x: tf.clip_by_value(x, 0, np.infty))
-
- if self.is_training:
- self.reader = reader.DataReader(self.data_dir, self.batch_size,
- self.img_height, self.img_width,
- self.seq_length, NUM_SCALES,
- self.file_extension,
- self.random_scale_crop,
- self.flipping_mode,
- self.random_color,
- self.imagenet_norm,
- self.shuffle,
- self.input_file)
- self.build_train_graph()
- else:
- self.build_depth_test_graph()
- self.build_egomotion_test_graph()
- if self.handle_motion:
- self.build_objectmotion_test_graph()
-
- # At this point, the model is ready. Print some info on model params.
- util.count_parameters()
-
- def build_train_graph(self):
- self.build_inference_for_training()
- self.build_loss()
- self.build_train_op()
- if self.build_sum:
- self.build_summaries()
-
- def build_inference_for_training(self):
- """Invokes depth and ego-motion networks and computes clouds if needed."""
- (self.image_stack, self.image_stack_norm, self.seg_stack,
- self.intrinsic_mat, self.intrinsic_mat_inv) = self.reader.read_data()
- with tf.variable_scope('depth_prediction'):
- # Organized by ...[i][scale]. Note that the order is flipped in
- # variables in build_loss() below.
- self.disp = {}
- self.depth = {}
- self.depth_upsampled = {}
- self.inf_loss = 0.0
- # Organized by [i].
- disp_bottlenecks = [None] * self.seq_length
-
- if self.icp_weight > 0:
- self.cloud = {}
- for i in range(self.seq_length):
- image = self.image_stack_norm[:, :, :, 3 * i:3 * (i + 1)]
-
- multiscale_disps_i, disp_bottlenecks[i] = nets.disp_net(
- self.architecture, image, self.use_skip,
- self.weight_reg, True)
- multiscale_depths_i = [1.0 / d for d in multiscale_disps_i]
- self.disp[i] = multiscale_disps_i
- self.depth[i] = multiscale_depths_i
- if self.depth_upsampling:
- self.depth_upsampled[i] = []
- # Upsample low-resolution depth maps using differentiable bilinear
- # interpolation.
- for s in range(len(multiscale_depths_i)):
- self.depth_upsampled[i].append(tf.image.resize_bilinear(
- multiscale_depths_i[s], [self.img_height, self.img_width],
- align_corners=True))
-
- if self.icp_weight > 0:
- multiscale_clouds_i = [
- project.get_cloud(d,
- self.intrinsic_mat_inv[:, s, :, :],
- name='cloud%d_%d' % (s, i))
- for (s, d) in enumerate(multiscale_depths_i)
- ]
- self.cloud[i] = multiscale_clouds_i
- # Reuse the same depth graph for all images.
- tf.get_variable_scope().reuse_variables()
-
- if self.handle_motion:
- # Define egomotion network. This network can see the whole scene except
- # for any moving objects as indicated by the provided segmentation masks.
- # To avoid the network getting clues of motion by tracking those masks, we
- # define the segmentation masks as the union temporally.
- with tf.variable_scope('egomotion_prediction'):
- base_input = self.image_stack_norm # (B, H, W, 9)
- seg_input = self.seg_stack # (B, H, W, 9)
- ref_zero = tf.constant(0, dtype=tf.uint8)
- # Motion model is currently defined for three-frame sequences.
- object_mask1 = tf.equal(seg_input[:, :, :, 0], ref_zero)
- object_mask2 = tf.equal(seg_input[:, :, :, 3], ref_zero)
- object_mask3 = tf.equal(seg_input[:, :, :, 6], ref_zero)
- mask_complete = tf.expand_dims(tf.logical_and( # (B, H, W, 1)
- tf.logical_and(object_mask1, object_mask2), object_mask3), axis=3)
- mask_complete = tf.tile(mask_complete, (1, 1, 1, 9)) # (B, H, W, 9)
- # Now mask out base_input.
- self.mask_complete = tf.to_float(mask_complete)
- self.base_input_masked = base_input * self.mask_complete
- self.egomotion = nets.egomotion_net(
- image_stack=self.base_input_masked,
- disp_bottleneck_stack=None,
- joint_encoder=False,
- seq_length=self.seq_length,
- weight_reg=self.weight_reg)
-
- # Define object motion network for refinement. This network only sees
- # one object at a time over the whole sequence, and tries to estimate its
- # motion. The sequence of images are the respective warped frames.
-
- # For each scale, contains batch_size elements of shape (N, 2, 6).
- self.object_transforms = {}
- # For each scale, contains batch_size elements of shape (N, H, W, 9).
- self.object_masks = {}
- self.object_masks_warped = {}
- # For each scale, contains batch_size elements of size N.
- self.object_ids = {}
-
- self.egomotions_seq = {}
- self.warped_seq = {}
- self.inputs_objectmotion_net = {}
- with tf.variable_scope('objectmotion_prediction'):
- # First, warp raw images according to overall egomotion.
- for s in range(NUM_SCALES):
- self.warped_seq[s] = []
- self.egomotions_seq[s] = []
- for source_index in range(self.seq_length):
- egomotion_mat_i_1 = project.get_transform_mat(
- self.egomotion, source_index, 1)
- warped_image_i_1, _ = (
- project.inverse_warp(
- self.image_stack[
- :, :, :, source_index*3:(source_index+1)*3],
- self.depth_upsampled[1][s],
- egomotion_mat_i_1,
- self.intrinsic_mat[:, 0, :, :],
- self.intrinsic_mat_inv[:, 0, :, :]))
-
- self.warped_seq[s].append(warped_image_i_1)
- self.egomotions_seq[s].append(egomotion_mat_i_1)
-
- # Second, for every object in the segmentation mask, take its mask and
- # warp it according to the egomotion estimate. Then put a threshold to
- # binarize the warped result. Use this mask to mask out background and
- # other objects, and pass the filtered image to the object motion
- # network.
- self.object_transforms[s] = []
- self.object_masks[s] = []
- self.object_ids[s] = []
- self.object_masks_warped[s] = []
- self.inputs_objectmotion_net[s] = {}
-
- for i in range(self.batch_size):
- seg_sequence = self.seg_stack[i] # (H, W, 9=3*3)
- object_ids = tf.unique(tf.reshape(seg_sequence, [-1]))[0]
- self.object_ids[s].append(object_ids)
- color_stack = []
- mask_stack = []
- mask_stack_warped = []
- for j in range(self.seq_length):
- current_image = self.warped_seq[s][j][i] # (H, W, 3)
- current_seg = seg_sequence[:, :, j * 3:(j+1) * 3] # (H, W, 3)
-
- def process_obj_mask_warp(obj_id):
- """Performs warping of the individual object masks."""
- obj_mask = tf.to_float(tf.equal(current_seg, obj_id))
- # Warp obj_mask according to overall egomotion.
- obj_mask_warped, _ = (
- project.inverse_warp(
- tf.expand_dims(obj_mask, axis=0),
- # Middle frame, highest scale, batch element i:
- tf.expand_dims(self.depth_upsampled[1][s][i], axis=0),
- # Matrix for warping j into middle frame, batch elem. i:
- tf.expand_dims(self.egomotions_seq[s][j][i], axis=0),
- tf.expand_dims(self.intrinsic_mat[i, 0, :, :], axis=0),
- tf.expand_dims(self.intrinsic_mat_inv[i, 0, :, :],
- axis=0)))
- obj_mask_warped = tf.squeeze(obj_mask_warped)
- obj_mask_binarized = tf.greater( # Threshold to binarize mask.
- obj_mask_warped, tf.constant(0.5))
- return tf.to_float(obj_mask_binarized)
-
- def process_obj_mask(obj_id):
- """Returns the individual object masks separately."""
- return tf.to_float(tf.equal(current_seg, obj_id))
- object_masks = tf.map_fn( # (N, H, W, 3)
- process_obj_mask, object_ids, dtype=tf.float32)
-
- if self.size_constraint_weight > 0:
- # The object segmentation masks are all in object_masks.
- # We need to measure the height of every of them, and get the
- # approximate distance.
-
- # self.depth_upsampled of shape (seq_length, scale, B, H, W).
- depth_pred = self.depth_upsampled[j][s][i] # (H, W)
- def get_losses(obj_mask):
- """Get motion constraint loss."""
- # Find height of segment.
- coords = tf.where(tf.greater( # Shape (num_true, 2=yx)
- obj_mask[:, :, 0], tf.constant(0.5, dtype=tf.float32)))
- y_max = tf.reduce_max(coords[:, 0])
- y_min = tf.reduce_min(coords[:, 0])
- seg_height = y_max - y_min
- f_y = self.intrinsic_mat[i, 0, 1, 1]
- approx_depth = ((f_y * self.global_scale_var) /
- tf.to_float(seg_height))
- reference_pred = tf.boolean_mask(
- depth_pred, tf.greater(
- tf.reshape(obj_mask[:, :, 0],
- (self.img_height, self.img_width, 1)),
- tf.constant(0.5, dtype=tf.float32)))
-
- # Establish loss on approx_depth, a scalar, and
- # reference_pred, our dense prediction. Normalize both to
- # prevent degenerative depth shrinking.
- global_mean_depth_pred = tf.reduce_mean(depth_pred)
- reference_pred /= global_mean_depth_pred
- approx_depth /= global_mean_depth_pred
- spatial_err = tf.abs(reference_pred - approx_depth)
- mean_spatial_err = tf.reduce_mean(spatial_err)
- return mean_spatial_err
-
- losses = tf.map_fn(
- get_losses, object_masks, dtype=tf.float32)
- self.inf_loss += tf.reduce_mean(losses)
- object_masks_warped = tf.map_fn( # (N, H, W, 3)
- process_obj_mask_warp, object_ids, dtype=tf.float32)
- filtered_images = tf.map_fn(
- lambda mask: current_image * mask, object_masks_warped,
- dtype=tf.float32) # (N, H, W, 3)
- color_stack.append(filtered_images)
- mask_stack.append(object_masks)
- mask_stack_warped.append(object_masks_warped)
-
- # For this batch-element, if there are N moving objects,
- # color_stack, mask_stack and mask_stack_warped contain both
- # seq_length elements of shape (N, H, W, 3).
- # We can now concatenate them on the last axis, creating a tensor of
- # (N, H, W, 3*3 = 9), and, assuming N does not get too large so that
- # we have enough memory, pass them in a single batch to the object
- # motion network.
- mask_stack = tf.concat(mask_stack, axis=3) # (N, H, W, 9)
- mask_stack_warped = tf.concat(mask_stack_warped, axis=3)
- color_stack = tf.concat(color_stack, axis=3) # (N, H, W, 9)
- all_transforms = nets.objectmotion_net(
- # We cut the gradient flow here as the object motion gradient
- # should have no saying in how the egomotion network behaves.
- # One could try just stopping the gradient for egomotion, but
- # not for the depth prediction network.
- image_stack=tf.stop_gradient(color_stack),
- disp_bottleneck_stack=None,
- joint_encoder=False, # Joint encoder not supported.
- seq_length=self.seq_length,
- weight_reg=self.weight_reg)
- # all_transforms of shape (N, 2, 6).
- self.object_transforms[s].append(all_transforms)
- self.object_masks[s].append(mask_stack)
- self.object_masks_warped[s].append(mask_stack_warped)
- self.inputs_objectmotion_net[s][i] = color_stack
- tf.get_variable_scope().reuse_variables()
- else:
- # Don't handle motion, classic model formulation.
- with tf.name_scope('egomotion_prediction'):
- if self.joint_encoder:
- # Re-arrange disp_bottleneck_stack to be of shape
- # [B, h_hid, w_hid, c_hid * seq_length]. Currently, it is a list with
- # seq_length elements, each of dimension [B, h_hid, w_hid, c_hid].
- disp_bottleneck_stack = tf.concat(disp_bottlenecks, axis=3)
- else:
- disp_bottleneck_stack = None
- self.egomotion = nets.egomotion_net(
- image_stack=self.image_stack_norm,
- disp_bottleneck_stack=disp_bottleneck_stack,
- joint_encoder=self.joint_encoder,
- seq_length=self.seq_length,
- weight_reg=self.weight_reg)
-
- def build_loss(self):
- """Adds ops for computing loss."""
- with tf.name_scope('compute_loss'):
- self.reconstr_loss = 0
- self.smooth_loss = 0
- self.ssim_loss = 0
- self.icp_transform_loss = 0
- self.icp_residual_loss = 0
-
- # self.images is organized by ...[scale][B, h, w, seq_len * 3].
- self.images = [None for _ in range(NUM_SCALES)]
- # Following nested lists are organized by ...[scale][source-target].
- self.warped_image = [{} for _ in range(NUM_SCALES)]
- self.warp_mask = [{} for _ in range(NUM_SCALES)]
- self.warp_error = [{} for _ in range(NUM_SCALES)]
- self.ssim_error = [{} for _ in range(NUM_SCALES)]
- self.icp_transform = [{} for _ in range(NUM_SCALES)]
- self.icp_residual = [{} for _ in range(NUM_SCALES)]
-
- self.middle_frame_index = util.get_seq_middle(self.seq_length)
-
- # Compute losses at each scale.
- for s in range(NUM_SCALES):
- # Scale image stack.
- if s == 0: # Just as a precaution. TF often has interpolation bugs.
- self.images[s] = self.image_stack
- else:
- height_s = int(self.img_height / (2**s))
- width_s = int(self.img_width / (2**s))
- self.images[s] = tf.image.resize_bilinear(
- self.image_stack, [height_s, width_s], align_corners=True)
-
- # Smoothness.
- if self.smooth_weight > 0:
- for i in range(self.seq_length):
- # When computing minimum loss, use the depth map from the middle
- # frame only.
- if not self.compute_minimum_loss or i == self.middle_frame_index:
- disp_smoothing = self.disp[i][s]
- if self.depth_normalization:
- # Perform depth normalization, dividing by the mean.
- mean_disp = tf.reduce_mean(disp_smoothing, axis=[1, 2, 3],
- keep_dims=True)
- disp_input = disp_smoothing / mean_disp
- else:
- disp_input = disp_smoothing
- scaling_f = (1.0 if self.equal_weighting else 1.0 / (2**s))
- self.smooth_loss += scaling_f * self.depth_smoothness(
- disp_input, self.images[s][:, :, :, 3 * i:3 * (i + 1)])
-
- self.debug_all_warped_image_batches = []
- for i in range(self.seq_length):
- for j in range(self.seq_length):
- if i == j:
- continue
-
- # When computing minimum loss, only consider the middle frame as
- # target.
- if self.compute_minimum_loss and j != self.middle_frame_index:
- continue
- # We only consider adjacent frames, unless either
- # compute_minimum_loss is on (where the middle frame is matched with
- # all other frames) or exhaustive_mode is on (where all frames are
- # matched with each other).
- if (not self.compute_minimum_loss and not self.exhaustive_mode and
- abs(i - j) != 1):
- continue
-
- selected_scale = 0 if self.depth_upsampling else s
- source = self.images[selected_scale][:, :, :, 3 * i:3 * (i + 1)]
- target = self.images[selected_scale][:, :, :, 3 * j:3 * (j + 1)]
-
- if self.depth_upsampling:
- target_depth = self.depth_upsampled[j][s]
- else:
- target_depth = self.depth[j][s]
-
- key = '%d-%d' % (i, j)
-
- if self.handle_motion:
- # self.seg_stack of shape (B, H, W, 9).
- # target_depth corresponds to middle frame, of shape (B, H, W, 1).
-
- # Now incorporate the other warping results, performed according
- # to the object motion network's predictions.
- # self.object_masks batch_size elements of (N, H, W, 9).
- # self.object_masks_warped batch_size elements of (N, H, W, 9).
- # self.object_transforms batch_size elements of (N, 2, 6).
- self.all_batches = []
- for batch_s in range(self.batch_size):
- # To warp i into j, first take the base warping (this is the
- # full image i warped into j using only the egomotion estimate).
- base_warping = self.warped_seq[s][i][batch_s]
- transform_matrices_thisbatch = tf.map_fn(
- lambda transform: project.get_transform_mat(
- tf.expand_dims(transform, axis=0), i, j)[0],
- self.object_transforms[0][batch_s])
-
- def inverse_warp_wrapper(matrix):
- """Wrapper for inverse warping method."""
- warp_image, _ = (
- project.inverse_warp(
- tf.expand_dims(base_warping, axis=0),
- tf.expand_dims(target_depth[batch_s], axis=0),
- tf.expand_dims(matrix, axis=0),
- tf.expand_dims(self.intrinsic_mat[
- batch_s, selected_scale, :, :], axis=0),
- tf.expand_dims(self.intrinsic_mat_inv[
- batch_s, selected_scale, :, :], axis=0)))
- return warp_image
- warped_images_thisbatch = tf.map_fn(
- inverse_warp_wrapper, transform_matrices_thisbatch,
- dtype=tf.float32)
- warped_images_thisbatch = warped_images_thisbatch[:, 0, :, :, :]
- # warped_images_thisbatch is now of shape (N, H, W, 9).
-
- # Combine warped frames into a single one, using the object
- # masks. Result should be (1, 128, 416, 3).
- # Essentially, we here want to sum them all up, filtered by the
- # respective object masks.
- mask_base_valid_source = tf.equal(
- self.seg_stack[batch_s, :, :, i*3:(i+1)*3],
- tf.constant(0, dtype=tf.uint8))
- mask_base_valid_target = tf.equal(
- self.seg_stack[batch_s, :, :, j*3:(j+1)*3],
- tf.constant(0, dtype=tf.uint8))
- mask_valid = tf.logical_and(
- mask_base_valid_source, mask_base_valid_target)
- self.base_warping = base_warping * tf.to_float(mask_valid)
- background = tf.expand_dims(self.base_warping, axis=0)
- def construct_const_filter_tensor(obj_id):
- return tf.fill(
- dims=[self.img_height, self.img_width, 3],
- value=tf.sign(obj_id)) * tf.to_float(
- tf.equal(self.seg_stack[batch_s, :, :, 3:6],
- tf.cast(obj_id, dtype=tf.uint8)))
- filter_tensor = tf.map_fn(
- construct_const_filter_tensor,
- tf.to_float(self.object_ids[s][batch_s]))
- filter_tensor = tf.stack(filter_tensor, axis=0)
- objects_to_add = tf.reduce_sum(
- tf.multiply(warped_images_thisbatch, filter_tensor),
- axis=0, keepdims=True)
- combined = background + objects_to_add
- self.all_batches.append(combined)
- # Now of shape (B, 128, 416, 3).
- self.warped_image[s][key] = tf.concat(self.all_batches, axis=0)
-
- else:
- # Don't handle motion, classic model formulation.
- egomotion_mat_i_j = project.get_transform_mat(
- self.egomotion, i, j)
- # Inverse warp the source image to the target image frame for
- # photometric consistency loss.
- self.warped_image[s][key], self.warp_mask[s][key] = (
- project.inverse_warp(
- source,
- target_depth,
- egomotion_mat_i_j,
- self.intrinsic_mat[:, selected_scale, :, :],
- self.intrinsic_mat_inv[:, selected_scale, :, :]))
-
- # Reconstruction loss.
- self.warp_error[s][key] = tf.abs(self.warped_image[s][key] - target)
- if not self.compute_minimum_loss:
- self.reconstr_loss += tf.reduce_mean(
- self.warp_error[s][key] * self.warp_mask[s][key])
- # SSIM.
- if self.ssim_weight > 0:
- self.ssim_error[s][key] = self.ssim(self.warped_image[s][key],
- target)
- # TODO(rezama): This should be min_pool2d().
- if not self.compute_minimum_loss:
- ssim_mask = slim.avg_pool2d(self.warp_mask[s][key], 3, 1,
- 'VALID')
- self.ssim_loss += tf.reduce_mean(
- self.ssim_error[s][key] * ssim_mask)
-
- # If the minimum loss should be computed, the loss calculation has been
- # postponed until here.
- if self.compute_minimum_loss:
- for frame_index in range(self.middle_frame_index):
- key1 = '%d-%d' % (frame_index, self.middle_frame_index)
- key2 = '%d-%d' % (self.seq_length - frame_index - 1,
- self.middle_frame_index)
- logging.info('computing min error between %s and %s', key1, key2)
- min_error = tf.minimum(self.warp_error[s][key1],
- self.warp_error[s][key2])
- self.reconstr_loss += tf.reduce_mean(min_error)
- if self.ssim_weight > 0: # Also compute the minimum SSIM loss.
- min_error_ssim = tf.minimum(self.ssim_error[s][key1],
- self.ssim_error[s][key2])
- self.ssim_loss += tf.reduce_mean(min_error_ssim)
-
- # Build the total loss as composed of L1 reconstruction, SSIM, smoothing
- # and object size constraint loss as appropriate.
- self.reconstr_loss *= self.reconstr_weight
- self.total_loss = self.reconstr_loss
- if self.smooth_weight > 0:
- self.smooth_loss *= self.smooth_weight
- self.total_loss += self.smooth_loss
- if self.ssim_weight > 0:
- self.ssim_loss *= self.ssim_weight
- self.total_loss += self.ssim_loss
- if self.size_constraint_weight > 0:
- self.inf_loss *= self.size_constraint_weight
- self.total_loss += self.inf_loss
-
- def gradient_x(self, img):
- return img[:, :, :-1, :] - img[:, :, 1:, :]
-
- def gradient_y(self, img):
- return img[:, :-1, :, :] - img[:, 1:, :, :]
-
- def depth_smoothness(self, depth, img):
- """Computes image-aware depth smoothness loss."""
- depth_dx = self.gradient_x(depth)
- depth_dy = self.gradient_y(depth)
- image_dx = self.gradient_x(img)
- image_dy = self.gradient_y(img)
- weights_x = tf.exp(-tf.reduce_mean(tf.abs(image_dx), 3, keepdims=True))
- weights_y = tf.exp(-tf.reduce_mean(tf.abs(image_dy), 3, keepdims=True))
- smoothness_x = depth_dx * weights_x
- smoothness_y = depth_dy * weights_y
- return tf.reduce_mean(abs(smoothness_x)) + tf.reduce_mean(abs(smoothness_y))
-
- def ssim(self, x, y):
- """Computes a differentiable structured image similarity measure."""
- c1 = 0.01**2 # As defined in SSIM to stabilize div. by small denominator.
- c2 = 0.03**2
- mu_x = slim.avg_pool2d(x, 3, 1, 'VALID')
- mu_y = slim.avg_pool2d(y, 3, 1, 'VALID')
- sigma_x = slim.avg_pool2d(x**2, 3, 1, 'VALID') - mu_x**2
- sigma_y = slim.avg_pool2d(y**2, 3, 1, 'VALID') - mu_y**2
- sigma_xy = slim.avg_pool2d(x * y, 3, 1, 'VALID') - mu_x * mu_y
- ssim_n = (2 * mu_x * mu_y + c1) * (2 * sigma_xy + c2)
- ssim_d = (mu_x**2 + mu_y**2 + c1) * (sigma_x + sigma_y + c2)
- ssim = ssim_n / ssim_d
- return tf.clip_by_value((1 - ssim) / 2, 0, 1)
-
- def build_train_op(self):
- with tf.name_scope('train_op'):
- optim = tf.train.AdamOptimizer(self.learning_rate, self.beta1)
- self.train_op = slim.learning.create_train_op(self.total_loss, optim)
- self.global_step = tf.Variable(0, name='global_step', trainable=False)
- self.incr_global_step = tf.assign(
- self.global_step, self.global_step + 1)
-
- def build_summaries(self):
- """Adds scalar and image summaries for TensorBoard."""
- tf.summary.scalar('total_loss', self.total_loss)
- tf.summary.scalar('reconstr_loss', self.reconstr_loss)
- if self.smooth_weight > 0:
- tf.summary.scalar('smooth_loss', self.smooth_loss)
- if self.ssim_weight > 0:
- tf.summary.scalar('ssim_loss', self.ssim_loss)
- if self.icp_weight > 0:
- tf.summary.scalar('icp_transform_loss', self.icp_transform_loss)
- tf.summary.scalar('icp_residual_loss', self.icp_residual_loss)
-
- if self.size_constraint_weight > 0:
- tf.summary.scalar('inf_loss', self.inf_loss)
- tf.summary.histogram('global_scale_var', self.global_scale_var)
-
- if self.handle_motion:
- for s in range(NUM_SCALES):
- for batch_s in range(self.batch_size):
- whole_strip = tf.concat([self.warped_seq[s][0][batch_s],
- self.warped_seq[s][1][batch_s],
- self.warped_seq[s][2][batch_s]], axis=1)
- tf.summary.image('base_warp_batch%s_scale%s' % (batch_s, s),
- tf.expand_dims(whole_strip, axis=0))
-
- whole_strip_input = tf.concat(
- [self.inputs_objectmotion_net[s][batch_s][:, :, :, 0:3],
- self.inputs_objectmotion_net[s][batch_s][:, :, :, 3:6],
- self.inputs_objectmotion_net[s][batch_s][:, :, :, 6:9]], axis=2)
- tf.summary.image('input_objectmotion_batch%s_scale%s' % (batch_s, s),
- whole_strip_input) # (B, H, 3*W, 3)
-
- for batch_s in range(self.batch_size):
- whole_strip = tf.concat([self.base_input_masked[batch_s, :, :, 0:3],
- self.base_input_masked[batch_s, :, :, 3:6],
- self.base_input_masked[batch_s, :, :, 6:9]],
- axis=1)
- tf.summary.image('input_egomotion_batch%s' % batch_s,
- tf.expand_dims(whole_strip, axis=0))
-
- # Show transform predictions (of all objects).
- for batch_s in range(self.batch_size):
- for i in range(self.seq_length - 1):
- # self.object_transforms contains batch_size elements of (N, 2, 6).
- tf.summary.histogram('batch%d_tx%d' % (batch_s, i),
- self.object_transforms[0][batch_s][:, i, 0])
- tf.summary.histogram('batch%d_ty%d' % (batch_s, i),
- self.object_transforms[0][batch_s][:, i, 1])
- tf.summary.histogram('batch%d_tz%d' % (batch_s, i),
- self.object_transforms[0][batch_s][:, i, 2])
- tf.summary.histogram('batch%d_rx%d' % (batch_s, i),
- self.object_transforms[0][batch_s][:, i, 3])
- tf.summary.histogram('batch%d_ry%d' % (batch_s, i),
- self.object_transforms[0][batch_s][:, i, 4])
- tf.summary.histogram('batch%d_rz%d' % (batch_s, i),
- self.object_transforms[0][batch_s][:, i, 5])
-
- for i in range(self.seq_length - 1):
- tf.summary.histogram('tx%d' % i, self.egomotion[:, i, 0])
- tf.summary.histogram('ty%d' % i, self.egomotion[:, i, 1])
- tf.summary.histogram('tz%d' % i, self.egomotion[:, i, 2])
- tf.summary.histogram('rx%d' % i, self.egomotion[:, i, 3])
- tf.summary.histogram('ry%d' % i, self.egomotion[:, i, 4])
- tf.summary.histogram('rz%d' % i, self.egomotion[:, i, 5])
-
- for s in range(NUM_SCALES):
- for i in range(self.seq_length):
- tf.summary.image('scale%d_image%d' % (s, i),
- self.images[s][:, :, :, 3 * i:3 * (i + 1)])
- if i in self.depth:
- tf.summary.histogram('scale%d_depth%d' % (s, i), self.depth[i][s])
- tf.summary.histogram('scale%d_disp%d' % (s, i), self.disp[i][s])
- tf.summary.image('scale%d_disparity%d' % (s, i), self.disp[i][s])
-
- for key in self.warped_image[s]:
- tf.summary.image('scale%d_warped_image%s' % (s, key),
- self.warped_image[s][key])
- tf.summary.image('scale%d_warp_error%s' % (s, key),
- self.warp_error[s][key])
- if self.ssim_weight > 0:
- tf.summary.image('scale%d_ssim_error%s' % (s, key),
- self.ssim_error[s][key])
- if self.icp_weight > 0:
- tf.summary.image('scale%d_icp_residual%s' % (s, key),
- self.icp_residual[s][key])
- transform = self.icp_transform[s][key]
- tf.summary.histogram('scale%d_icp_tx%s' % (s, key), transform[:, 0])
- tf.summary.histogram('scale%d_icp_ty%s' % (s, key), transform[:, 1])
- tf.summary.histogram('scale%d_icp_tz%s' % (s, key), transform[:, 2])
- tf.summary.histogram('scale%d_icp_rx%s' % (s, key), transform[:, 3])
- tf.summary.histogram('scale%d_icp_ry%s' % (s, key), transform[:, 4])
- tf.summary.histogram('scale%d_icp_rz%s' % (s, key), transform[:, 5])
-
- def build_depth_test_graph(self):
- """Builds depth model reading from placeholders."""
- with tf.variable_scope('depth_prediction'):
- input_image = tf.placeholder(
- tf.float32, [self.batch_size, self.img_height, self.img_width, 3],
- name='raw_input')
- self.input_image = input_image
- if self.imagenet_norm:
- input_image = (input_image - reader.IMAGENET_MEAN) / reader.IMAGENET_SD
- est_disp, _ = nets.disp_net(architecture=self.architecture,
- image=input_image,
- use_skip=self.use_skip,
- weight_reg=self.weight_reg,
- is_training=True)
- est_depth = 1.0 / est_disp[0]
- self.est_depth = est_depth
-
- def build_egomotion_test_graph(self):
- """Builds egomotion model reading from placeholders."""
- input_image_stack = tf.placeholder(
- tf.float32,
- [1, self.img_height, self.img_width, self.seq_length * 3],
- name='raw_input')
- input_bottleneck_stack = None
-
- if self.imagenet_norm:
- im_mean = tf.tile(
- tf.constant(reader.IMAGENET_MEAN), multiples=[self.seq_length])
- im_sd = tf.tile(
- tf.constant(reader.IMAGENET_SD), multiples=[self.seq_length])
- input_image_stack = (input_image_stack - im_mean) / im_sd
-
- if self.joint_encoder:
- # Pre-compute embeddings here.
- with tf.variable_scope('depth_prediction', reuse=True):
- input_bottleneck_stack = []
- encoder_selected = nets.encoder(self.architecture)
- for i in range(self.seq_length):
- input_image = input_image_stack[:, :, :, i * 3:(i + 1) * 3]
- tf.get_variable_scope().reuse_variables()
- embedding, _ = encoder_selected(
- target_image=input_image,
- weight_reg=self.weight_reg,
- is_training=True)
- input_bottleneck_stack.append(embedding)
- input_bottleneck_stack = tf.concat(input_bottleneck_stack, axis=3)
-
- with tf.variable_scope('egomotion_prediction'):
- est_egomotion = nets.egomotion_net(
- image_stack=input_image_stack,
- disp_bottleneck_stack=input_bottleneck_stack,
- joint_encoder=self.joint_encoder,
- seq_length=self.seq_length,
- weight_reg=self.weight_reg)
- self.input_image_stack = input_image_stack
- self.est_egomotion = est_egomotion
-
- def build_objectmotion_test_graph(self):
- """Builds egomotion model reading from placeholders."""
- input_image_stack_om = tf.placeholder(
- tf.float32,
- [1, self.img_height, self.img_width, self.seq_length * 3],
- name='raw_input')
-
- if self.imagenet_norm:
- im_mean = tf.tile(
- tf.constant(reader.IMAGENET_MEAN), multiples=[self.seq_length])
- im_sd = tf.tile(
- tf.constant(reader.IMAGENET_SD), multiples=[self.seq_length])
- input_image_stack_om = (input_image_stack_om - im_mean) / im_sd
-
- with tf.variable_scope('objectmotion_prediction'):
- est_objectmotion = nets.objectmotion_net(
- image_stack=input_image_stack_om,
- disp_bottleneck_stack=None,
- joint_encoder=self.joint_encoder,
- seq_length=self.seq_length,
- weight_reg=self.weight_reg)
- self.input_image_stack_om = input_image_stack_om
- self.est_objectmotion = est_objectmotion
-
- def inference_depth(self, inputs, sess):
- return sess.run(self.est_depth, feed_dict={self.input_image: inputs})
-
- def inference_egomotion(self, inputs, sess):
- return sess.run(
- self.est_egomotion, feed_dict={self.input_image_stack: inputs})
-
- def inference_objectmotion(self, inputs, sess):
- return sess.run(
- self.est_objectmotion, feed_dict={self.input_image_stack_om: inputs})
diff --git a/research/struct2depth/nets.py b/research/struct2depth/nets.py
deleted file mode 100644
index 1cec1b36f3c44d3eaf11451ca3ae4d92839d5886..0000000000000000000000000000000000000000
--- a/research/struct2depth/nets.py
+++ /dev/null
@@ -1,525 +0,0 @@
-
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Depth and Ego-Motion networks."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import numpy as np
-import tensorflow as tf
-slim = tf.contrib.slim
-
-SIMPLE = 'simple'
-RESNET = 'resnet'
-ARCHITECTURES = [SIMPLE, RESNET]
-
-SCALE_TRANSLATION = 0.001
-SCALE_ROTATION = 0.01
-
-# Disparity (inverse depth) values range from 0.01 to 10. Note that effectively,
-# this is undone if depth normalization is used, which scales the values to
-# have a mean of 1.
-DISP_SCALING = 10
-MIN_DISP = 0.01
-WEIGHT_DECAY_KEY = 'WEIGHT_DECAY'
-EGOMOTION_VEC_SIZE = 6
-
-
-def egomotion_net(image_stack, disp_bottleneck_stack, joint_encoder, seq_length,
- weight_reg):
- """Predict ego-motion vectors from a stack of frames or embeddings.
-
- Args:
- image_stack: Input tensor with shape [B, h, w, seq_length * 3] in order.
- disp_bottleneck_stack: Input tensor with shape [B, h_hidden, w_hidden,
- seq_length * c_hidden] in order.
- joint_encoder: Determines if the same encoder is used for computing the
- bottleneck layer of both the egomotion and the depth prediction
- network. If enabled, disp_bottleneck_stack is used as input, and the
- encoding steps are skipped. If disabled, a separate encoder is defined
- on image_stack.
- seq_length: The sequence length used.
- weight_reg: The amount of weight regularization.
-
- Returns:
- Egomotion vectors with shape [B, seq_length - 1, 6].
- """
- num_egomotion_vecs = seq_length - 1
- with tf.variable_scope('pose_exp_net') as sc:
- end_points_collection = sc.original_name_scope + '_end_points'
- with slim.arg_scope([slim.conv2d, slim.conv2d_transpose],
- normalizer_fn=None,
- weights_regularizer=slim.l2_regularizer(weight_reg),
- normalizer_params=None,
- activation_fn=tf.nn.relu,
- outputs_collections=end_points_collection):
- if not joint_encoder:
- # Define separate encoder. If sharing, we can skip the encoding step,
- # as the bottleneck layer will already be passed as input.
- cnv1 = slim.conv2d(image_stack, 16, [7, 7], stride=2, scope='cnv1')
- cnv2 = slim.conv2d(cnv1, 32, [5, 5], stride=2, scope='cnv2')
- cnv3 = slim.conv2d(cnv2, 64, [3, 3], stride=2, scope='cnv3')
- cnv4 = slim.conv2d(cnv3, 128, [3, 3], stride=2, scope='cnv4')
- cnv5 = slim.conv2d(cnv4, 256, [3, 3], stride=2, scope='cnv5')
-
- with tf.variable_scope('pose'):
- inputs = disp_bottleneck_stack if joint_encoder else cnv5
- cnv6 = slim.conv2d(inputs, 256, [3, 3], stride=2, scope='cnv6')
- cnv7 = slim.conv2d(cnv6, 256, [3, 3], stride=2, scope='cnv7')
- pred_channels = EGOMOTION_VEC_SIZE * num_egomotion_vecs
- egomotion_pred = slim.conv2d(cnv7, pred_channels, [1, 1], scope='pred',
- stride=1, normalizer_fn=None,
- activation_fn=None)
- egomotion_avg = tf.reduce_mean(egomotion_pred, [1, 2])
- egomotion_res = tf.reshape(
- egomotion_avg, [-1, num_egomotion_vecs, EGOMOTION_VEC_SIZE])
- # Tinghui found that scaling by a small constant facilitates training.
- egomotion_scaled = tf.concat([egomotion_res[:, 0:3] * SCALE_TRANSLATION,
- egomotion_res[:, 3:6] * SCALE_ROTATION],
- axis=1)
- return egomotion_scaled
-
-
-def objectmotion_net(image_stack, disp_bottleneck_stack, joint_encoder,
- seq_length, weight_reg):
- """Predict object-motion vectors from a stack of frames or embeddings.
-
- Args:
- image_stack: Input tensor with shape [B, h, w, seq_length * 3] in order.
- disp_bottleneck_stack: Input tensor with shape [B, h_hidden, w_hidden,
- seq_length * c_hidden] in order.
- joint_encoder: Determines if the same encoder is used for computing the
- bottleneck layer of both the egomotion and the depth prediction
- network. If enabled, disp_bottleneck_stack is used as input, and the
- encoding steps are skipped. If disabled, a separate encoder is defined
- on image_stack.
- seq_length: The sequence length used.
- weight_reg: The amount of weight regularization.
-
- Returns:
- Egomotion vectors with shape [B, seq_length - 1, 6].
- """
- num_egomotion_vecs = seq_length - 1
- with tf.variable_scope('pose_exp_net') as sc:
- end_points_collection = sc.original_name_scope + '_end_points'
- with slim.arg_scope([slim.conv2d, slim.conv2d_transpose],
- normalizer_fn=None,
- weights_regularizer=slim.l2_regularizer(weight_reg),
- normalizer_params=None,
- activation_fn=tf.nn.relu,
- outputs_collections=end_points_collection):
- if not joint_encoder:
- # Define separate encoder. If sharing, we can skip the encoding step,
- # as the bottleneck layer will already be passed as input.
- cnv1 = slim.conv2d(image_stack, 16, [7, 7], stride=2, scope='cnv1')
- cnv2 = slim.conv2d(cnv1, 32, [5, 5], stride=2, scope='cnv2')
- cnv3 = slim.conv2d(cnv2, 64, [3, 3], stride=2, scope='cnv3')
- cnv4 = slim.conv2d(cnv3, 128, [3, 3], stride=2, scope='cnv4')
- cnv5 = slim.conv2d(cnv4, 256, [3, 3], stride=2, scope='cnv5')
-
- with tf.variable_scope('pose'):
- inputs = disp_bottleneck_stack if joint_encoder else cnv5
- cnv6 = slim.conv2d(inputs, 256, [3, 3], stride=2, scope='cnv6')
- cnv7 = slim.conv2d(cnv6, 256, [3, 3], stride=2, scope='cnv7')
- pred_channels = EGOMOTION_VEC_SIZE * num_egomotion_vecs
- egomotion_pred = slim.conv2d(cnv7, pred_channels, [1, 1], scope='pred',
- stride=1, normalizer_fn=None,
- activation_fn=None)
- egomotion_avg = tf.reduce_mean(egomotion_pred, [1, 2])
- egomotion_res = tf.reshape(
- egomotion_avg, [-1, num_egomotion_vecs, EGOMOTION_VEC_SIZE])
- # Tinghui found that scaling by a small constant facilitates training.
- egomotion_scaled = tf.concat([egomotion_res[:, 0:3] * SCALE_TRANSLATION,
- egomotion_res[:, 3:6] * SCALE_ROTATION],
- axis=1)
- return egomotion_scaled
-
-
-def disp_net(architecture, image, use_skip, weight_reg, is_training):
- """Defines an encoder-decoder architecture for depth prediction."""
- if architecture not in ARCHITECTURES:
- raise ValueError('Unknown architecture.')
- encoder_selected = encoder(architecture)
- decoder_selected = decoder(architecture)
-
- # Encode image.
- bottleneck, skip_connections = encoder_selected(image, weight_reg,
- is_training)
- # Decode to depth.
- multiscale_disps_i = decoder_selected(target_image=image,
- bottleneck=bottleneck,
- weight_reg=weight_reg,
- use_skip=use_skip,
- skip_connections=skip_connections)
- return multiscale_disps_i, bottleneck
-
-
-def encoder(architecture):
- return encoder_resnet if architecture == RESNET else encoder_simple
-
-
-def decoder(architecture):
- return decoder_resnet if architecture == RESNET else decoder_simple
-
-
-def encoder_simple(target_image, weight_reg, is_training):
- """Defines the old encoding architecture."""
- del is_training
- with slim.arg_scope([slim.conv2d],
- normalizer_fn=None,
- normalizer_params=None,
- weights_regularizer=slim.l2_regularizer(weight_reg),
- activation_fn=tf.nn.relu):
- # Define (joint) encoder.
- cnv1 = slim.conv2d(target_image, 32, [7, 7], stride=2, scope='cnv1')
- cnv1b = slim.conv2d(cnv1, 32, [7, 7], stride=1, scope='cnv1b')
- cnv2 = slim.conv2d(cnv1b, 64, [5, 5], stride=2, scope='cnv2')
- cnv2b = slim.conv2d(cnv2, 64, [5, 5], stride=1, scope='cnv2b')
- cnv3 = slim.conv2d(cnv2b, 128, [3, 3], stride=2, scope='cnv3')
- cnv3b = slim.conv2d(cnv3, 128, [3, 3], stride=1, scope='cnv3b')
- cnv4 = slim.conv2d(cnv3b, 256, [3, 3], stride=2, scope='cnv4')
- cnv4b = slim.conv2d(cnv4, 256, [3, 3], stride=1, scope='cnv4b')
- cnv5 = slim.conv2d(cnv4b, 512, [3, 3], stride=2, scope='cnv5')
- cnv5b = slim.conv2d(cnv5, 512, [3, 3], stride=1, scope='cnv5b')
- cnv6 = slim.conv2d(cnv5b, 512, [3, 3], stride=2, scope='cnv6')
- cnv6b = slim.conv2d(cnv6, 512, [3, 3], stride=1, scope='cnv6b')
- cnv7 = slim.conv2d(cnv6b, 512, [3, 3], stride=2, scope='cnv7')
- cnv7b = slim.conv2d(cnv7, 512, [3, 3], stride=1, scope='cnv7b')
- return cnv7b, (cnv6b, cnv5b, cnv4b, cnv3b, cnv2b, cnv1b)
-
-
-def decoder_simple(target_image, bottleneck, weight_reg, use_skip,
- skip_connections):
- """Defines the old depth decoder architecture."""
- h = target_image.get_shape()[1].value
- w = target_image.get_shape()[2].value
- (cnv6b, cnv5b, cnv4b, cnv3b, cnv2b, cnv1b) = skip_connections
- with slim.arg_scope([slim.conv2d, slim.conv2d_transpose],
- normalizer_fn=None,
- normalizer_params=None,
- weights_regularizer=slim.l2_regularizer(weight_reg),
- activation_fn=tf.nn.relu):
- up7 = slim.conv2d_transpose(bottleneck, 512, [3, 3], stride=2,
- scope='upcnv7')
- up7 = _resize_like(up7, cnv6b)
- if use_skip:
- i7_in = tf.concat([up7, cnv6b], axis=3)
- else:
- i7_in = up7
- icnv7 = slim.conv2d(i7_in, 512, [3, 3], stride=1, scope='icnv7')
-
- up6 = slim.conv2d_transpose(icnv7, 512, [3, 3], stride=2, scope='upcnv6')
- up6 = _resize_like(up6, cnv5b)
- if use_skip:
- i6_in = tf.concat([up6, cnv5b], axis=3)
- else:
- i6_in = up6
- icnv6 = slim.conv2d(i6_in, 512, [3, 3], stride=1, scope='icnv6')
-
- up5 = slim.conv2d_transpose(icnv6, 256, [3, 3], stride=2, scope='upcnv5')
- up5 = _resize_like(up5, cnv4b)
- if use_skip:
- i5_in = tf.concat([up5, cnv4b], axis=3)
- else:
- i5_in = up5
- icnv5 = slim.conv2d(i5_in, 256, [3, 3], stride=1, scope='icnv5')
-
- up4 = slim.conv2d_transpose(icnv5, 128, [3, 3], stride=2, scope='upcnv4')
- up4 = _resize_like(up4, cnv3b)
- if use_skip:
- i4_in = tf.concat([up4, cnv3b], axis=3)
- else:
- i4_in = up4
- icnv4 = slim.conv2d(i4_in, 128, [3, 3], stride=1, scope='icnv4')
- disp4 = (slim.conv2d(icnv4, 1, [3, 3], stride=1, activation_fn=tf.sigmoid,
- normalizer_fn=None, scope='disp4')
- * DISP_SCALING + MIN_DISP)
- disp4_up = tf.image.resize_bilinear(disp4, [np.int(h / 4), np.int(w / 4)],
- align_corners=True)
-
- up3 = slim.conv2d_transpose(icnv4, 64, [3, 3], stride=2, scope='upcnv3')
- up3 = _resize_like(up3, cnv2b)
- if use_skip:
- i3_in = tf.concat([up3, cnv2b, disp4_up], axis=3)
- else:
- i3_in = tf.concat([up3, disp4_up])
- icnv3 = slim.conv2d(i3_in, 64, [3, 3], stride=1, scope='icnv3')
- disp3 = (slim.conv2d(icnv3, 1, [3, 3], stride=1, activation_fn=tf.sigmoid,
- normalizer_fn=None, scope='disp3')
- * DISP_SCALING + MIN_DISP)
- disp3_up = tf.image.resize_bilinear(disp3, [np.int(h / 2), np.int(w / 2)],
- align_corners=True)
-
- up2 = slim.conv2d_transpose(icnv3, 32, [3, 3], stride=2, scope='upcnv2')
- up2 = _resize_like(up2, cnv1b)
- if use_skip:
- i2_in = tf.concat([up2, cnv1b, disp3_up], axis=3)
- else:
- i2_in = tf.concat([up2, disp3_up])
- icnv2 = slim.conv2d(i2_in, 32, [3, 3], stride=1, scope='icnv2')
- disp2 = (slim.conv2d(icnv2, 1, [3, 3], stride=1, activation_fn=tf.sigmoid,
- normalizer_fn=None, scope='disp2')
- * DISP_SCALING + MIN_DISP)
- disp2_up = tf.image.resize_bilinear(disp2, [h, w], align_corners=True)
-
- up1 = slim.conv2d_transpose(icnv2, 16, [3, 3], stride=2, scope='upcnv1')
- i1_in = tf.concat([up1, disp2_up], axis=3)
- icnv1 = slim.conv2d(i1_in, 16, [3, 3], stride=1, scope='icnv1')
- disp1 = (slim.conv2d(icnv1, 1, [3, 3], stride=1, activation_fn=tf.sigmoid,
- normalizer_fn=None, scope='disp1')
- * DISP_SCALING + MIN_DISP)
- return [disp1, disp2, disp3, disp4]
-
-
-def encoder_resnet(target_image, weight_reg, is_training):
- """Defines a ResNet18-based encoding architecture.
-
- This implementation follows Juyong Kim's implementation of ResNet18 on GitHub:
- https://github.com/dalgu90/resnet-18-tensorflow
-
- Args:
- target_image: Input tensor with shape [B, h, w, 3] to encode.
- weight_reg: Parameter ignored.
- is_training: Whether the model is being trained or not.
-
- Returns:
- Tuple of tensors, with the first being the bottleneck layer as tensor of
- size [B, h_hid, w_hid, c_hid], and others being intermediate layers
- for building skip-connections.
- """
- del weight_reg
- encoder_filters = [64, 64, 128, 256, 512]
- stride = 2
-
- # conv1
- with tf.variable_scope('conv1'):
- x = _conv(target_image, 7, encoder_filters[0], stride)
- x = _bn(x, is_train=is_training)
- econv1 = _relu(x)
- x = tf.nn.max_pool(econv1, [1, 3, 3, 1], [1, 2, 2, 1], 'SAME')
-
- # conv2_x
- x = _residual_block(x, is_training, name='conv2_1')
- econv2 = _residual_block(x, is_training, name='conv2_2')
-
- # conv3_x
- x = _residual_block_first(econv2, is_training, encoder_filters[2], stride,
- name='conv3_1')
- econv3 = _residual_block(x, is_training, name='conv3_2')
-
- # conv4_x
- x = _residual_block_first(econv3, is_training, encoder_filters[3], stride,
- name='conv4_1')
- econv4 = _residual_block(x, is_training, name='conv4_2')
-
- # conv5_x
- x = _residual_block_first(econv4, is_training, encoder_filters[4], stride,
- name='conv5_1')
- econv5 = _residual_block(x, is_training, name='conv5_2')
- return econv5, (econv4, econv3, econv2, econv1)
-
-
-def decoder_resnet(target_image, bottleneck, weight_reg, use_skip,
- skip_connections):
- """Defines the depth decoder architecture.
-
- Args:
- target_image: The original encoder input tensor with shape [B, h, w, 3].
- Just the shape information is used here.
- bottleneck: Bottleneck layer to be decoded.
- weight_reg: The amount of weight regularization.
- use_skip: Whether the passed skip connections econv1, econv2, econv3 and
- econv4 should be used.
- skip_connections: Tensors for building skip-connections.
-
- Returns:
- Disparities at 4 different scales.
- """
- (econv4, econv3, econv2, econv1) = skip_connections
- decoder_filters = [16, 32, 64, 128, 256]
- default_pad = tf.constant([[0, 0], [1, 1], [1, 1], [0, 0]])
- reg = slim.l2_regularizer(weight_reg) if weight_reg > 0.0 else None
- with slim.arg_scope([slim.conv2d, slim.conv2d_transpose],
- normalizer_fn=None,
- normalizer_params=None,
- activation_fn=tf.nn.relu,
- weights_regularizer=reg):
- upconv5 = slim.conv2d_transpose(bottleneck, decoder_filters[4], [3, 3],
- stride=2, scope='upconv5')
- upconv5 = _resize_like(upconv5, econv4)
- if use_skip:
- i5_in = tf.concat([upconv5, econv4], axis=3)
- else:
- i5_in = upconv5
- i5_in = tf.pad(i5_in, default_pad, mode='REFLECT')
- iconv5 = slim.conv2d(i5_in, decoder_filters[4], [3, 3], stride=1,
- scope='iconv5', padding='VALID')
-
- upconv4 = slim.conv2d_transpose(iconv5, decoder_filters[3], [3, 3],
- stride=2, scope='upconv4')
- upconv4 = _resize_like(upconv4, econv3)
- if use_skip:
- i4_in = tf.concat([upconv4, econv3], axis=3)
- else:
- i4_in = upconv4
- i4_in = tf.pad(i4_in, default_pad, mode='REFLECT')
- iconv4 = slim.conv2d(i4_in, decoder_filters[3], [3, 3], stride=1,
- scope='iconv4', padding='VALID')
-
- disp4_input = tf.pad(iconv4, default_pad, mode='REFLECT')
- disp4 = (slim.conv2d(disp4_input, 1, [3, 3], stride=1,
- activation_fn=tf.sigmoid, normalizer_fn=None,
- scope='disp4', padding='VALID')
- * DISP_SCALING + MIN_DISP)
-
- upconv3 = slim.conv2d_transpose(iconv4, decoder_filters[2], [3, 3],
- stride=2, scope='upconv3')
- upconv3 = _resize_like(upconv3, econv2)
- if use_skip:
- i3_in = tf.concat([upconv3, econv2], axis=3)
- else:
- i3_in = upconv3
- i3_in = tf.pad(i3_in, default_pad, mode='REFLECT')
- iconv3 = slim.conv2d(i3_in, decoder_filters[2], [3, 3], stride=1,
- scope='iconv3', padding='VALID')
- disp3_input = tf.pad(iconv3, default_pad, mode='REFLECT')
- disp3 = (slim.conv2d(disp3_input, 1, [3, 3], stride=1,
- activation_fn=tf.sigmoid, normalizer_fn=None,
- scope='disp3', padding='VALID')
- * DISP_SCALING + MIN_DISP)
-
- upconv2 = slim.conv2d_transpose(iconv3, decoder_filters[1], [3, 3],
- stride=2, scope='upconv2')
- upconv2 = _resize_like(upconv2, econv1)
- if use_skip:
- i2_in = tf.concat([upconv2, econv1], axis=3)
- else:
- i2_in = upconv2
- i2_in = tf.pad(i2_in, default_pad, mode='REFLECT')
- iconv2 = slim.conv2d(i2_in, decoder_filters[1], [3, 3], stride=1,
- scope='iconv2', padding='VALID')
- disp2_input = tf.pad(iconv2, default_pad, mode='REFLECT')
- disp2 = (slim.conv2d(disp2_input, 1, [3, 3], stride=1,
- activation_fn=tf.sigmoid, normalizer_fn=None,
- scope='disp2', padding='VALID')
- * DISP_SCALING + MIN_DISP)
-
- upconv1 = slim.conv2d_transpose(iconv2, decoder_filters[0], [3, 3],
- stride=2, scope='upconv1')
- upconv1 = _resize_like(upconv1, target_image)
- upconv1 = tf.pad(upconv1, default_pad, mode='REFLECT')
- iconv1 = slim.conv2d(upconv1, decoder_filters[0], [3, 3], stride=1,
- scope='iconv1', padding='VALID')
- disp1_input = tf.pad(iconv1, default_pad, mode='REFLECT')
- disp1 = (slim.conv2d(disp1_input, 1, [3, 3], stride=1,
- activation_fn=tf.sigmoid, normalizer_fn=None,
- scope='disp1', padding='VALID')
- * DISP_SCALING + MIN_DISP)
-
- return [disp1, disp2, disp3, disp4]
-
-
-def _residual_block_first(x, is_training, out_channel, strides, name='unit'):
- """Helper function for defining ResNet architecture."""
- in_channel = x.get_shape().as_list()[-1]
- with tf.variable_scope(name):
- # Shortcut connection
- if in_channel == out_channel:
- if strides == 1:
- shortcut = tf.identity(x)
- else:
- shortcut = tf.nn.max_pool(x, [1, strides, strides, 1],
- [1, strides, strides, 1], 'VALID')
- else:
- shortcut = _conv(x, 1, out_channel, strides, name='shortcut')
- # Residual
- x = _conv(x, 3, out_channel, strides, name='conv_1')
- x = _bn(x, is_train=is_training, name='bn_1')
- x = _relu(x, name='relu_1')
- x = _conv(x, 3, out_channel, 1, name='conv_2')
- x = _bn(x, is_train=is_training, name='bn_2')
- # Merge
- x = x + shortcut
- x = _relu(x, name='relu_2')
- return x
-
-
-def _residual_block(x, is_training, input_q=None, output_q=None, name='unit'):
- """Helper function for defining ResNet architecture."""
- num_channel = x.get_shape().as_list()[-1]
- with tf.variable_scope(name):
- shortcut = x # Shortcut connection
- # Residual
- x = _conv(x, 3, num_channel, 1, input_q=input_q, output_q=output_q,
- name='conv_1')
- x = _bn(x, is_train=is_training, name='bn_1')
- x = _relu(x, name='relu_1')
- x = _conv(x, 3, num_channel, 1, input_q=output_q, output_q=output_q,
- name='conv_2')
- x = _bn(x, is_train=is_training, name='bn_2')
- # Merge
- x = x + shortcut
- x = _relu(x, name='relu_2')
- return x
-
-
-def _conv(x, filter_size, out_channel, stride, pad='SAME', input_q=None,
- output_q=None, name='conv'):
- """Helper function for defining ResNet architecture."""
- if (input_q is None) ^ (output_q is None):
- raise ValueError('Input/Output splits are not correctly given.')
-
- in_shape = x.get_shape()
- with tf.variable_scope(name):
- # Main operation: conv2d
- with tf.device('/CPU:0'):
- kernel = tf.get_variable(
- 'kernel', [filter_size, filter_size, in_shape[3], out_channel],
- tf.float32, initializer=tf.random_normal_initializer(
- stddev=np.sqrt(2.0/filter_size/filter_size/out_channel)))
- if kernel not in tf.get_collection(WEIGHT_DECAY_KEY):
- tf.add_to_collection(WEIGHT_DECAY_KEY, kernel)
- conv = tf.nn.conv2d(x, kernel, [1, stride, stride, 1], pad)
- return conv
-
-
-def _bn(x, is_train, name='bn'):
- """Helper function for defining ResNet architecture."""
- bn = tf.layers.batch_normalization(x, training=is_train, name=name)
- return bn
-
-
-def _relu(x, name=None, leakness=0.0):
- """Helper function for defining ResNet architecture."""
- if leakness > 0.0:
- name = 'lrelu' if name is None else name
- return tf.maximum(x, x*leakness, name='lrelu')
- else:
- name = 'relu' if name is None else name
- return tf.nn.relu(x, name='relu')
-
-
-def _resize_like(inputs, ref):
- i_h, i_w = inputs.get_shape()[1], inputs.get_shape()[2]
- r_h, r_w = ref.get_shape()[1], ref.get_shape()[2]
- if i_h == r_h and i_w == r_w:
- return inputs
- else:
- # TODO(casser): Other interpolation methods could be explored here.
- return tf.image.resize_bilinear(inputs, [r_h.value, r_w.value],
- align_corners=True)
diff --git a/research/struct2depth/optimize.py b/research/struct2depth/optimize.py
deleted file mode 100644
index becb3ab69f29dfb9dabe5e1534bd1d960f6037cb..0000000000000000000000000000000000000000
--- a/research/struct2depth/optimize.py
+++ /dev/null
@@ -1,383 +0,0 @@
-
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Applies online refinement while running inference.
-
-Instructions: Run static inference first before calling this script. Make sure
-to point output_dir to the same folder where static inference results were
-saved previously.
-
-For example use, please refer to README.
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import datetime
-import os
-import random
-from absl import app
-from absl import flags
-from absl import logging
-import numpy as np
-import tensorflow as tf
-
-import model
-import nets
-import reader
-import util
-
-gfile = tf.gfile
-SAVE_EVERY = 1 # Defines the interval that predictions should be saved at.
-SAVE_PREVIEWS = True # If set, while save image previews of depth predictions.
-FIXED_SEED = 8964 # Fixed seed for repeatability.
-
-flags.DEFINE_string('output_dir', None, 'Directory to store predictions. '
- 'Assumes that regular inference has been executed before '
- 'and results were stored in this folder.')
-flags.DEFINE_string('data_dir', None, 'Folder pointing to preprocessed '
- 'triplets to fine-tune on.')
-flags.DEFINE_string('triplet_list_file', None, 'Text file containing paths to '
- 'image files to process. Paths should be relative with '
- 'respect to the list file location. Every line should be '
- 'of the form [input_folder_name] [input_frame_num] '
- '[output_path], where [output_path] is optional to specify '
- 'a different path to store the prediction.')
-flags.DEFINE_string('triplet_list_file_remains', None, 'Optional text file '
- 'containing relative paths to image files which should not '
- 'be fine-tuned, e.g. because of missing adjacent frames. '
- 'For all files listed, the static prediction will be '
- 'copied instead. File can be empty. If not, every line '
- 'should be of the form [input_folder_name] '
- '[input_frame_num] [output_path], where [output_path] is '
- 'optional to specify a different path to take and store '
- 'the unrefined prediction from/to.')
-flags.DEFINE_string('model_ckpt', None, 'Model checkpoint to optimize.')
-flags.DEFINE_string('ft_name', '', 'Optional prefix for temporary files.')
-flags.DEFINE_string('file_extension', 'png', 'Image data file extension.')
-flags.DEFINE_float('learning_rate', 0.0001, 'Adam learning rate.')
-flags.DEFINE_float('beta1', 0.9, 'Adam momentum.')
-flags.DEFINE_float('reconstr_weight', 0.85, 'Frame reconstruction loss weight.')
-flags.DEFINE_float('ssim_weight', 0.15, 'SSIM loss weight.')
-flags.DEFINE_float('smooth_weight', 0.01, 'Smoothness loss weight.')
-flags.DEFINE_float('icp_weight', 0.0, 'ICP loss weight.')
-flags.DEFINE_float('size_constraint_weight', 0.0005, 'Weight of the object '
- 'size constraint loss. Use only with motion handling.')
-flags.DEFINE_integer('batch_size', 1, 'The size of a sample batch')
-flags.DEFINE_integer('img_height', 128, 'Input frame height.')
-flags.DEFINE_integer('img_width', 416, 'Input frame width.')
-flags.DEFINE_integer('seq_length', 3, 'Number of frames in sequence.')
-flags.DEFINE_enum('architecture', nets.RESNET, nets.ARCHITECTURES,
- 'Defines the architecture to use for the depth prediction '
- 'network. Defaults to ResNet-based encoder and accompanying '
- 'decoder.')
-flags.DEFINE_boolean('imagenet_norm', True, 'Whether to normalize the input '
- 'images channel-wise so that they match the distribution '
- 'most ImageNet-models were trained on.')
-flags.DEFINE_float('weight_reg', 0.05, 'The amount of weight regularization to '
- 'apply. This has no effect on the ResNet-based encoder '
- 'architecture.')
-flags.DEFINE_boolean('exhaustive_mode', False, 'Whether to exhaustively warp '
- 'from any frame to any other instead of just considering '
- 'adjacent frames. Where necessary, multiple egomotion '
- 'estimates will be applied. Does not have an effect if '
- 'compute_minimum_loss is enabled.')
-flags.DEFINE_boolean('random_scale_crop', False, 'Whether to apply random '
- 'image scaling and center cropping during training.')
-flags.DEFINE_bool('depth_upsampling', True, 'Whether to apply depth '
- 'upsampling of lower-scale representations before warping to '
- 'compute reconstruction loss on full-resolution image.')
-flags.DEFINE_bool('depth_normalization', True, 'Whether to apply depth '
- 'normalization, that is, normalizing inverse depth '
- 'prediction maps by their mean to avoid degeneration towards '
- 'small values.')
-flags.DEFINE_bool('compute_minimum_loss', True, 'Whether to take the '
- 'element-wise minimum of the reconstruction/SSIM error in '
- 'order to avoid overly penalizing dis-occlusion effects.')
-flags.DEFINE_bool('use_skip', True, 'Whether to use skip connections in the '
- 'encoder-decoder architecture.')
-flags.DEFINE_bool('joint_encoder', False, 'Whether to share parameters '
- 'between the depth and egomotion networks by using a joint '
- 'encoder architecture. The egomotion network is then '
- 'operating only on the hidden representation provided by the '
- 'joint encoder.')
-flags.DEFINE_float('egomotion_threshold', 0.01, 'Minimum egomotion magnitude '
- 'to apply finetuning. If lower, just forwards the ordinary '
- 'prediction.')
-flags.DEFINE_integer('num_steps', 20, 'Number of optimization steps to run.')
-flags.DEFINE_boolean('handle_motion', True, 'Whether the checkpoint was '
- 'trained with motion handling.')
-flags.DEFINE_bool('flip', False, 'Whether images should be flipped as well as '
- 'resulting predictions (for test-time augmentation). This '
- 'currently applies to the depth network only.')
-
-FLAGS = flags.FLAGS
-flags.mark_flag_as_required('output_dir')
-flags.mark_flag_as_required('data_dir')
-flags.mark_flag_as_required('model_ckpt')
-flags.mark_flag_as_required('triplet_list_file')
-
-
-def main(_):
- """Runs fine-tuning and inference.
-
- There are three categories of images.
- 1) Images where we have previous and next frame, and that are not filtered
- out by the heuristic. For them, we will use the fine-tuned predictions.
- 2) Images where we have previous and next frame, but that were filtered out
- by our heuristic. For them, we will use the ordinary prediction instead.
- 3) Images where we have at least one missing adjacent frame. For them, we will
- use the ordinary prediction as indicated by triplet_list_file_remains (if
- provided). They will also not be part of the generated inference list in
- the first place.
-
- Raises:
- ValueError: Invalid parameters have been passed.
- """
-
- if FLAGS.handle_motion and FLAGS.joint_encoder:
- raise ValueError('Using a joint encoder is currently not supported when '
- 'modeling object motion.')
- if FLAGS.handle_motion and FLAGS.seq_length != 3:
- raise ValueError('The current motion model implementation only supports '
- 'using a sequence length of three.')
- if FLAGS.handle_motion and not FLAGS.compute_minimum_loss:
- raise ValueError('Computing the minimum photometric loss is required when '
- 'enabling object motion handling.')
- if FLAGS.size_constraint_weight > 0 and not FLAGS.handle_motion:
- raise ValueError('To enforce object size constraints, enable motion '
- 'handling.')
- if FLAGS.icp_weight > 0.0:
- raise ValueError('ICP is currently not supported.')
- if FLAGS.compute_minimum_loss and FLAGS.seq_length % 2 != 1:
- raise ValueError('Compute minimum loss requires using an odd number of '
- 'images in a sequence.')
- if FLAGS.compute_minimum_loss and FLAGS.exhaustive_mode:
- raise ValueError('Exhaustive mode has no effect when compute_minimum_loss '
- 'is enabled.')
- if FLAGS.img_width % (2 ** 5) != 0 or FLAGS.img_height % (2 ** 5) != 0:
- logging.warn('Image size is not divisible by 2^5. For the architecture '
- 'employed, this could cause artefacts caused by resizing in '
- 'lower dimensions.')
-
- if FLAGS.output_dir.endswith('/'):
- FLAGS.output_dir = FLAGS.output_dir[:-1]
-
- # Create file lists to prepare fine-tuning, save it to unique_file.
- unique_file_name = (str(datetime.datetime.now().date()) + '_' +
- str(datetime.datetime.now().time()).replace(':', '_'))
- unique_file = os.path.join(FLAGS.data_dir, unique_file_name + '.txt')
- with gfile.FastGFile(FLAGS.triplet_list_file, 'r') as f:
- files_to_process = f.readlines()
- files_to_process = [line.rstrip() for line in files_to_process]
- files_to_process = [line for line in files_to_process if len(line)]
- logging.info('Creating unique file list %s with %s entries.', unique_file,
- len(files_to_process))
- with gfile.FastGFile(unique_file, 'w') as f_out:
- fetches_network = FLAGS.num_steps * FLAGS.batch_size
- fetches_saves = FLAGS.batch_size * int(np.floor(FLAGS.num_steps/SAVE_EVERY))
- repetitions = fetches_network + 3 * fetches_saves
- for i in range(len(files_to_process)):
- for _ in range(repetitions):
- f_out.write(files_to_process[i] + '\n')
-
- # Read remaining files.
- remaining = []
- if gfile.Exists(FLAGS.triplet_list_file_remains):
- with gfile.FastGFile(FLAGS.triplet_list_file_remains, 'r') as f:
- remaining = f.readlines()
- remaining = [line.rstrip() for line in remaining]
- remaining = [line for line in remaining if len(line)]
- logging.info('Running fine-tuning on %s files, %s files are remaining.',
- len(files_to_process), len(remaining))
-
- # Run fine-tuning process and save predictions in id-folders.
- tf.set_random_seed(FIXED_SEED)
- np.random.seed(FIXED_SEED)
- random.seed(FIXED_SEED)
- flipping_mode = reader.FLIP_ALWAYS if FLAGS.flip else reader.FLIP_NONE
- train_model = model.Model(data_dir=FLAGS.data_dir,
- file_extension=FLAGS.file_extension,
- is_training=True,
- learning_rate=FLAGS.learning_rate,
- beta1=FLAGS.beta1,
- reconstr_weight=FLAGS.reconstr_weight,
- smooth_weight=FLAGS.smooth_weight,
- ssim_weight=FLAGS.ssim_weight,
- icp_weight=FLAGS.icp_weight,
- batch_size=FLAGS.batch_size,
- img_height=FLAGS.img_height,
- img_width=FLAGS.img_width,
- seq_length=FLAGS.seq_length,
- architecture=FLAGS.architecture,
- imagenet_norm=FLAGS.imagenet_norm,
- weight_reg=FLAGS.weight_reg,
- exhaustive_mode=FLAGS.exhaustive_mode,
- random_scale_crop=FLAGS.random_scale_crop,
- flipping_mode=flipping_mode,
- random_color=False,
- depth_upsampling=FLAGS.depth_upsampling,
- depth_normalization=FLAGS.depth_normalization,
- compute_minimum_loss=FLAGS.compute_minimum_loss,
- use_skip=FLAGS.use_skip,
- joint_encoder=FLAGS.joint_encoder,
- build_sum=False,
- shuffle=False,
- input_file=unique_file_name,
- handle_motion=FLAGS.handle_motion,
- size_constraint_weight=FLAGS.size_constraint_weight,
- train_global_scale_var=False)
-
- failed_heuristic_ids = finetune_inference(train_model, FLAGS.model_ckpt,
- FLAGS.output_dir + '_ft')
- logging.info('Fine-tuning completed, %s files were filtered out by '
- 'heuristic.', len(failed_heuristic_ids))
- for failed_id in failed_heuristic_ids:
- failed_entry = files_to_process[failed_id]
- remaining.append(failed_entry)
- logging.info('In total, %s images were fine-tuned, while %s were not.',
- len(files_to_process)-len(failed_heuristic_ids), len(remaining))
-
- # Copy all results to have the same structural output as running ordinary
- # inference.
- for i in range(len(files_to_process)):
- if files_to_process[i] not in remaining: # Use fine-tuned result.
- elements = files_to_process[i].split(' ')
- source_file = os.path.join(FLAGS.output_dir + '_ft', FLAGS.ft_name +
- 'id_' + str(i),
- str(FLAGS.num_steps).zfill(10) +
- ('_flip' if FLAGS.flip else ''))
- if len(elements) == 2: # No differing mapping defined.
- target_dir = os.path.join(FLAGS.output_dir + '_ft', elements[0])
- target_file = os.path.join(
- target_dir, elements[1] + ('_flip' if FLAGS.flip else ''))
- else: # Other mapping for file defined, copy to this location instead.
- target_dir = os.path.join(
- FLAGS.output_dir + '_ft', os.path.dirname(elements[2]))
- target_file = os.path.join(
- target_dir,
- os.path.basename(elements[2]) + ('_flip' if FLAGS.flip else ''))
- if not gfile.Exists(target_dir):
- gfile.MakeDirs(target_dir)
- logging.info('Copy refined result %s to %s.', source_file, target_file)
- gfile.Copy(source_file + '.npy', target_file + '.npy', overwrite=True)
- gfile.Copy(source_file + '.txt', target_file + '.txt', overwrite=True)
- gfile.Copy(source_file + '.%s' % FLAGS.file_extension,
- target_file + '.%s' % FLAGS.file_extension, overwrite=True)
- for j in range(len(remaining)):
- elements = remaining[j].split(' ')
- if len(elements) == 2: # No differing mapping defined.
- target_dir = os.path.join(FLAGS.output_dir + '_ft', elements[0])
- target_file = os.path.join(
- target_dir, elements[1] + ('_flip' if FLAGS.flip else ''))
- else: # Other mapping for file defined, copy to this location instead.
- target_dir = os.path.join(
- FLAGS.output_dir + '_ft', os.path.dirname(elements[2]))
- target_file = os.path.join(
- target_dir,
- os.path.basename(elements[2]) + ('_flip' if FLAGS.flip else ''))
- if not gfile.Exists(target_dir):
- gfile.MakeDirs(target_dir)
- source_file = target_file.replace('_ft', '')
- logging.info('Copy unrefined result %s to %s.', source_file, target_file)
- gfile.Copy(source_file + '.npy', target_file + '.npy', overwrite=True)
- gfile.Copy(source_file + '.%s' % FLAGS.file_extension,
- target_file + '.%s' % FLAGS.file_extension, overwrite=True)
- logging.info('Done, predictions saved in %s.', FLAGS.output_dir + '_ft')
-
-
-def finetune_inference(train_model, model_ckpt, output_dir):
- """Train model."""
- vars_to_restore = None
- if model_ckpt is not None:
- vars_to_restore = util.get_vars_to_save_and_restore(model_ckpt)
- ckpt_path = model_ckpt
- pretrain_restorer = tf.train.Saver(vars_to_restore)
- sv = tf.train.Supervisor(logdir=None, save_summaries_secs=0, saver=None,
- summary_op=None)
- config = tf.ConfigProto()
- config.gpu_options.allow_growth = True
- img_nr = 0
- failed_heuristic = []
- with sv.managed_session(config=config) as sess:
- # TODO(casser): Caching the weights would be better to avoid I/O bottleneck.
- while True: # Loop terminates when all examples have been processed.
- if model_ckpt is not None:
- logging.info('Restored weights from %s', ckpt_path)
- pretrain_restorer.restore(sess, ckpt_path)
- logging.info('Running fine-tuning, image %s...', img_nr)
- img_pred_folder = os.path.join(
- output_dir, FLAGS.ft_name + 'id_' + str(img_nr))
- if not gfile.Exists(img_pred_folder):
- gfile.MakeDirs(img_pred_folder)
- step = 1
-
- # Run fine-tuning.
- while step <= FLAGS.num_steps:
- logging.info('Running step %s of %s.', step, FLAGS.num_steps)
- fetches = {
- 'train': train_model.train_op,
- 'global_step': train_model.global_step,
- 'incr_global_step': train_model.incr_global_step
- }
- _ = sess.run(fetches)
- if step % SAVE_EVERY == 0:
- # Get latest prediction for middle frame, highest scale.
- pred = train_model.depth[1][0].eval(session=sess)
- if FLAGS.flip:
- pred = np.flip(pred, axis=2)
- input_img = train_model.image_stack.eval(session=sess)
- input_img_prev = input_img[0, :, :, 0:3]
- input_img_center = input_img[0, :, :, 3:6]
- input_img_next = input_img[0, :, :, 6:]
- img_pred_file = os.path.join(
- img_pred_folder,
- str(step).zfill(10) + ('_flip' if FLAGS.flip else '') + '.npy')
- motion = np.squeeze(train_model.egomotion.eval(session=sess))
- # motion of shape (seq_length - 1, 6).
- motion = np.mean(motion, axis=0) # Average egomotion across frames.
-
- if SAVE_PREVIEWS or step == FLAGS.num_steps:
- # Also save preview of depth map.
- color_map = util.normalize_depth_for_display(
- np.squeeze(pred[0, :, :]))
- visualization = np.concatenate(
- (input_img_prev, input_img_center, input_img_next, color_map))
- motion_s = [str(m) for m in motion]
- s_rep = ','.join(motion_s)
- with gfile.Open(img_pred_file.replace('.npy', '.txt'), 'w') as f:
- f.write(s_rep)
- util.save_image(
- img_pred_file.replace('.npy', '.%s' % FLAGS.file_extension),
- visualization, FLAGS.file_extension)
-
- with gfile.Open(img_pred_file, 'wb') as f:
- np.save(f, pred)
-
- # Apply heuristic to not finetune if egomotion magnitude is too low.
- ego_magnitude = np.linalg.norm(motion[:3], ord=2)
- heuristic = ego_magnitude >= FLAGS.egomotion_threshold
- if not heuristic and step == FLAGS.num_steps:
- failed_heuristic.append(img_nr)
-
- step += 1
- img_nr += 1
- return failed_heuristic
-
-
-if __name__ == '__main__':
- app.run(main)
diff --git a/research/struct2depth/project.py b/research/struct2depth/project.py
deleted file mode 100644
index f249ebd3d6ab5837209b07f14f4e54f39f2baf8a..0000000000000000000000000000000000000000
--- a/research/struct2depth/project.py
+++ /dev/null
@@ -1,326 +0,0 @@
-
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Geometry utilities for projecting frames based on depth and motion.
-
-Modified from Spatial Transformer Networks:
-https://github.com/tensorflow/models/blob/master/transformer/spatial_transformer.py
-"""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-from absl import logging
-import numpy as np
-import tensorflow as tf
-
-
-def inverse_warp(img, depth, egomotion_mat, intrinsic_mat,
- intrinsic_mat_inv):
- """Inverse warp a source image to the target image plane.
-
- Args:
- img: The source image (to sample pixels from) -- [B, H, W, 3].
- depth: Depth map of the target image -- [B, H, W].
- egomotion_mat: Matrix defining egomotion transform -- [B, 4, 4].
- intrinsic_mat: Camera intrinsic matrix -- [B, 3, 3].
- intrinsic_mat_inv: Inverse of the intrinsic matrix -- [B, 3, 3].
- Returns:
- Projected source image
- """
- dims = tf.shape(img)
- batch_size, img_height, img_width = dims[0], dims[1], dims[2]
- depth = tf.reshape(depth, [batch_size, 1, img_height * img_width])
- grid = _meshgrid_abs(img_height, img_width)
- grid = tf.tile(tf.expand_dims(grid, 0), [batch_size, 1, 1])
- cam_coords = _pixel2cam(depth, grid, intrinsic_mat_inv)
- ones = tf.ones([batch_size, 1, img_height * img_width])
- cam_coords_hom = tf.concat([cam_coords, ones], axis=1)
-
- # Get projection matrix for target camera frame to source pixel frame
- hom_filler = tf.constant([0.0, 0.0, 0.0, 1.0], shape=[1, 1, 4])
- hom_filler = tf.tile(hom_filler, [batch_size, 1, 1])
- intrinsic_mat_hom = tf.concat(
- [intrinsic_mat, tf.zeros([batch_size, 3, 1])], axis=2)
- intrinsic_mat_hom = tf.concat([intrinsic_mat_hom, hom_filler], axis=1)
- proj_target_cam_to_source_pixel = tf.matmul(intrinsic_mat_hom, egomotion_mat)
- source_pixel_coords = _cam2pixel(cam_coords_hom,
- proj_target_cam_to_source_pixel)
- source_pixel_coords = tf.reshape(source_pixel_coords,
- [batch_size, 2, img_height, img_width])
- source_pixel_coords = tf.transpose(source_pixel_coords, perm=[0, 2, 3, 1])
- projected_img, mask = _spatial_transformer(img, source_pixel_coords)
- return projected_img, mask
-
-
-def get_transform_mat(egomotion_vecs, i, j):
- """Returns a transform matrix defining the transform from frame i to j."""
- egomotion_transforms = []
- batchsize = tf.shape(egomotion_vecs)[0]
- if i == j:
- return tf.tile(tf.expand_dims(tf.eye(4, 4), axis=0), [batchsize, 1, 1])
- for k in range(min(i, j), max(i, j)):
- transform_matrix = _egomotion_vec2mat(egomotion_vecs[:, k, :], batchsize)
- if i > j: # Going back in sequence, need to invert egomotion.
- egomotion_transforms.insert(0, tf.linalg.inv(transform_matrix))
- else: # Going forward in sequence
- egomotion_transforms.append(transform_matrix)
-
- # Multiply all matrices.
- egomotion_mat = egomotion_transforms[0]
- for i in range(1, len(egomotion_transforms)):
- egomotion_mat = tf.matmul(egomotion_mat, egomotion_transforms[i])
- return egomotion_mat
-
-
-def _pixel2cam(depth, pixel_coords, intrinsic_mat_inv):
- """Transform coordinates in the pixel frame to the camera frame."""
- cam_coords = tf.matmul(intrinsic_mat_inv, pixel_coords) * depth
- return cam_coords
-
-
-def _cam2pixel(cam_coords, proj_c2p):
- """Transform coordinates in the camera frame to the pixel frame."""
- pcoords = tf.matmul(proj_c2p, cam_coords)
- x = tf.slice(pcoords, [0, 0, 0], [-1, 1, -1])
- y = tf.slice(pcoords, [0, 1, 0], [-1, 1, -1])
- z = tf.slice(pcoords, [0, 2, 0], [-1, 1, -1])
- # Not tested if adding a small number is necessary
- x_norm = x / (z + 1e-10)
- y_norm = y / (z + 1e-10)
- pixel_coords = tf.concat([x_norm, y_norm], axis=1)
- return pixel_coords
-
-
-def _meshgrid_abs(height, width):
- """Meshgrid in the absolute coordinates."""
- x_t = tf.matmul(
- tf.ones(shape=tf.stack([height, 1])),
- tf.transpose(tf.expand_dims(tf.linspace(-1.0, 1.0, width), 1), [1, 0]))
- y_t = tf.matmul(
- tf.expand_dims(tf.linspace(-1.0, 1.0, height), 1),
- tf.ones(shape=tf.stack([1, width])))
- x_t = (x_t + 1.0) * 0.5 * tf.cast(width - 1, tf.float32)
- y_t = (y_t + 1.0) * 0.5 * tf.cast(height - 1, tf.float32)
- x_t_flat = tf.reshape(x_t, (1, -1))
- y_t_flat = tf.reshape(y_t, (1, -1))
- ones = tf.ones_like(x_t_flat)
- grid = tf.concat([x_t_flat, y_t_flat, ones], axis=0)
- return grid
-
-
-def _euler2mat(z, y, x):
- """Converts euler angles to rotation matrix.
-
- From:
- https://github.com/pulkitag/pycaffe-utils/blob/master/rot_utils.py#L174
-
- TODO: Remove the dimension for 'N' (deprecated for converting all source
- poses altogether).
-
- Args:
- z: rotation angle along z axis (in radians) -- size = [B, n]
- y: rotation angle along y axis (in radians) -- size = [B, n]
- x: rotation angle along x axis (in radians) -- size = [B, n]
-
- Returns:
- Rotation matrix corresponding to the euler angles, with shape [B, n, 3, 3].
- """
- batch_size = tf.shape(z)[0]
- n = 1
- z = tf.clip_by_value(z, -np.pi, np.pi)
- y = tf.clip_by_value(y, -np.pi, np.pi)
- x = tf.clip_by_value(x, -np.pi, np.pi)
-
- # Expand to B x N x 1 x 1
- z = tf.expand_dims(tf.expand_dims(z, -1), -1)
- y = tf.expand_dims(tf.expand_dims(y, -1), -1)
- x = tf.expand_dims(tf.expand_dims(x, -1), -1)
-
- zeros = tf.zeros([batch_size, n, 1, 1])
- ones = tf.ones([batch_size, n, 1, 1])
-
- cosz = tf.cos(z)
- sinz = tf.sin(z)
- rotz_1 = tf.concat([cosz, -sinz, zeros], axis=3)
- rotz_2 = tf.concat([sinz, cosz, zeros], axis=3)
- rotz_3 = tf.concat([zeros, zeros, ones], axis=3)
- zmat = tf.concat([rotz_1, rotz_2, rotz_3], axis=2)
-
- cosy = tf.cos(y)
- siny = tf.sin(y)
- roty_1 = tf.concat([cosy, zeros, siny], axis=3)
- roty_2 = tf.concat([zeros, ones, zeros], axis=3)
- roty_3 = tf.concat([-siny, zeros, cosy], axis=3)
- ymat = tf.concat([roty_1, roty_2, roty_3], axis=2)
-
- cosx = tf.cos(x)
- sinx = tf.sin(x)
- rotx_1 = tf.concat([ones, zeros, zeros], axis=3)
- rotx_2 = tf.concat([zeros, cosx, -sinx], axis=3)
- rotx_3 = tf.concat([zeros, sinx, cosx], axis=3)
- xmat = tf.concat([rotx_1, rotx_2, rotx_3], axis=2)
-
- return tf.matmul(tf.matmul(xmat, ymat), zmat)
-
-
-def _egomotion_vec2mat(vec, batch_size):
- """Converts 6DoF transform vector to transformation matrix.
-
- Args:
- vec: 6DoF parameters [tx, ty, tz, rx, ry, rz] -- [B, 6].
- batch_size: Batch size.
-
- Returns:
- A transformation matrix -- [B, 4, 4].
- """
- translation = tf.slice(vec, [0, 0], [-1, 3])
- translation = tf.expand_dims(translation, -1)
- rx = tf.slice(vec, [0, 3], [-1, 1])
- ry = tf.slice(vec, [0, 4], [-1, 1])
- rz = tf.slice(vec, [0, 5], [-1, 1])
- rot_mat = _euler2mat(rz, ry, rx)
- rot_mat = tf.squeeze(rot_mat, squeeze_dims=[1])
- filler = tf.constant([0.0, 0.0, 0.0, 1.0], shape=[1, 1, 4])
- filler = tf.tile(filler, [batch_size, 1, 1])
- transform_mat = tf.concat([rot_mat, translation], axis=2)
- transform_mat = tf.concat([transform_mat, filler], axis=1)
- return transform_mat
-
-
-def _bilinear_sampler(im, x, y, name='blinear_sampler'):
- """Perform bilinear sampling on im given list of x, y coordinates.
-
- Implements the differentiable sampling mechanism with bilinear kernel
- in https://arxiv.org/abs/1506.02025.
-
- x,y are tensors specifying normalized coordinates [-1, 1] to be sampled on im.
- For example, (-1, -1) in (x, y) corresponds to pixel location (0, 0) in im,
- and (1, 1) in (x, y) corresponds to the bottom right pixel in im.
-
- Args:
- im: Batch of images with shape [B, h, w, channels].
- x: Tensor of normalized x coordinates in [-1, 1], with shape [B, h, w, 1].
- y: Tensor of normalized y coordinates in [-1, 1], with shape [B, h, w, 1].
- name: Name scope for ops.
-
- Returns:
- Sampled image with shape [B, h, w, channels].
- Principled mask with shape [B, h, w, 1], dtype:float32. A value of 1.0
- in the mask indicates that the corresponding coordinate in the sampled
- image is valid.
- """
- with tf.variable_scope(name):
- x = tf.reshape(x, [-1])
- y = tf.reshape(y, [-1])
-
- # Constants.
- batch_size = tf.shape(im)[0]
- _, height, width, channels = im.get_shape().as_list()
-
- x = tf.to_float(x)
- y = tf.to_float(y)
- height_f = tf.cast(height, 'float32')
- width_f = tf.cast(width, 'float32')
- zero = tf.constant(0, dtype=tf.int32)
- max_y = tf.cast(tf.shape(im)[1] - 1, 'int32')
- max_x = tf.cast(tf.shape(im)[2] - 1, 'int32')
-
- # Scale indices from [-1, 1] to [0, width - 1] or [0, height - 1].
- x = (x + 1.0) * (width_f - 1.0) / 2.0
- y = (y + 1.0) * (height_f - 1.0) / 2.0
-
- # Compute the coordinates of the 4 pixels to sample from.
- x0 = tf.cast(tf.floor(x), 'int32')
- x1 = x0 + 1
- y0 = tf.cast(tf.floor(y), 'int32')
- y1 = y0 + 1
-
- mask = tf.logical_and(
- tf.logical_and(x0 >= zero, x1 <= max_x),
- tf.logical_and(y0 >= zero, y1 <= max_y))
- mask = tf.to_float(mask)
-
- x0 = tf.clip_by_value(x0, zero, max_x)
- x1 = tf.clip_by_value(x1, zero, max_x)
- y0 = tf.clip_by_value(y0, zero, max_y)
- y1 = tf.clip_by_value(y1, zero, max_y)
- dim2 = width
- dim1 = width * height
-
- # Create base index.
- base = tf.range(batch_size) * dim1
- base = tf.reshape(base, [-1, 1])
- base = tf.tile(base, [1, height * width])
- base = tf.reshape(base, [-1])
-
- base_y0 = base + y0 * dim2
- base_y1 = base + y1 * dim2
- idx_a = base_y0 + x0
- idx_b = base_y1 + x0
- idx_c = base_y0 + x1
- idx_d = base_y1 + x1
-
- # Use indices to lookup pixels in the flat image and restore channels dim.
- im_flat = tf.reshape(im, tf.stack([-1, channels]))
- im_flat = tf.to_float(im_flat)
- pixel_a = tf.gather(im_flat, idx_a)
- pixel_b = tf.gather(im_flat, idx_b)
- pixel_c = tf.gather(im_flat, idx_c)
- pixel_d = tf.gather(im_flat, idx_d)
-
- x1_f = tf.to_float(x1)
- y1_f = tf.to_float(y1)
-
- # And finally calculate interpolated values.
- wa = tf.expand_dims(((x1_f - x) * (y1_f - y)), 1)
- wb = tf.expand_dims((x1_f - x) * (1.0 - (y1_f - y)), 1)
- wc = tf.expand_dims(((1.0 - (x1_f - x)) * (y1_f - y)), 1)
- wd = tf.expand_dims(((1.0 - (x1_f - x)) * (1.0 - (y1_f - y))), 1)
-
- output = tf.add_n([wa * pixel_a, wb * pixel_b, wc * pixel_c, wd * pixel_d])
- output = tf.reshape(output, tf.stack([batch_size, height, width, channels]))
- mask = tf.reshape(mask, tf.stack([batch_size, height, width, 1]))
- return output, mask
-
-
-def _spatial_transformer(img, coords):
- """A wrapper over binlinear_sampler(), taking absolute coords as input."""
- img_height = tf.cast(tf.shape(img)[1], tf.float32)
- img_width = tf.cast(tf.shape(img)[2], tf.float32)
- px = coords[:, :, :, :1]
- py = coords[:, :, :, 1:]
- # Normalize coordinates to [-1, 1] to send to _bilinear_sampler.
- px = px / (img_width - 1) * 2.0 - 1.0
- py = py / (img_height - 1) * 2.0 - 1.0
- output_img, mask = _bilinear_sampler(img, px, py)
- return output_img, mask
-
-
-def get_cloud(depth, intrinsics_inv, name=None):
- """Convert depth map to 3D point cloud."""
- with tf.name_scope(name):
- dims = depth.shape.as_list()
- batch_size, img_height, img_width = dims[0], dims[1], dims[2]
- depth = tf.reshape(depth, [batch_size, 1, img_height * img_width])
- grid = _meshgrid_abs(img_height, img_width)
- grid = tf.tile(tf.expand_dims(grid, 0), [batch_size, 1, 1])
- cam_coords = _pixel2cam(depth, grid, intrinsics_inv)
- cam_coords = tf.transpose(cam_coords, [0, 2, 1])
- cam_coords = tf.reshape(cam_coords, [batch_size, img_height, img_width, 3])
- logging.info('depth -> cloud: %s', cam_coords)
- return cam_coords
diff --git a/research/struct2depth/reader.py b/research/struct2depth/reader.py
deleted file mode 100644
index 444e4bea90a9ac377c6e4789a0eebf947f8ee790..0000000000000000000000000000000000000000
--- a/research/struct2depth/reader.py
+++ /dev/null
@@ -1,344 +0,0 @@
-
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Reads data that is produced by dataset/gen_data.py."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import os
-import random
-from absl import logging
-import tensorflow as tf
-
-import util
-
-gfile = tf.gfile
-
-QUEUE_SIZE = 2000
-QUEUE_BUFFER = 3
-# See nets.encoder_resnet as reference for below input-normalizing constants.
-IMAGENET_MEAN = (0.485, 0.456, 0.406)
-IMAGENET_SD = (0.229, 0.224, 0.225)
-FLIP_RANDOM = 'random' # Always perform random flipping.
-FLIP_ALWAYS = 'always' # Always flip image input, used for test augmentation.
-FLIP_NONE = 'none' # Always disables flipping.
-
-
-class DataReader(object):
- """Reads stored sequences which are produced by dataset/gen_data.py."""
-
- def __init__(self, data_dir, batch_size, img_height, img_width, seq_length,
- num_scales, file_extension, random_scale_crop, flipping_mode,
- random_color, imagenet_norm, shuffle, input_file='train'):
- self.data_dir = data_dir
- self.batch_size = batch_size
- self.img_height = img_height
- self.img_width = img_width
- self.seq_length = seq_length
- self.num_scales = num_scales
- self.file_extension = file_extension
- self.random_scale_crop = random_scale_crop
- self.flipping_mode = flipping_mode
- self.random_color = random_color
- self.imagenet_norm = imagenet_norm
- self.shuffle = shuffle
- self.input_file = input_file
-
- def read_data(self):
- """Provides images and camera intrinsics."""
- with tf.name_scope('data_loading'):
- with tf.name_scope('enqueue_paths'):
- seed = random.randint(0, 2**31 - 1)
- self.file_lists = self.compile_file_list(self.data_dir, self.input_file)
- image_paths_queue = tf.train.string_input_producer(
- self.file_lists['image_file_list'], seed=seed,
- shuffle=self.shuffle,
- num_epochs=(1 if not self.shuffle else None)
- )
- seg_paths_queue = tf.train.string_input_producer(
- self.file_lists['segment_file_list'], seed=seed,
- shuffle=self.shuffle,
- num_epochs=(1 if not self.shuffle else None))
- cam_paths_queue = tf.train.string_input_producer(
- self.file_lists['cam_file_list'], seed=seed,
- shuffle=self.shuffle,
- num_epochs=(1 if not self.shuffle else None))
- img_reader = tf.WholeFileReader()
- _, image_contents = img_reader.read(image_paths_queue)
- seg_reader = tf.WholeFileReader()
- _, seg_contents = seg_reader.read(seg_paths_queue)
- if self.file_extension == 'jpg':
- image_seq = tf.image.decode_jpeg(image_contents)
- seg_seq = tf.image.decode_jpeg(seg_contents, channels=3)
- elif self.file_extension == 'png':
- image_seq = tf.image.decode_png(image_contents, channels=3)
- seg_seq = tf.image.decode_png(seg_contents, channels=3)
-
- with tf.name_scope('load_intrinsics'):
- cam_reader = tf.TextLineReader()
- _, raw_cam_contents = cam_reader.read(cam_paths_queue)
- rec_def = []
- for _ in range(9):
- rec_def.append([1.0])
- raw_cam_vec = tf.decode_csv(raw_cam_contents, record_defaults=rec_def)
- raw_cam_vec = tf.stack(raw_cam_vec)
- intrinsics = tf.reshape(raw_cam_vec, [3, 3])
-
- with tf.name_scope('convert_image'):
- image_seq = self.preprocess_image(image_seq) # Converts to float.
-
- if self.random_color:
- with tf.name_scope('image_augmentation'):
- image_seq = self.augment_image_colorspace(image_seq)
-
- image_stack = self.unpack_images(image_seq)
- seg_stack = self.unpack_images(seg_seq)
-
- if self.flipping_mode != FLIP_NONE:
- random_flipping = (self.flipping_mode == FLIP_RANDOM)
- with tf.name_scope('image_augmentation_flip'):
- image_stack, seg_stack, intrinsics = self.augment_images_flip(
- image_stack, seg_stack, intrinsics,
- randomized=random_flipping)
-
- if self.random_scale_crop:
- with tf.name_scope('image_augmentation_scale_crop'):
- image_stack, seg_stack, intrinsics = self.augment_images_scale_crop(
- image_stack, seg_stack, intrinsics, self.img_height,
- self.img_width)
-
- with tf.name_scope('multi_scale_intrinsics'):
- intrinsic_mat = self.get_multi_scale_intrinsics(intrinsics,
- self.num_scales)
- intrinsic_mat.set_shape([self.num_scales, 3, 3])
- intrinsic_mat_inv = tf.matrix_inverse(intrinsic_mat)
- intrinsic_mat_inv.set_shape([self.num_scales, 3, 3])
-
- if self.imagenet_norm:
- im_mean = tf.tile(
- tf.constant(IMAGENET_MEAN), multiples=[self.seq_length])
- im_sd = tf.tile(
- tf.constant(IMAGENET_SD), multiples=[self.seq_length])
- image_stack_norm = (image_stack - im_mean) / im_sd
- else:
- image_stack_norm = image_stack
-
- with tf.name_scope('batching'):
- if self.shuffle:
- (image_stack, image_stack_norm, seg_stack, intrinsic_mat,
- intrinsic_mat_inv) = tf.train.shuffle_batch(
- [image_stack, image_stack_norm, seg_stack, intrinsic_mat,
- intrinsic_mat_inv],
- batch_size=self.batch_size,
- capacity=QUEUE_SIZE + QUEUE_BUFFER * self.batch_size,
- min_after_dequeue=QUEUE_SIZE)
- else:
- (image_stack, image_stack_norm, seg_stack, intrinsic_mat,
- intrinsic_mat_inv) = tf.train.batch(
- [image_stack, image_stack_norm, seg_stack, intrinsic_mat,
- intrinsic_mat_inv],
- batch_size=self.batch_size,
- num_threads=1,
- capacity=QUEUE_SIZE + QUEUE_BUFFER * self.batch_size)
- logging.info('image_stack: %s', util.info(image_stack))
- return (image_stack, image_stack_norm, seg_stack, intrinsic_mat,
- intrinsic_mat_inv)
-
- def unpack_images(self, image_seq):
- """[h, w * seq_length, 3] -> [h, w, 3 * seq_length]."""
- with tf.name_scope('unpack_images'):
- image_list = [
- image_seq[:, i * self.img_width:(i + 1) * self.img_width, :]
- for i in range(self.seq_length)
- ]
- image_stack = tf.concat(image_list, axis=2)
- image_stack.set_shape(
- [self.img_height, self.img_width, self.seq_length * 3])
- return image_stack
-
- @classmethod
- def preprocess_image(cls, image):
- # Convert from uint8 to float.
- return tf.image.convert_image_dtype(image, dtype=tf.float32)
-
- @classmethod
- def augment_image_colorspace(cls, image_stack):
- """Apply data augmentation to inputs."""
- image_stack_aug = image_stack
- # Randomly shift brightness.
- apply_brightness = tf.less(tf.random_uniform(
- shape=[], minval=0.0, maxval=1.0, dtype=tf.float32), 0.5)
- image_stack_aug = tf.cond(
- apply_brightness,
- lambda: tf.image.random_brightness(image_stack_aug, max_delta=0.1),
- lambda: image_stack_aug)
-
- # Randomly shift contrast.
- apply_contrast = tf.less(tf.random_uniform(
- shape=[], minval=0.0, maxval=1.0, dtype=tf.float32), 0.5)
- image_stack_aug = tf.cond(
- apply_contrast,
- lambda: tf.image.random_contrast(image_stack_aug, 0.85, 1.15),
- lambda: image_stack_aug)
-
- # Randomly change saturation.
- apply_saturation = tf.less(tf.random_uniform(
- shape=[], minval=0.0, maxval=1.0, dtype=tf.float32), 0.5)
- image_stack_aug = tf.cond(
- apply_saturation,
- lambda: tf.image.random_saturation(image_stack_aug, 0.85, 1.15),
- lambda: image_stack_aug)
-
- # Randomly change hue.
- apply_hue = tf.less(tf.random_uniform(
- shape=[], minval=0.0, maxval=1.0, dtype=tf.float32), 0.5)
- image_stack_aug = tf.cond(
- apply_hue,
- lambda: tf.image.random_hue(image_stack_aug, max_delta=0.1),
- lambda: image_stack_aug)
-
- image_stack_aug = tf.clip_by_value(image_stack_aug, 0, 1)
- return image_stack_aug
-
- @classmethod
- def augment_images_flip(cls, image_stack, seg_stack, intrinsics,
- randomized=True):
- """Randomly flips the image horizontally."""
-
- def flip(cls, image_stack, seg_stack, intrinsics):
- _, in_w, _ = image_stack.get_shape().as_list()
- fx = intrinsics[0, 0]
- fy = intrinsics[1, 1]
- cx = in_w - intrinsics[0, 2]
- cy = intrinsics[1, 2]
- intrinsics = cls.make_intrinsics_matrix(fx, fy, cx, cy)
- return (tf.image.flip_left_right(image_stack),
- tf.image.flip_left_right(seg_stack), intrinsics)
-
- if randomized:
- prob = tf.random_uniform(shape=[], minval=0.0, maxval=1.0,
- dtype=tf.float32)
- predicate = tf.less(prob, 0.5)
- return tf.cond(predicate,
- lambda: flip(cls, image_stack, seg_stack, intrinsics),
- lambda: (image_stack, seg_stack, intrinsics))
- else:
- return flip(cls, image_stack, seg_stack, intrinsics)
-
- @classmethod
- def augment_images_scale_crop(cls, im, seg, intrinsics, out_h, out_w):
- """Randomly scales and crops image."""
-
- def scale_randomly(im, seg, intrinsics):
- """Scales image and adjust intrinsics accordingly."""
- in_h, in_w, _ = im.get_shape().as_list()
- scaling = tf.random_uniform([2], 1, 1.15)
- x_scaling = scaling[0]
- y_scaling = scaling[1]
- out_h = tf.cast(in_h * y_scaling, dtype=tf.int32)
- out_w = tf.cast(in_w * x_scaling, dtype=tf.int32)
- # Add batch.
- im = tf.expand_dims(im, 0)
- im = tf.image.resize_area(im, [out_h, out_w])
- im = im[0]
- seg = tf.expand_dims(seg, 0)
- seg = tf.image.resize_area(seg, [out_h, out_w])
- seg = seg[0]
- fx = intrinsics[0, 0] * x_scaling
- fy = intrinsics[1, 1] * y_scaling
- cx = intrinsics[0, 2] * x_scaling
- cy = intrinsics[1, 2] * y_scaling
- intrinsics = cls.make_intrinsics_matrix(fx, fy, cx, cy)
- return im, seg, intrinsics
-
- # Random cropping
- def crop_randomly(im, seg, intrinsics, out_h, out_w):
- """Crops image and adjust intrinsics accordingly."""
- # batch_size, in_h, in_w, _ = im.get_shape().as_list()
- in_h, in_w, _ = tf.unstack(tf.shape(im))
- offset_y = tf.random_uniform([1], 0, in_h - out_h + 1, dtype=tf.int32)[0]
- offset_x = tf.random_uniform([1], 0, in_w - out_w + 1, dtype=tf.int32)[0]
- im = tf.image.crop_to_bounding_box(im, offset_y, offset_x, out_h, out_w)
- seg = tf.image.crop_to_bounding_box(seg, offset_y, offset_x, out_h, out_w)
- fx = intrinsics[0, 0]
- fy = intrinsics[1, 1]
- cx = intrinsics[0, 2] - tf.cast(offset_x, dtype=tf.float32)
- cy = intrinsics[1, 2] - tf.cast(offset_y, dtype=tf.float32)
- intrinsics = cls.make_intrinsics_matrix(fx, fy, cx, cy)
- return im, seg, intrinsics
-
- im, seg, intrinsics = scale_randomly(im, seg, intrinsics)
- im, seg, intrinsics = crop_randomly(im, seg, intrinsics, out_h, out_w)
- return im, seg, intrinsics
-
- def compile_file_list(self, data_dir, split, load_pose=False):
- """Creates a list of input files."""
- logging.info('data_dir: %s', data_dir)
- with gfile.Open(os.path.join(data_dir, '%s.txt' % split), 'r') as f:
- frames = f.readlines()
- frames = [k.rstrip() for k in frames]
- subfolders = [x.split(' ')[0] for x in frames]
- frame_ids = [x.split(' ')[1] for x in frames]
- image_file_list = [
- os.path.join(data_dir, subfolders[i], frame_ids[i] + '.' +
- self.file_extension)
- for i in range(len(frames))
- ]
- segment_file_list = [
- os.path.join(data_dir, subfolders[i], frame_ids[i] + '-fseg.' +
- self.file_extension)
- for i in range(len(frames))
- ]
- cam_file_list = [
- os.path.join(data_dir, subfolders[i], frame_ids[i] + '_cam.txt')
- for i in range(len(frames))
- ]
- file_lists = {}
- file_lists['image_file_list'] = image_file_list
- file_lists['segment_file_list'] = segment_file_list
- file_lists['cam_file_list'] = cam_file_list
- if load_pose:
- pose_file_list = [
- os.path.join(data_dir, subfolders[i], frame_ids[i] + '_pose.txt')
- for i in range(len(frames))
- ]
- file_lists['pose_file_list'] = pose_file_list
- self.steps_per_epoch = len(image_file_list) // self.batch_size
- return file_lists
-
- @classmethod
- def make_intrinsics_matrix(cls, fx, fy, cx, cy):
- r1 = tf.stack([fx, 0, cx])
- r2 = tf.stack([0, fy, cy])
- r3 = tf.constant([0., 0., 1.])
- intrinsics = tf.stack([r1, r2, r3])
- return intrinsics
-
- @classmethod
- def get_multi_scale_intrinsics(cls, intrinsics, num_scales):
- """Returns multiple intrinsic matrices for different scales."""
- intrinsics_multi_scale = []
- # Scale the intrinsics accordingly for each scale
- for s in range(num_scales):
- fx = intrinsics[0, 0] / (2**s)
- fy = intrinsics[1, 1] / (2**s)
- cx = intrinsics[0, 2] / (2**s)
- cy = intrinsics[1, 2] / (2**s)
- intrinsics_multi_scale.append(cls.make_intrinsics_matrix(fx, fy, cx, cy))
- intrinsics_multi_scale = tf.stack(intrinsics_multi_scale)
- return intrinsics_multi_scale
diff --git a/research/struct2depth/train.py b/research/struct2depth/train.py
deleted file mode 100644
index 248c182fe5790ea1305cf887962bd26dd33d7b54..0000000000000000000000000000000000000000
--- a/research/struct2depth/train.py
+++ /dev/null
@@ -1,259 +0,0 @@
-
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Train the model. Please refer to README for example usage."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import math
-import os
-import random
-import time
-from absl import app
-from absl import flags
-from absl import logging
-import numpy as np
-import tensorflow as tf
-
-import model
-import nets
-import reader
-import util
-
-gfile = tf.gfile
-MAX_TO_KEEP = 1000000 # Maximum number of checkpoints to keep.
-
-flags.DEFINE_string('data_dir', None, 'Preprocessed data.')
-flags.DEFINE_string('file_extension', 'png', 'Image data file extension.')
-flags.DEFINE_float('learning_rate', 0.0002, 'Adam learning rate.')
-flags.DEFINE_float('beta1', 0.9, 'Adam momentum.')
-flags.DEFINE_float('reconstr_weight', 0.85, 'Frame reconstruction loss weight.')
-flags.DEFINE_float('ssim_weight', 0.15, 'SSIM loss weight.')
-flags.DEFINE_float('smooth_weight', 0.04, 'Smoothness loss weight.')
-flags.DEFINE_float('icp_weight', 0.0, 'ICP loss weight.')
-flags.DEFINE_float('size_constraint_weight', 0.0005, 'Weight of the object '
- 'size constraint loss. Use only when motion handling is '
- 'enabled.')
-flags.DEFINE_integer('batch_size', 4, 'The size of a sample batch')
-flags.DEFINE_integer('img_height', 128, 'Input frame height.')
-flags.DEFINE_integer('img_width', 416, 'Input frame width.')
-flags.DEFINE_integer('seq_length', 3, 'Number of frames in sequence.')
-flags.DEFINE_enum('architecture', nets.RESNET, nets.ARCHITECTURES,
- 'Defines the architecture to use for the depth prediction '
- 'network. Defaults to ResNet-based encoder and accompanying '
- 'decoder.')
-flags.DEFINE_boolean('imagenet_norm', True, 'Whether to normalize the input '
- 'images channel-wise so that they match the distribution '
- 'most ImageNet-models were trained on.')
-flags.DEFINE_float('weight_reg', 0.05, 'The amount of weight regularization to '
- 'apply. This has no effect on the ResNet-based encoder '
- 'architecture.')
-flags.DEFINE_boolean('exhaustive_mode', False, 'Whether to exhaustively warp '
- 'from any frame to any other instead of just considering '
- 'adjacent frames. Where necessary, multiple egomotion '
- 'estimates will be applied. Does not have an effect if '
- 'compute_minimum_loss is enabled.')
-flags.DEFINE_boolean('random_scale_crop', False, 'Whether to apply random '
- 'image scaling and center cropping during training.')
-flags.DEFINE_enum('flipping_mode', reader.FLIP_RANDOM,
- [reader.FLIP_RANDOM, reader.FLIP_ALWAYS, reader.FLIP_NONE],
- 'Determines the image flipping mode: if random, performs '
- 'on-the-fly augmentation. Otherwise, flips the input images '
- 'always or never, respectively.')
-flags.DEFINE_string('pretrained_ckpt', None, 'Path to checkpoint with '
- 'pretrained weights. Do not include .data* extension.')
-flags.DEFINE_string('imagenet_ckpt', None, 'Initialize the weights according '
- 'to an ImageNet-pretrained checkpoint. Requires '
- 'architecture to be ResNet-18.')
-flags.DEFINE_string('checkpoint_dir', None, 'Directory to save model '
- 'checkpoints.')
-flags.DEFINE_integer('train_steps', 10000000, 'Number of training steps.')
-flags.DEFINE_integer('summary_freq', 100, 'Save summaries every N steps.')
-flags.DEFINE_bool('depth_upsampling', True, 'Whether to apply depth '
- 'upsampling of lower-scale representations before warping to '
- 'compute reconstruction loss on full-resolution image.')
-flags.DEFINE_bool('depth_normalization', True, 'Whether to apply depth '
- 'normalization, that is, normalizing inverse depth '
- 'prediction maps by their mean to avoid degeneration towards '
- 'small values.')
-flags.DEFINE_bool('compute_minimum_loss', True, 'Whether to take the '
- 'element-wise minimum of the reconstruction/SSIM error in '
- 'order to avoid overly penalizing dis-occlusion effects.')
-flags.DEFINE_bool('use_skip', True, 'Whether to use skip connections in the '
- 'encoder-decoder architecture.')
-flags.DEFINE_bool('equal_weighting', False, 'Whether to use equal weighting '
- 'of the smoothing loss term, regardless of resolution.')
-flags.DEFINE_bool('joint_encoder', False, 'Whether to share parameters '
- 'between the depth and egomotion networks by using a joint '
- 'encoder architecture. The egomotion network is then '
- 'operating only on the hidden representation provided by the '
- 'joint encoder.')
-flags.DEFINE_bool('handle_motion', True, 'Whether to try to handle motion by '
- 'using the provided segmentation masks.')
-flags.DEFINE_string('master', 'local', 'Location of the session.')
-
-FLAGS = flags.FLAGS
-flags.mark_flag_as_required('data_dir')
-flags.mark_flag_as_required('checkpoint_dir')
-
-
-def main(_):
- # Fixed seed for repeatability
- seed = 8964
- tf.set_random_seed(seed)
- np.random.seed(seed)
- random.seed(seed)
-
- if FLAGS.handle_motion and FLAGS.joint_encoder:
- raise ValueError('Using a joint encoder is currently not supported when '
- 'modeling object motion.')
- if FLAGS.handle_motion and FLAGS.seq_length != 3:
- raise ValueError('The current motion model implementation only supports '
- 'using a sequence length of three.')
- if FLAGS.handle_motion and not FLAGS.compute_minimum_loss:
- raise ValueError('Computing the minimum photometric loss is required when '
- 'enabling object motion handling.')
- if FLAGS.size_constraint_weight > 0 and not FLAGS.handle_motion:
- raise ValueError('To enforce object size constraints, enable motion '
- 'handling.')
- if FLAGS.imagenet_ckpt and not FLAGS.imagenet_norm:
- logging.warn('When initializing with an ImageNet-pretrained model, it is '
- 'recommended to normalize the image inputs accordingly using '
- 'imagenet_norm.')
- if FLAGS.compute_minimum_loss and FLAGS.seq_length % 2 != 1:
- raise ValueError('Compute minimum loss requires using an odd number of '
- 'images in a sequence.')
- if FLAGS.architecture != nets.RESNET and FLAGS.imagenet_ckpt:
- raise ValueError('Can only load weights from pre-trained ImageNet model '
- 'when using ResNet-architecture.')
- if FLAGS.compute_minimum_loss and FLAGS.exhaustive_mode:
- raise ValueError('Exhaustive mode has no effect when compute_minimum_loss '
- 'is enabled.')
- if FLAGS.img_width % (2 ** 5) != 0 or FLAGS.img_height % (2 ** 5) != 0:
- logging.warn('Image size is not divisible by 2^5. For the architecture '
- 'employed, this could cause artefacts caused by resizing in '
- 'lower dimensions.')
- if FLAGS.icp_weight > 0.0:
- # TODO(casser): Change ICP interface to take matrix instead of vector.
- raise ValueError('ICP is currently not supported.')
-
- if not gfile.Exists(FLAGS.checkpoint_dir):
- gfile.MakeDirs(FLAGS.checkpoint_dir)
-
- train_model = model.Model(data_dir=FLAGS.data_dir,
- file_extension=FLAGS.file_extension,
- is_training=True,
- learning_rate=FLAGS.learning_rate,
- beta1=FLAGS.beta1,
- reconstr_weight=FLAGS.reconstr_weight,
- smooth_weight=FLAGS.smooth_weight,
- ssim_weight=FLAGS.ssim_weight,
- icp_weight=FLAGS.icp_weight,
- batch_size=FLAGS.batch_size,
- img_height=FLAGS.img_height,
- img_width=FLAGS.img_width,
- seq_length=FLAGS.seq_length,
- architecture=FLAGS.architecture,
- imagenet_norm=FLAGS.imagenet_norm,
- weight_reg=FLAGS.weight_reg,
- exhaustive_mode=FLAGS.exhaustive_mode,
- random_scale_crop=FLAGS.random_scale_crop,
- flipping_mode=FLAGS.flipping_mode,
- depth_upsampling=FLAGS.depth_upsampling,
- depth_normalization=FLAGS.depth_normalization,
- compute_minimum_loss=FLAGS.compute_minimum_loss,
- use_skip=FLAGS.use_skip,
- joint_encoder=FLAGS.joint_encoder,
- handle_motion=FLAGS.handle_motion,
- equal_weighting=FLAGS.equal_weighting,
- size_constraint_weight=FLAGS.size_constraint_weight)
-
- train(train_model, FLAGS.pretrained_ckpt, FLAGS.imagenet_ckpt,
- FLAGS.checkpoint_dir, FLAGS.train_steps, FLAGS.summary_freq)
-
-
-def train(train_model, pretrained_ckpt, imagenet_ckpt, checkpoint_dir,
- train_steps, summary_freq):
- """Train model."""
- vars_to_restore = None
- if pretrained_ckpt is not None:
- vars_to_restore = util.get_vars_to_save_and_restore(pretrained_ckpt)
- ckpt_path = pretrained_ckpt
- elif imagenet_ckpt:
- vars_to_restore = util.get_imagenet_vars_to_restore(imagenet_ckpt)
- ckpt_path = imagenet_ckpt
- pretrain_restorer = tf.train.Saver(vars_to_restore)
- vars_to_save = util.get_vars_to_save_and_restore()
- vars_to_save[train_model.global_step.op.name] = train_model.global_step
- saver = tf.train.Saver(vars_to_save, max_to_keep=MAX_TO_KEEP)
- sv = tf.train.Supervisor(logdir=checkpoint_dir, save_summaries_secs=0,
- saver=None)
- config = tf.ConfigProto()
- config.gpu_options.allow_growth = True
- with sv.managed_session(config=config) as sess:
- if pretrained_ckpt is not None or imagenet_ckpt:
- logging.info('Restoring pretrained weights from %s', ckpt_path)
- pretrain_restorer.restore(sess, ckpt_path)
-
- logging.info('Attempting to resume training from %s...', checkpoint_dir)
- checkpoint = tf.train.latest_checkpoint(checkpoint_dir)
- logging.info('Last checkpoint found: %s', checkpoint)
- if checkpoint:
- saver.restore(sess, checkpoint)
-
- logging.info('Training...')
- start_time = time.time()
- last_summary_time = time.time()
- steps_per_epoch = train_model.reader.steps_per_epoch
- step = 1
- while step <= train_steps:
- fetches = {
- 'train': train_model.train_op,
- 'global_step': train_model.global_step,
- 'incr_global_step': train_model.incr_global_step
- }
- if step % summary_freq == 0:
- fetches['loss'] = train_model.total_loss
- fetches['summary'] = sv.summary_op
-
- results = sess.run(fetches)
- global_step = results['global_step']
-
- if step % summary_freq == 0:
- sv.summary_writer.add_summary(results['summary'], global_step)
- train_epoch = math.ceil(global_step / steps_per_epoch)
- train_step = global_step - (train_epoch - 1) * steps_per_epoch
- this_cycle = time.time() - last_summary_time
- last_summary_time += this_cycle
- logging.info(
- 'Epoch: [%2d] [%5d/%5d] time: %4.2fs (%ds total) loss: %.3f',
- train_epoch, train_step, steps_per_epoch, this_cycle,
- time.time() - start_time, results['loss'])
-
- if step % steps_per_epoch == 0:
- logging.info('[*] Saving checkpoint to %s...', checkpoint_dir)
- saver.save(sess, os.path.join(checkpoint_dir, 'model'),
- global_step=global_step)
-
- # Setting step to global_step allows for training for a total of
- # train_steps even if the program is restarted during training.
- step = global_step + 1
-
-
-if __name__ == '__main__':
- app.run(main)
diff --git a/research/struct2depth/util.py b/research/struct2depth/util.py
deleted file mode 100644
index 79376864685363ab886ae35c8fa614d9641a397d..0000000000000000000000000000000000000000
--- a/research/struct2depth/util.py
+++ /dev/null
@@ -1,252 +0,0 @@
-
-# Copyright 2018 The TensorFlow Authors All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-# ==============================================================================
-
-"""Contains common utilities and functions."""
-
-from __future__ import absolute_import
-from __future__ import division
-from __future__ import print_function
-
-import locale
-import os
-import re
-from absl import logging
-import matplotlib
-matplotlib.use('Agg')
-import matplotlib.pyplot as plt
-import numpy as np
-import tensorflow as tf
-import cv2
-gfile = tf.gfile
-
-
-CMAP_DEFAULT = 'plasma'
-# Defines the cropping that is applied to the Cityscapes dataset with respect to
-# the original raw input resolution.
-CITYSCAPES_CROP = [256, 768, 192, 1856]
-
-
-def crop_cityscapes(im, resize=None):
- ymin, ymax, xmin, xmax = CITYSCAPES_CROP
- im = im[ymin:ymax, xmin:xmax]
- if resize is not None:
- im = cv2.resize(im, resize)
- return im
-
-
-def gray2rgb(im, cmap=CMAP_DEFAULT):
- cmap = plt.get_cmap(cmap)
- result_img = cmap(im.astype(np.float32))
- if result_img.shape[2] > 3:
- result_img = np.delete(result_img, 3, 2)
- return result_img
-
-
-def load_image(img_file, resize=None, interpolation='linear'):
- """Load image from disk. Output value range: [0,1]."""
- im_data = np.fromstring(gfile.Open(img_file).read(), np.uint8)
- im = cv2.imdecode(im_data, cv2.IMREAD_COLOR)
- im = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
- if resize and resize != im.shape[:2]:
- ip = cv2.INTER_LINEAR if interpolation == 'linear' else cv2.INTER_NEAREST
- im = cv2.resize(im, resize, interpolation=ip)
- return np.array(im, dtype=np.float32) / 255.0
-
-
-def save_image(img_file, im, file_extension):
- """Save image from disk. Expected input value range: [0,1]."""
- im = (im * 255.0).astype(np.uint8)
- with gfile.Open(img_file, 'w') as f:
- im = cv2.cvtColor(im, cv2.COLOR_RGB2BGR)
- _, im_data = cv2.imencode('.%s' % file_extension, im)
- f.write(im_data.tostring())
-
-
-def normalize_depth_for_display(depth, pc=95, crop_percent=0, normalizer=None,
- cmap=CMAP_DEFAULT):
- """Converts a depth map to an RGB image."""
- # Convert to disparity.
-
- disp = 1.0 / (depth + 1e-6)
- if normalizer is not None:
- disp /= normalizer
- else:
- disp /= (np.percentile(disp, pc) + 1e-6)
- disp = np.clip(disp, 0, 1)
- disp = gray2rgb(disp, cmap=cmap)
- keep_h = int(disp.shape[0] * (1 - crop_percent))
- disp = disp[:keep_h]
- return disp
-
-
-def get_seq_start_end(target_index, seq_length, sample_every=1):
- """Returns absolute seq start and end indices for a given target frame."""
- half_offset = int((seq_length - 1) / 2) * sample_every
- end_index = target_index + half_offset
- start_index = end_index - (seq_length - 1) * sample_every
- return start_index, end_index
-
-
-def get_seq_middle(seq_length):
- """Returns relative index for the middle frame in sequence."""
- half_offset = int((seq_length - 1) / 2)
- return seq_length - 1 - half_offset
-
-
-def info(obj):
- """Return info on shape and dtype of a numpy array or TensorFlow tensor."""
- if obj is None:
- return 'None.'
- elif isinstance(obj, list):
- if obj:
- return 'List of %d... %s' % (len(obj), info(obj[0]))
- else:
- return 'Empty list.'
- elif isinstance(obj, tuple):
- if obj:
- return 'Tuple of %d... %s' % (len(obj), info(obj[0]))
- else:
- return 'Empty tuple.'
- else:
- if is_a_numpy_array(obj):
- return 'Array with shape: %s, dtype: %s' % (obj.shape, obj.dtype)
- else:
- return str(obj)
-
-
-def is_a_numpy_array(obj):
- """Returns true if obj is a numpy array."""
- return type(obj).__module__ == np.__name__
-
-
-def count_parameters(also_print=True):
- """Cound the number of parameters in the model.
-
- Args:
- also_print: Boolean. If True also print the numbers.
-
- Returns:
- The total number of parameters.
- """
- total = 0
- if also_print:
- logging.info('Model Parameters:')
- for (_, v) in get_vars_to_save_and_restore().items():
- shape = v.get_shape()
- if also_print:
- logging.info('%s %s: %s', v.op.name, shape,
- format_number(shape.num_elements()))
- total += shape.num_elements()
- if also_print:
- logging.info('Total: %s', format_number(total))
- return total
-
-
-def get_vars_to_save_and_restore(ckpt=None):
- """Returns list of variables that should be saved/restored.
-
- Args:
- ckpt: Path to existing checkpoint. If present, returns only the subset of
- variables that exist in given checkpoint.
-
- Returns:
- List of all variables that need to be saved/restored.
- """
- model_vars = tf.trainable_variables()
- # Add batchnorm variables.
- bn_vars = [v for v in tf.global_variables()
- if 'moving_mean' in v.op.name or 'moving_variance' in v.op.name or
- 'mu' in v.op.name or 'sigma' in v.op.name or
- 'global_scale_var' in v.op.name]
- model_vars.extend(bn_vars)
- model_vars = sorted(model_vars, key=lambda x: x.op.name)
- mapping = {}
- if ckpt is not None:
- ckpt_var = tf.contrib.framework.list_variables(ckpt)
- ckpt_var_names = [name for (name, unused_shape) in ckpt_var]
- ckpt_var_shapes = [shape for (unused_name, shape) in ckpt_var]
- not_loaded = list(ckpt_var_names)
- for v in model_vars:
- if v.op.name not in ckpt_var_names:
- # For backward compatibility, try additional matching.
- v_additional_name = v.op.name.replace('egomotion_prediction/', '')
- if v_additional_name in ckpt_var_names:
- # Check if shapes match.
- ind = ckpt_var_names.index(v_additional_name)
- if ckpt_var_shapes[ind] == v.get_shape():
- mapping[v_additional_name] = v
- not_loaded.remove(v_additional_name)
- continue
- else:
- logging.warn('Shape mismatch, will not restore %s.', v.op.name)
- logging.warn('Did not find var %s in checkpoint: %s', v.op.name,
- os.path.basename(ckpt))
- else:
- # Check if shapes match.
- ind = ckpt_var_names.index(v.op.name)
- if ckpt_var_shapes[ind] == v.get_shape():
- mapping[v.op.name] = v
- not_loaded.remove(v.op.name)
- else:
- logging.warn('Shape mismatch, will not restore %s.', v.op.name)
- if not_loaded:
- logging.warn('The following variables in the checkpoint were not loaded:')
- for varname_not_loaded in not_loaded:
- logging.info('%s', varname_not_loaded)
- else: # just get model vars.
- for v in model_vars:
- mapping[v.op.name] = v
- return mapping
-
-
-def get_imagenet_vars_to_restore(imagenet_ckpt):
- """Returns dict of variables to restore from ImageNet-checkpoint."""
- vars_to_restore_imagenet = {}
- ckpt_var_names = tf.contrib.framework.list_variables(imagenet_ckpt)
- ckpt_var_names = [name for (name, unused_shape) in ckpt_var_names]
- model_vars = tf.global_variables()
- for v in model_vars:
- if 'global_step' in v.op.name: continue
- mvname_noprefix = v.op.name.replace('depth_prediction/', '')
- mvname_noprefix = mvname_noprefix.replace('moving_mean', 'mu')
- mvname_noprefix = mvname_noprefix.replace('moving_variance', 'sigma')
- if mvname_noprefix in ckpt_var_names:
- vars_to_restore_imagenet[mvname_noprefix] = v
- else:
- logging.info('The following variable will not be restored from '
- 'pretrained ImageNet-checkpoint: %s', mvname_noprefix)
- return vars_to_restore_imagenet
-
-
-def format_number(n):
- """Formats number with thousands commas."""
- locale.setlocale(locale.LC_ALL, 'en_US')
- return locale.format('%d', n, grouping=True)
-
-
-def atoi(text):
- return int(text) if text.isdigit() else text
-
-
-def natural_keys(text):
- return [atoi(c) for c in re.split(r'(\d+)', text)]
-
-
-def read_text_lines(filepath):
- with tf.gfile.Open(filepath, 'r') as f:
- lines = f.readlines()
- lines = [l.rstrip() for l in lines]
- return lines
diff --git a/research/swivel/.gitignore b/research/swivel/.gitignore
deleted file mode 100644
index 215593fb25dfe5862662aafcade225a7c9d62b83..0000000000000000000000000000000000000000
--- a/research/swivel/.gitignore
+++ /dev/null
@@ -1,14 +0,0 @@
-*.an.tab
-*.pyc
-*.ws.tab
-MEN.tar.gz
-Mtruk.csv
-SimLex-999.zip
-analogy
-fastprep
-*.dSYM
-questions-words.txt
-word_relationship.*
-tensorflow/
-rw.zip
-ws353simrel.tar.gz
diff --git a/research/swivel/README.md b/research/swivel/README.md
deleted file mode 100644
index c5550a2d18ccabdc22dc271c5b0515b233497068..0000000000000000000000000000000000000000
--- a/research/swivel/README.md
+++ /dev/null
@@ -1,185 +0,0 @@
-
-
-
-
-# Swivel in Tensorflow
-
-This is a [TensorFlow](http://www.tensorflow.org/) implementation of the
-[Swivel algorithm](http://arxiv.org/abs/1602.02215) for generating word
-embeddings.
-
-Swivel works as follows:
-
-1. Compute the co-occurrence statistics from a corpus; that is, determine how
- often a word *c* appears the context (e.g., "within ten words") of a focus
- word *f*. This results in a sparse *co-occurrence matrix* whose rows
- represent the focus words, and whose columns represent the context
- words. Each cell value is the number of times the focus and context words
- were observed together.
-2. Re-organize the co-occurrence matrix and chop it into smaller pieces.
-3. Assign a random *embedding vector* of fixed dimension (say, 300) to each
- focus word and to each context word.
-4. Iteratively attempt to approximate the
- [pointwise mutual information](https://en.wikipedia.org/wiki/Pointwise_mutual_information)
- (PMI) between words with the dot product of the corresponding embedding
- vectors.
-
-Note that the resulting co-occurrence matrix is very sparse (i.e., contains many
-zeros) since most words won't have been observed in the context of other words.
-In the case of very rare words, it seems reasonable to assume that you just
-haven't sampled enough data to spot their co-occurrence yet. On the other hand,
-if we've failed to observed two common words co-occuring, it seems likely that
-they are *anti-correlated*.
-
-Swivel attempts to capture this intuition by using both the observed and the
-un-observed co-occurrences to inform the way it iteratively adjusts vectors.
-Empirically, this seems to lead to better embeddings, especially for rare words.
-
-# Contents
-
-This release includes the following programs.
-
-* `prep.py` is a program that takes a text corpus and pre-processes it for
- training. Specifically, it computes a vocabulary and token co-occurrence
- statistics for the corpus. It then outputs the information into a format that
- can be digested by the TensorFlow trainer.
-* `swivel.py` is a TensorFlow program that generates embeddings from the
- co-occurrence statistics. It uses the files created by `prep.py` as input,
- and generates two text files as output: the row and column embeddings.
-* `distributed.sh` is a Bash script that is meant to act as a template for
- launching "distributed" Swivel training; i.e., multiple processes that work in
- parallel and communicate via a parameter server.
-* `text2bin.py` combines the row and column vectors generated by Swivel into a
- flat binary file that can be quickly loaded into memory to perform vector
- arithmetic. This can also be used to convert embeddings from
- [Glove](http://nlp.stanford.edu/projects/glove/) and
- [word2vec](https://code.google.com/archive/p/word2vec/) into a form that can
- be used by the following tools.
-* `nearest.py` is a program that you can use to manually inspect binary
- embeddings.
-* `eval.mk` is a GNU makefile that fill retrieve and normalize several common
- word similarity and analogy evaluation data sets.
-* `wordsim.py` performs word similarity evaluation of the resulting vectors.
-* `analogy` performs analogy evaluation of the resulting vectors.
-* `fastprep` is a C++ program that works much more quickly that `prep.py`, but
- also has some additional dependencies to build.
-
-# Building Embeddings with Swivel
-
-To build your own word embeddings with Swivel, you'll need the following:
-
-* A large corpus of text; for example, the
- [dump of English Wikipedia](https://dumps.wikimedia.org/enwiki/).
-* A working [TensorFlow](http://www.tensorflow.org/) implementation.
-* A machine with plenty of disk space and, ideally, a beefy GPU card. (We've
- experimented with the
- [Nvidia Titan X](http://www.geforce.com/hardware/desktop-gpus/geforce-gtx-titan-x),
- for example.)
-
-You'll then run `prep.py` (or `fastprep`) to prepare the data for Swivel and run
-`swivel.py` to create the embeddings. The resulting embeddings will be output
-into two large text files: one for the row vectors and one for the column
-vectors. You can use those "as is", or convert them into a binary file using
-`text2bin.py` and then use the tools here to experiment with the resulting
-vectors.
-
-## Preparing the data for training
-
-Once you've downloaded the corpus (e.g., to `/tmp/wiki.txt`), run `prep.py` to
-prepare the data for training:
-
- ./prep.py --output_dir /tmp/swivel_data --input /tmp/wiki.txt
-
-By default, `prep.py` will make one pass through the text file to compute a
-"vocabulary" of the most frequent words, and then a second pass to compute the
-co-occurrence statistics. The following options allow you to control this
-behavior:
-
-| Option | Description |
-|:--- |:--- |
-| `--min_count ` | Only include words in the generated vocabulary that appear at least *n* times. |
-| `--max_vocab ` | Admit at most *n* words into the vocabulary. |
-| `--vocab ` | Use the specified filename as the vocabulary instead of computing it from the corpus. The file should contain one word per line. |
-
-The `prep.py` program is pretty simple. Notably, it does almost no text
-processing: it does no case translation and simply breaks text into tokens by
-splitting on spaces. Feel free to experiment with the `words` function if you'd
-like to do something more sophisticated.
-
-Unfortunately, `prep.py` is pretty slow. Also included is `fastprep`, a C++
-equivalent that works much more quickly. Building `fastprep.cc` is a bit more
-involved: it requires you to pull and build the Tensorflow source code in order
-to provide the libraries and headers that it needs. See `fastprep.mk` for more
-details.
-
-## Training the embeddings
-
-When `prep.py` completes, it will have produced a directory containing the data
-that the Swivel trainer needs to run. Train embeddings as follows:
-
- ./swivel.py --input_base_path /tmp/swivel_data \
- --output_base_path /tmp/swivel_data
-
-There are a variety of parameters that you can fiddle with to customize the
-embeddings; some that you may want to experiment with include:
-
-| Option | Description |
-|:--- |:--- |
-| `--embedding_size ` | The dimensionality of the embeddings that are created. By default, 300 dimensional embeddings are created. |
-| `--num_epochs ` | The number of iterations through the data that are performed. By default, 40 epochs are trained. |
-
-As mentioned above, access to beefy GPU will dramatically reduce the amount of
-time it takes Swivel to train embeddings.
-
-When complete, you should find `row_embeddings.tsv` and `col_embedding.tsv` in
-the directory specified by `--ouput_base_path`. These files are tab-delimited
-files that contain one embedding per line. Each line contains the token
-followed by *dim* floating point numbers.
-
-## Exploring and evaluating the embeddings
-
-There are also some simple tools you can to explore the embeddings. These tools
-work with a simple binary vector format that can be `mmap`-ed into memory along
-with a separate vocabulary file. Use `text2bin.py` to generate these files:
-
- ./text2bin.py -o vecs.bin -v vocab.txt /tmp/swivel_data/*_embedding.tsv
-
-You can do some simple exploration using `nearest.py`:
-
- ./nearest.py -v vocab.txt -e vecs.bin
- query> dog
- dog
- dogs
- cat
- ...
- query> man woman king
- king
- queen
- princess
- ...
-
-To evaluate the embeddings using common word similarity and analogy datasets,
-use `eval.mk` to retrieve the data sets and build the tools. Note that wordsim is currently not compatible with Python 3.x.
-
- make -f eval.mk
- ./wordsim.py --vocab vocab.txt --embeddings vecs.bin *.ws.tab
- ./analogy --vocab vocab.txt --embeddings vecs.bin *.an.tab
-
-The word similarity evaluation compares the embeddings' estimate of "similarity"
-with human judgement using
-[Spearman's rho](https://en.wikipedia.org/wiki/Spearman%27s_rank_correlation_coefficient)
-as the measure of correlation. (Bigger numbers are better.)
-
-The analogy evaluation tests how well the embeddings can predict analogies like
-"man is to woman as king is to queen".
-
-Note that `eval.mk` forces all evaluation data into lower case. From there,
-both the word similarity and analogy evaluations assume that the eval data and
-the embeddings use consistent capitalization: if you train embeddings using
-mixed case and evaluate them using lower case, things won't work well.
-
-# Contact
-
-If you have any questions about Swivel, feel free to post to
-[swivel-embeddings@googlegroups.com](https://groups.google.com/forum/#!forum/swivel-embeddings).
-
diff --git a/research/swivel/analogy.cc b/research/swivel/analogy.cc
deleted file mode 100644
index 5a3ff9b3b3b46faa4bad255ddb282cc9478331bd..0000000000000000000000000000000000000000
--- a/research/swivel/analogy.cc
+++ /dev/null
@@ -1,365 +0,0 @@
-/* -*- Mode: C++ -*- */
-
-/*
- * Copyright 2016 Google Inc. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * Computes embedding performance on analogy tasks. Accepts as input one or
- * more files containing four words per line (A B C D), and determines if:
- *
- * vec(C) - vec(A) + vec(B) ~= vec(D)
- *
- * Cosine distance in the embedding space is used to retrieve neighbors. Any
- * missing vocabulary items are scored as losses.
- */
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-
-static const char usage[] = R"(
-Performs analogy testing of embedding vectors.
-
-Usage:
-
- analogy --embeddings --vocab eval1.tab ...
-
-Options:
-
- --embeddings
- The file containing the binary embedding vectors to evaluate.
-
- --vocab
- The vocabulary file corresponding to the embedding vectors.
-
- --nthreads
- The number of evaluation threads to run (default: 8)
-)";
-
-// Reads the vocabulary file into a map from token to vector index.
-static std::unordered_map ReadVocab(
- const std::string& vocab_filename) {
- std::unordered_map vocab;
- std::ifstream fin(vocab_filename);
-
- int index = 0;
- for (std::string token; std::getline(fin, token); ++index) {
- auto n = token.find('\t');
- if (n != std::string::npos) token = token.substr(n);
-
- vocab[token] = index;
- }
-
- return vocab;
-}
-
-// An analogy query: "A is to B as C is to D".
-typedef std::tuple AnalogyQuery;
-
-std::vector ReadQueries(
- const std::string &filename,
- const std::unordered_map &vocab, int *total) {
- std::ifstream fin(filename);
-
- std::vector queries;
- int lineno = 0;
- while (1) {
- // Read the four words.
- std::string words[4];
- int nread = 0;
- for (int i = 0; i < 4; ++i) {
- fin >> words[i];
- if (!words[i].empty()) ++nread;
- }
-
- ++lineno;
- if (nread == 0) break;
-
- if (nread < 4) {
- std::cerr << "expected four words at line " << lineno << std::endl;
- break;
- }
-
- // Look up each word's index.
- int ixs[4], nvalid;
- for (nvalid = 0; nvalid < 4; ++nvalid) {
- std::unordered_map::const_iterator it =
- vocab.find(words[nvalid]);
-
- if (it == vocab.end()) break;
-
- ixs[nvalid] = it->second;
- }
-
- // If we don't have all the words, count it as a loss.
- if (nvalid >= 4)
- queries.push_back(std::make_tuple(ixs[0], ixs[1], ixs[2], ixs[3]));
- }
-
- *total = lineno;
- return queries;
-}
-
-
-// A thread that evaluates some fraction of the analogies.
-class AnalogyEvaluator {
- public:
- // Creates a new Analogy evaluator for a range of analogy queries.
- AnalogyEvaluator(std::vector::const_iterator begin,
- std::vector::const_iterator end,
- const float *embeddings, const int num_embeddings,
- const int dim)
- : begin_(begin),
- end_(end),
- embeddings_(embeddings),
- num_embeddings_(num_embeddings),
- dim_(dim) {}
-
- // A thunk for pthreads.
- static void* Run(void *param) {
- AnalogyEvaluator *self = static_cast(param);
- self->Evaluate();
- return nullptr;
- }
-
- // Evaluates the analogies.
- void Evaluate();
-
- // Returns the number of correct analogies after evaluation is complete.
- int GetNumCorrect() const { return correct_; }
-
- protected:
- // The beginning of the range of queries to consider.
- std::vector::const_iterator begin_;
-
- // The end of the range of queries to consider.
- std::vector::const_iterator end_;
-
- // The raw embedding vectors.
- const float *embeddings_;
-
- // The number of embedding vectors.
- const int num_embeddings_;
-
- // The embedding vector dimensionality.
- const int dim_;
-
- // The number of correct analogies.
- int correct_;
-};
-
-
-void AnalogyEvaluator::Evaluate() {
- float* sum = new float[dim_];
-
- correct_ = 0;
- for (auto query = begin_; query < end_; ++query) {
- const float* vec;
- int a, b, c, d;
- std::tie(a, b, c, d) = *query;
-
- // Compute C - A + B.
- vec = embeddings_ + dim_ * c;
- for (int i = 0; i < dim_; ++i) sum[i] = vec[i];
-
- vec = embeddings_ + dim_ * a;
- for (int i = 0; i < dim_; ++i) sum[i] -= vec[i];
-
- vec = embeddings_ + dim_ * b;
- for (int i = 0; i < dim_; ++i) sum[i] += vec[i];
-
- // Find the nearest neighbor that isn't one of the query words.
- int best_ix = -1;
- float best_dot = -1.0;
- for (int i = 0; i < num_embeddings_; ++i) {
- if (i == a || i == b || i == c) continue;
-
- vec = embeddings_ + dim_ * i;
-
- float dot = 0;
- for (int j = 0; j < dim_; ++j) dot += vec[j] * sum[j];
-
- if (dot > best_dot) {
- best_ix = i;
- best_dot = dot;
- }
- }
-
- // The fourth word is the answer; did we get it right?
- if (best_ix == d) ++correct_;
- }
-
- delete[] sum;
-}
-
-
-int main(int argc, char *argv[]) {
- if (argc <= 1) {
- printf(usage);
- return 2;
- }
-
- std::string embeddings_filename, vocab_filename;
- int nthreads = 8;
-
- std::vector input_filenames;
- std::vector> queries;
-
- for (int i = 1; i < argc; ++i) {
- std::string arg = argv[i];
- if (arg == "--embeddings") {
- if (++i >= argc) goto argmissing;
- embeddings_filename = argv[i];
- } else if (arg == "--vocab") {
- if (++i >= argc) goto argmissing;
- vocab_filename = argv[i];
- } else if (arg == "--nthreads") {
- if (++i >= argc) goto argmissing;
- if ((nthreads = atoi(argv[i])) <= 0) goto badarg;
- } else if (arg == "--help") {
- std::cout << usage << std::endl;
- return 0;
- } else if (arg[0] == '-') {
- std::cerr << "unknown option: '" << arg << "'" << std::endl;
- return 2;
- } else {
- input_filenames.push_back(arg);
- }
-
- continue;
-
- argmissing:
- std::cerr << "missing value for '" << argv[i - 1] << "' (--help for help)"
- << std::endl;
- return 2;
-
- badarg:
- std::cerr << "invalid value '" << argv[i] << "' for '" << argv[i - 1]
- << "' (--help for help)" << std::endl;
-
- return 2;
- }
-
- // Read the vocabulary.
- std::unordered_map vocab = ReadVocab(vocab_filename);
- if (!vocab.size()) {
- std::cerr << "unable to read vocabulary file '" << vocab_filename << "'"
- << std::endl;
- return 1;
- }
-
- const int n = vocab.size();
-
- // Read the vectors.
- int fd;
- if ((fd = open(embeddings_filename.c_str(), O_RDONLY)) < 0) {
- std::cerr << "unable to open embeddings file '" << embeddings_filename
- << "'" << std::endl;
- return 1;
- }
-
- off_t nbytes = lseek(fd, 0, SEEK_END);
- if (nbytes == -1) {
- std::cerr << "unable to determine file size for '" << embeddings_filename
- << "'" << std::endl;
- return 1;
- }
-
- if (nbytes % (sizeof(float) * n) != 0) {
- std::cerr << "'" << embeddings_filename
- << "' has a strange file size; expected it to be "
- "a multiple of the vocabulary size"
- << std::endl;
-
- return 1;
- }
-
- const int dim = nbytes / (sizeof(float) * n);
- float *embeddings = static_cast