# Path: deployment/model_deploy.py
# def get_available_gpus():
#   def __init__(self, var_device, clone_device):
#   def choose(self, op):
# def create_clones(config, model_fn, args=None, kwargs=None, gpu_offset=0):
# def create_extra_clones_on_another_gpu(config, model_fn, args=None, kwargs=None):
# def _gather_clone_loss(clone, num_clones, regularization_losses):
# def _optimize_clone(optimizer, clone, num_clones, regularization_losses,
#                     **kwargs):
# def optimize_clones(clones, optimizer,
#                     regularization_losses=None,
#                     **kwargs):
# def deploy(config,
#            model_fn,
#            args=None,
#            kwargs=None,
#            optimizer=None,
#            summarize_gradients=False):
# def _sum_clones_gradients(clone_grads):
# def _add_gradients_summaries(grads_and_vars):
#   def __init__(self,
#                num_clones=1,
#                clone_on_cpu=False,
#                replica_id=0,
#                num_replicas=1,
#                num_ps_tasks=0,
#                worker_job_name='worker',
#                ps_job_name='ps'):
#   def num_clones(self):
#   def clone_on_cpu(self):
#   def replica_id(self):
#   def num_replicas(self):
#   def num_ps_tasks(self):
#   def ps_device(self):
#   def worker_device(self):
#   def caching_device(self):
#   def clone_device(self, clone_index, force=False):
#   def clone_scope(self, clone_index):
#   def optimizer_device(self):
#   def inputs_device(self):
#   def variables_device(self):
#       def __init__(self, device, tasks):
#       def choose(self, op):
# class VariableDeviceChooser(object):
# class DeploymentConfig(object):
#     class _PSDeviceChooser(object):
# 
# Path: deployment/train_util.py
# FLAGS = tf.app.flags.FLAGS
# def _configure_learning_rate(global_step):
# def _configure_optimizer(learning_rate):
# def _add_variables_summaries(learning_rate):
# def _load_weights():
# def _get_init_fn(variables_to_restore):
#         def init_with_weight(sess):
# def _get_variables_to_restore():
# def _get_variables_to_train():
# 
# Path: nets/nets_factory.py
# def get_network_fn(name, num_classes, weight_decay=0.0, is_training=False):
#   def network_fn(images):
#     def rnn_part(images):
# 
# Path: preprocessing/preprocessing_factory.py
# def get_preprocessing(name, is_training=False):
#   def preprocessing_fn(image, output_height, output_width, **kwargs):


import tensorflow as tf
import numpy as np
import time
import os
import math
import async_loader
from datetime import datetime
from tensorflow.python.ops import control_flow_ops
from deployment import model_deploy
from deployment import train_util
from nets import nets_factory
from preprocessing import preprocessing_factory
                end_point_outputs.remove(end_point_output)
                labels = split_rnn_labels[0]
                split_rnn_labels.remove(labels)
                logits, end_points = network_fn.rnn_part(cnn_output)
                end_points.update(end_point_output)
                #############################
                # Specify the loss function #
                #############################
                tf.losses.softmax_cross_entropy(
                            logits=logits, onehot_labels=labels, label_smoothing=FLAGS.label_smoothing, weights=1.0)
                return end_points
            # Run BN part, CNN and RNN should have different labels because of the different sample order
            model_deploy.create_clones(deploy_config, clone_bn_part,
                                       [split_images, split_cnn_labels, cnn_outputs, end_point_outputs],
                                       gpu_offset=1)
            # Merge on another GPU to avoid transport data back to original GPUs
            assert len(model_deploy.get_available_gpus()) > deploy_config.num_clones
            with tf.device(deploy_config.clone_device(0)):
                # Concat all clones to one tensor
                cnn_outputs = tf.concat(values=cnn_outputs, axis=0)
                output_shape = cnn_outputs.get_shape().as_list()
                # Reshape to expose the video number dimension
                cnn_outputs = tf.reshape(cnn_outputs, [FLAGS.n_steps, total_video_num]+output_shape[1:])
                # Split in the video number dimension, so that each clone has an input for lstm
                cnn_outputs = tf.split(cnn_outputs, deploy_config.num_clones, 1)
                # Merge n_steps and video number dimension
                cnn_outputs = [tf.reshape(output, [-1]+output_shape[1:]) for output in cnn_outputs]
            # Run RNN part on another GPU #deploy_config.num_clones
            #  clones = model_deploy.create_extra_clones_on_another_gpu(deploy_config, clone_rnn,
                                                #  [cnn_outputs, split_rnn_labels, end_point_outputs])

# Path: deployment/model_deploy.py
# def get_available_gpus():
#   def __init__(self, var_device, clone_device):
#   def choose(self, op):
# def create_clones(config, model_fn, args=None, kwargs=None, gpu_offset=0):
# def create_extra_clones_on_another_gpu(config, model_fn, args=None, kwargs=None):
# def _gather_clone_loss(clone, num_clones, regularization_losses):
# def _optimize_clone(optimizer, clone, num_clones, regularization_losses,
#                     **kwargs):
# def optimize_clones(clones, optimizer,
#                     regularization_losses=None,
#                     **kwargs):
# def deploy(config,
#            model_fn,
#            args=None,
#            kwargs=None,
#            optimizer=None,
#            summarize_gradients=False):
# def _sum_clones_gradients(clone_grads):
# def _add_gradients_summaries(grads_and_vars):
#   def __init__(self,
#                num_clones=1,
#                clone_on_cpu=False,
#                replica_id=0,
#                num_replicas=1,
#                num_ps_tasks=0,
#                worker_job_name='worker',
#                ps_job_name='ps'):
#   def num_clones(self):
#   def clone_on_cpu(self):
#   def replica_id(self):
#   def num_replicas(self):
#   def num_ps_tasks(self):
#   def ps_device(self):
#   def worker_device(self):
#   def caching_device(self):
#   def clone_device(self, clone_index, force=False):
#   def clone_scope(self, clone_index):
#   def optimizer_device(self):
#   def inputs_device(self):
#   def variables_device(self):
#       def __init__(self, device, tasks):
#       def choose(self, op):
# class VariableDeviceChooser(object):
# class DeploymentConfig(object):
#     class _PSDeviceChooser(object):
# 
# Path: deployment/train_util.py
# FLAGS = tf.app.flags.FLAGS
# def _configure_learning_rate(global_step):
# def _configure_optimizer(learning_rate):
# def _add_variables_summaries(learning_rate):
# def _load_weights():
# def _get_init_fn(variables_to_restore):
#         def init_with_weight(sess):
# def _get_variables_to_restore():
# def _get_variables_to_train():
# 
# Path: nets/nets_factory.py
# def get_network_fn(name, num_classes, weight_decay=0.0, is_training=False):
#   def network_fn(images):
#     def rnn_part(images):
# 
# Path: preprocessing/preprocessing_factory.py
# def get_preprocessing(name, is_training=False):
#   def preprocessing_fn(image, output_height, output_width, **kwargs):


# Path: train_video_classifier.py
import tensorflow as tf
import numpy as np
import time
import os
import math
import async_loader
from datetime import datetime
from tensorflow.python.ops import control_flow_ops
from deployment import model_deploy
from deployment import train_util
from nets import nets_factory
from preprocessing import preprocessing_factory

                end_point_outputs.remove(end_point_output)
                labels = split_rnn_labels[0]
                split_rnn_labels.remove(labels)
                logits, end_points = network_fn.rnn_part(cnn_output)
                end_points.update(end_point_output)
                #############################
                # Specify the loss function #
                #############################
                tf.losses.softmax_cross_entropy(
                            logits=logits, onehot_labels=labels, label_smoothing=FLAGS.label_smoothing, weights=1.0)
                return end_points
            # Run BN part, CNN and RNN should have different labels because of the different sample order
            model_deploy.create_clones(deploy_config, clone_bn_part,
                                       [split_images, split_cnn_labels, cnn_outputs, end_point_outputs],
                                       gpu_offset=1)
            # Merge on another GPU to avoid transport data back to original GPUs
            assert len(model_deploy.get_available_gpus()) > deploy_config.num_clones
            with tf.device(deploy_config.clone_device(0)):
                # Concat all clones to one tensor
                cnn_outputs = tf.concat(values=cnn_outputs, axis=0)
                output_shape = cnn_outputs.get_shape().as_list()
                # Reshape to expose the video number dimension
                cnn_outputs = tf.reshape(cnn_outputs, [FLAGS.n_steps, total_video_num]+output_shape[1:])
                # Split in the video number dimension, so that each clone has an input for lstm
                cnn_outputs = tf.split(cnn_outputs, deploy_config.num_clones, 1)
                # Merge n_steps and video number dimension
                cnn_outputs = [tf.reshape(output, [-1]+output_shape[1:]) for output in cnn_outputs]
            # Run RNN part on another GPU #deploy_config.num_clones
            #  clones = model_deploy.create_extra_clones_on_another_gpu(deploy_config, clone_rnn,
                                                #  [cnn_outputs, split_rnn_labels, end_point_outputs])

            clones = model_deploy.create_clones(deploy_config, clone_rnn,