# Copies signatures
# (c) MJMJ/2021

import tensorflow as tf
import tensorflow.keras.backend as K
import tensorflow_addons as tfa
import deepdish as dd
import os
import numpy as np
from nets.triplet_loss_all import TripletBatchAllLoss

# ===============================================================
# Version 1 of L1-smooth
HUBER_DELTA = 0.5


def mj_smoothL1(y_true, y_pred):
    x = K.abs(y_true - y_pred)
    x = K.switch(x < HUBER_DELTA, 0.5 * x ** 2, HUBER_DELTA * (x - 0.5 * HUBER_DELTA))
    return K.sum(x)


def mj_smoothL1ex(h_delta):
	def mj_smoothL1_(y_true, y_pred):
		x = K.abs(y_true - y_pred)
		x = K.switch(x < h_delta, 0.5 * x ** 2, h_delta * (x - 0.5 * h_delta))
		# return K.mean(x, axis=-1)
		return K.sum(x)
	return mj_smoothL1_


class GaitCopyModel():
	def __init__(self, experdir):
		self.model = None
		self.model_encode = None
		self.hist = None
		self.experdir = experdir

	def load(self, netpath, encode_layer=None, compile=True, gaitset=False):
		try:
			if gaitset:
				self.model = tf.keras.models.load_model(netpath, compile=compile, custom_objects={"MatMul": MatMul(),
																								  'tf': tf,
																								  "TripletBatchAllLoss": TripletBatchAllLoss()})
				encode_layer = "flatten"
			else:
				self.model = tf.keras.models.load_model(netpath, compile=compile, custom_objects={'mj_smoothL1': mj_smoothL1})
				print("++++++++++++++++++++++++++++++++++++++++++++")
				print("Model loaded from: " + netpath)
		except:
			# Load config file and build model.
			bdir = os.path.dirname(netpath)
			fconfig = os.path.join(bdir, "model-config.hdf5")
			netconfig = dd.io.load(fconfig)
			self.model = self.build_by_config(netconfig)

			# Load weights file.
			bname = os.path.basename(netpath)
			fparts = os.path.splitext(bname)
			filewes = os.path.join(bdir, fparts[0] + "_weights.hdf5")
			self.model.load_weights(filewes, by_name=True)

			print("++++++++++++++++++++++++++++++++++++++++++++")
			print("Model loaded from config + weight files: " + fconfig + '     ' + filewes)

		if encode_layer is None:
			self.model_encode = tf.keras.Model(self.model.input, self.model.layers[-1].input)
		else:
			out_layer = self.model.get_layer(encode_layer).output
			self.model_encode = tf.keras.Model(self.model.input, out_layer)

	def build_or_load(self, input_shape, number_convolutional_layers, filters_size, filters_numbers, strides,
	                  ndense_units=2048, weight_decay=0.0001, dropout=0.4, optimizer=tf.keras.optimizers.SGD(0.01, 0.9),
	                  nclasses=0, initnet="", freeze_convs=False, use3D=False, freeze_all=False, model_version='iwann', lstm=-1,
					  lstm_number=512, dropout_lstm=0.0, L2_norm_lstm=None, loss_mode='both', margin=0.25, loss_weights=[1.0, 0.1],
					  with_l2=False, kinit='glorot_uniform', drop_code=0, mobpars=None, hdelta=0.5):

		if initnet == "":
			build = self.build(input_shape, number_convolutional_layers, filters_size, filters_numbers, strides,
							   ndense_units, weight_decay, dropout, optimizer, nclasses, use3D=use3D,
							   model_version=model_version, lstm=lstm, lstm_number=lstm_number,
							   dropout_lstm=dropout_lstm, L2_norm_lstm=L2_norm_lstm, loss_mode=loss_mode, margin=margin,
							   loss_weights=loss_weights, with_l2=with_l2, kinit=kinit, drop_code=drop_code,
							   mobpars=mobpars)
		else:
			self.load(initnet)

			# Check if freeze some weights
			if freeze_convs or freeze_all:
				seq1 = self.model.get_layer("convBranch")

				for layer in seq1.layers:
					if freeze_all or type(layer) == tf.keras.layers.Conv2D or type(layer) == tf.keras.layers.Conv3D:
						layer.trainable = False

				for layer in self.model.layers:
					if freeze_all or type(layer) == tf.keras.layers.Dense:
						layer.trainable = False

			# Check if exists FC for classification:
			replace_fc = False
			for layer in self.model.layers:
				if layer.name == "probs":
					# Check number of classes.
					if layer.units != nclasses:
						print("Replacing FC layer for the new classes...")
						replace_fc = True

			if replace_fc:
				main_branch = self.model.layers[-1].input
				main_branch = tf.keras.layers.Dense(nclasses, activation='softmax', kernel_initializer='he_uniform',
				                                    name="probs")(main_branch)
				self.model = tf.keras.Model(inputs=self.model.input, outputs=main_branch)
				self.model.compile(optimizer=optimizer, loss='sparse_categorical_crossentropy',
				                   metrics=[tf.keras.metrics.SparseCategoricalAccuracy()])

			print("Alright")

	def build_by_config(self, netconfig):
		filters_size = netconfig["filters_size"]
		filters_numbers = netconfig["filters_numbers"]
		strides = netconfig["strides"]
		input_shape = netconfig["input_shape"]
		ndense_units = netconfig["ndense_units"]
		weight_decay = netconfig["weight_decay"]
		dropout = netconfig["dropout"]
		if "nclasses" in netconfig.keys():
			nclasses = netconfig["nclasses"]
		else:
			nclasses = 150
		optimizer = netconfig["optimizer"]

		if "use3D" in netconfig.keys():
			use3D = netconfig["use3D"]
		else:
			use3D = False

		if "drop_code" in netconfig.keys():
			drop_code = netconfig["drop_code"]
		else:
			drop_code = 0

		model_version = netconfig["model_version"]
		lstm = netconfig["lstm"]
		lstm_number = netconfig["lstm_number"]
		dropout_lstm = netconfig["dropout_lstm"]
		L2_norm_lstm = netconfig["L2_norm_lstm"]
		if "l2" in netconfig.keys():
			with_l2 = netconfig["l2"]
		else:
			with_l2 = False

		self.model = self.build(input_shape, len(filters_numbers), filters_size, filters_numbers, strides, ndense_units,
		                        weight_decay, dropout, nclasses=nclasses, optimizer=optimizer, use3D=use3D, model_version=model_version,
		                        lstm=lstm, lstm_number=lstm_number, dropout_lstm=dropout_lstm, L2_norm_lstm=L2_norm_lstm,
								with_l2=with_l2, drop_code=drop_code)

	def build(self, input_shape, number_convolutional_layers, filters_size, filters_numbers, strides, ndense_units=512,
	          weight_decay=0.0005, dropout=0.4, optimizer=tf.keras.optimizers.SGD(0.01, 0.9), nclasses=0, use3D=False,
			  model_version='iwann', lstm=-1,
			  lstm_number=512, dropout_lstm=0.0, L2_norm_lstm=None, loss_mode='MSE', margin=0.25, loss_weights=[1.0, 0.1],
			  with_l2=False, kinit='glorot_uniform', drop_code=0, mobpars=None, hdelta=0.5, cross=False):
		"""
		        :param input_shapes: tuple ((50,60,60), (25,60,60))
		        :param number_convolutional_layers:
		        :param filters_size:
		        :param filters_numbers:
		        :param ndense_units:
		        :param weight_decay:
		        :param dropout:
		        :param optimizer:
		        :param margin:
		        :return:
		        """

		if number_convolutional_layers < 1:
			print("ERROR: Number of convolutional layers must be greater than 0")

		outputs = []
		losses = []
		metrics = []

		if lstm == 0:
			input = tf.keras.layers.Input(shape=(None, input_shape[0], input_shape[1], input_shape[2]), name='input')
			lstm_layer = tf.keras.layers.ConvLSTM2D(16, 3, padding='same', data_format='channels_first')(input)
			input_shape = (16, input_shape[1], input_shape[2])
		elif lstm == 1 or lstm == 2:
			input = tf.keras.layers.Input(shape=(None, input_shape[0], input_shape[1], input_shape[2]), name='input')
			input_shape = (None, input_shape[0], input_shape[1], input_shape[2])
		elif lstm == 5:
			input = tf.keras.layers.Input(shape=(None, input_shape[0], input_shape[1], input_shape[2]), name='input')
			lstm_layer = tf.keras.layers.ConvLSTM2D(50, 3, padding='same', data_format='channels_first')(input)
			input_shape = (50, input_shape[1], input_shape[2])
		elif lstm == 6:
			input = tf.keras.layers.Input(shape=(None, input_shape[0], input_shape[1], input_shape[2]), name='input')
			lstm_layer = tf.keras.layers.ConvLSTM2D(16, 7, padding='same', data_format='channels_first')(input)
			input_shape = (16, input_shape[1], input_shape[2])
		elif lstm == 7:
			input = tf.keras.layers.Input(shape=(None, input_shape[0], input_shape[1], input_shape[2]), name='input')
			lstm_layer = tf.keras.layers.ConvLSTM2D(50, 7, padding='same', data_format='channels_first')(input)
			input_shape = (50, input_shape[1], input_shape[2])
		elif lstm >= 8:
			input = tf.keras.layers.Input(shape=(None, input_shape[0], input_shape[1], input_shape[2]), name='input')
			lstm_layer = tf.keras.layers.ConvLSTM2D(50, 3, padding='same', data_format='channels_first')(input)
			input_shape = [(50, input_shape[1], input_shape[2]), (None, input_shape[0], input_shape[1], input_shape[2])]
		else:
			input = tf.keras.layers.Input(shape=input_shape, name='input')
		if use3D:
			if model_version == 'bmvc' or model_version=='smallA' or model_version=='smallB' :
				convBranch = self.build_3Dbranch_Manuel("convBranch", input_shape, ndense_units, 
					                                    dropout=dropout, kernel_initializer=kinit, filters_size=filters_size,
					                                    filters_numbers=filters_numbers)
			elif model_version == "gaitset" or model_version == "gaitset_cross":
				convBranch = self.build_gaitset_branch(input_layer=input, input_shape=input_shape)
			else:
				convBranch = self.build_3Dbranch("convBranch", input_shape, number_convolutional_layers, filters_size, strides,
				                           filters_numbers, weight_decay, ndense_units, dropout)
		else:
			if model_version == 'bmvc':
				if lstm >= 8:
					lstm_branch1 = 5
					lstm_branch2 = 2
					convBranch1 = self.build_branch_Manuel("convBranch", input_shape[0], number_convolutional_layers,
					                                      filters_size, strides, filters_numbers, weight_decay,  ndense_units,
					                                       dropout, lstm_branch1, lstm_number, dropout_lstm, L2_norm_lstm, False)
					convBranch2 = self.build_branch_Manuel("convBranch2", input_shape[1], number_convolutional_layers,
					                                       filters_size, strides, filters_numbers, weight_decay, ndense_units,
					                                       dropout, lstm_branch2, lstm_number, dropout_lstm, L2_norm_lstm, False)
					convBranch = [convBranch1, convBranch2]
				else:
					convBranch = self.build_branch_Manuel("convBranch", input_shape, number_convolutional_layers, filters_size,
				                               strides, filters_numbers, weight_decay, ndense_units, dropout, lstm, lstm_number, dropout_lstm, L2_norm_lstm)
			elif model_version == 'bmvcfc':
				convBranch = self.build_branch_fc("convBranch", input_shape, number_convolutional_layers,
													  filters_size, strides, filters_numbers, weight_decay,
												  ndense_units, dropout)
				convBranch.summary()
			else:
				if lstm >= 8:
					lstm_branch1 = 5
					lstm_branch2 = 2
					convBranch1 = self.build_branch("convBranch", input_shape[0], number_convolutional_layers,
					                                filters_size, strides, filters_numbers, weight_decay, ndense_units,
					                                dropout, lstm_branch1, lstm_number, dropout_lstm, L2_norm_lstm, False)
					convBranch2 = self.build_branch("convBranch2", input_shape[1], number_convolutional_layers,
					                                filters_size, strides, filters_numbers, weight_decay, ndense_units,
					                                dropout, lstm_branch2, lstm_number, dropout_lstm, L2_norm_lstm, False)
					convBranch = [convBranch1, convBranch2]
				else:
					convBranch = self.build_branch("convBranch", input_shape, number_convolutional_layers, filters_size, strides,
				                           filters_numbers, weight_decay, ndense_units, dropout, lstm, lstm_number,
												   dropout_lstm, L2_norm_lstm, final_pool=False)

		if lstm == 0 or lstm == 5 or lstm == 6 or lstm == 7:
			output = convBranch(lstm_layer)
		elif lstm >= 8 and lstm <= 15:
			output1 = convBranch[0](lstm_layer)
			output2 = convBranch[1](input)

			if lstm == 10 or lstm == 15:
				# Add max layer
				output1 = tf.keras.layers.Lambda(lambda x: tf.math.l2_normalize(x, axis=1), name="embedL2_1")(output1)
				output2 = tf.keras.layers.Lambda(lambda x: tf.math.l2_normalize(x, axis=1), name="embedL2_2")(output2)

			# Add concat layer
			main_branch = tf.keras.layers.Concatenate(axis=1)([output1, output2])

			if lstm == 11 or lstm == 12 or lstm == 15:
				main_branch = tf.keras.layers.Dropout(dropout, name="drop_concat")(main_branch)

			if lstm != 9 and lstm != 12 and lstm != 15:
				# Add dense layer + dropout
				main_branch = tf.keras.layers.Dense(ndense_units * 2, name="dense")(main_branch)
				if dropout > 0:
					main_branch = tf.keras.layers.Dropout(dropout, name="drop")(main_branch)
			output = tf.keras.layers.Dense(ndense_units, name="code")(main_branch)

		else:
			if model_version != "gaitset" and model_version != "gaitset_cross":
				output = convBranch(input)
			else:
				output = convBranch

		if drop_code > 0:
			output = tf.keras.layers.Dropout(drop_code, name="drop_code")(output)

		outputs.append(output)

		if model_version == "gaitset_cross":
			outputs.append(output)
			output = tf.keras.layers.Dense(nclasses)(output)
			outputs.append(output)


		# main_branch = tf.keras.layers.Dense(1024, activation='linear', kernel_initializer='he_uniform',
		# 									name="signature")(output)
		if with_l2:
			l2norm_ = tf.keras.layers.Lambda(lambda x: tf.math.l2_normalize(x, axis=1), name="signature")(output)
			outputs.append(l2norm_)

		if loss_mode == "MSE":
			losses.append('mean_squared_error')
		elif loss_mode == "sL1":
			losses.append(mj_smoothL1)
		elif loss_mode == "sL1e" or loss_mode == "sL1x":
			losses.append(mj_smoothL1ex(hdelta))
		elif loss_mode == "Huber":
			losses.append(tf.keras.losses.Huber(delta=hdelta))
		elif loss_mode == "sL1tri":
			losses = [mj_smoothL1, tfa.losses.TripletSemiHardLoss(margin=margin)]
		elif loss_mode == "sL1triH":
			losses = [mj_smoothL1, tfa.losses.TripletHardLoss(margin=margin)]
		elif loss_mode == "sL1triB":
			losses = [mj_smoothL1, TripletBatchAllLoss(margin=margin)]
		else:
			print("ERROR: invalid loss mode - "+loss_mode)


		metrics.append(tf.keras.metrics.MeanAbsoluteError())
		metrics.append(tf.keras.metrics.MeanSquaredError())

		if model_version == "gaitset_cross":
			losses.append('sparse_categorical_crossentropy')
			metrics.append('accuracy')
			loss_weights.append(0.2)

		self.model = tf.keras.Model(inputs=input, outputs=outputs, name="copynet")
		#self.model.compile(optimizer=optimizer, loss=losses, loss_weights=loss_weights, metrics=metrics)

		# Save useful info for recovering the model with different Python versions
		modelpars = {'filters_size': filters_size,
		             'filters_numbers': filters_numbers,
		             'input_shape': input_shape,
		             'ndense_units': ndense_units,
		             'weight_decay': weight_decay,
		             'dropout': dropout,
		             'optimizer': optimizer,
		             'custom': 'TripletSemiHardLoss',
		             'nclasses': nclasses,
		             'use3D': use3D,
		             'model_version': model_version,
		             'loss_mode': loss_mode,
		             'loss_weights': loss_weights,
		             'margin': margin,
					 'l2': with_l2}
		#dd.io.save(os.path.join(self.experdir, "model-config.hdf5"), modelpars)

	def build_branch(self, name, input_shape=(50, 60, 60), number_convolutional_layers=4, filters_size=None,
	                 strides=None, filters_numbers=None, weight_decay=0.0005, ndense_units=4096, dropout=0.4, lstm=-1,
					 lstm_number=512, dropout_lstm=0.0, L2_norm_lstm=None, add_dense=True, final_pool=True):
		if filters_numbers is None:
			filters_numbers = [96, 192, 512, 4096]
		L2_norm = tf.keras.regularizers.l2(weight_decay)
		if L2_norm_lstm is not None:
			L2_norm_lstm = tf.keras.regularizers.l2(L2_norm_lstm)

		convBranch = tf.keras.Sequential(name=name)
		if lstm == 2:
			convBranch.add(tf.keras.layers.TimeDistributed(
				tf.keras.layers.Conv2D(filters_numbers[0], kernel_size=(filters_size[0]), strides=(strides[0]),
				                       kernel_regularizer=L2_norm, activation='relu', input_shape=input_shape,
				                       data_format='channels_first')))

			convBranch.add(tf.keras.layers.TimeDistributed(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), data_format='channels_first')))

			for i in range(1, number_convolutional_layers):
				convBranch.add(tf.keras.layers.TimeDistributed(
					tf.keras.layers.Conv2D(filters_numbers[i], kernel_size=(filters_size[i]), strides=(strides[i]),
					                       kernel_regularizer=L2_norm, activation='relu',
					                       data_format='channels_first')))

				convBranch.add(tf.keras.layers.TimeDistributed(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), data_format='channels_first')))

			convBranch.add(tf.keras.layers.TimeDistributed(tf.keras.layers.Flatten(name="flatten")))
			convBranch.add(tf.keras.layers.LSTM(lstm_number, dropout=dropout_lstm, kernel_regularizer=L2_norm_lstm))

			if add_dense:
				# Add dense layer + dropout
				convBranch.add(tf.keras.layers.Dense(ndense_units, name="dense"))
				if dropout > 0:
					convBranch.add(tf.keras.layers.Dropout(dropout, name="drop"))
		else:
			if lstm == 1:
				convBranch.add(tf.keras.layers.ConvLSTM2D(filters_numbers[0], kernel_size=(filters_size[0]), strides=(strides[0]),
					                       kernel_regularizer=L2_norm, input_shape=input_shape,
					                       data_format='channels_first'))
			else:
				convBranch.add(tf.keras.layers.Conv2D(filters_numbers[0], kernel_size=(filters_size[0]), strides=(strides[0]),
			                                    kernel_regularizer=L2_norm, activation='relu', input_shape=input_shape,
			                                    data_format='channels_first'))

			convBranch.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), data_format='channels_first'))

			for i in range(1, number_convolutional_layers):
				convBranch.add(tf.keras.layers.Conv2D(filters_numbers[i], kernel_size=(filters_size[i]), strides=(strides[i]),
				                                    kernel_regularizer=L2_norm, activation='relu',
				                                    data_format='channels_first'))

				# Needed for IWANN model:
				if (i < (number_convolutional_layers - 1)) or (i == (number_convolutional_layers - 1) and final_pool):
					convBranch.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), data_format='channels_first'))

			convBranch.add(tf.keras.layers.Flatten(name="flatten"))

			if add_dense:
				# Add dense layer + dropout
				convBranch.add(tf.keras.layers.Dense(ndense_units, name="dense"))
				if dropout > 0:
					convBranch.add(tf.keras.layers.Dropout(dropout, name="drop"))

		return convBranch

	def build_branch_Manuel(self, name, input_shape=(50, 60, 60), number_convolutional_layers=4, filters_size=None,
	                 strides=None, filters_numbers=None, weight_decay=0.0005, ndense_units=1024, dropout=0.4, lstm=-1,
							lstm_number=512, dropout_lstm=0.0, L2_norm_lstm=None, add_dense=True):
		if filters_numbers is None:
			filters_numbers = [96, 192, 512, 512]
		L2_norm = tf.keras.regularizers.l2(weight_decay)
		if L2_norm_lstm is not None:
			L2_norm_lstm = tf.keras.regularizers.l2(L2_norm_lstm)

		convBranch = tf.keras.Sequential(name=name)

		if lstm == 2:
			convBranch.add(tf.keras.layers.TimeDistributed(
				tf.keras.layers.Conv2D(filters_numbers[0], kernel_size=(filters_size[0]), strides=(strides[0]),
				                       kernel_regularizer=L2_norm, activation='relu', input_shape=input_shape,
				                       data_format='channels_first')))

			convBranch.add(tf.keras.layers.TimeDistributed(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), data_format='channels_first')))

			for i in range(1, number_convolutional_layers):
				convBranch.add(tf.keras.layers.TimeDistributed(
					tf.keras.layers.Conv2D(filters_numbers[i], kernel_size=(filters_size[i]), strides=(strides[i]),
					                       kernel_regularizer=L2_norm, activation='relu',
					                       data_format='channels_first')))

				#if i != number_convolutional_layers - 1:
				convBranch.add(tf.keras.layers.TimeDistributed(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), data_format='channels_first')))

			convBranch.add(tf.keras.layers.TimeDistributed(tf.keras.layers.Flatten(name="flatten")))
			convBranch.add(tf.keras.layers.LSTM(lstm_number, dropout=dropout_lstm, kernel_regularizer=L2_norm_lstm))

			if add_dense:
				# Add dense layer + dropout
				convBranch.add(tf.keras.layers.Dense(ndense_units * 2, name="dense"))
				if dropout > 0:
					convBranch.add(tf.keras.layers.Dropout(dropout, name="drop"))
				convBranch.add(tf.keras.layers.Dense(ndense_units, name="code"))
		else:
			if lstm == 1:
				convBranch.add(tf.keras.layers.ConvLSTM2D(filters_numbers[0], kernel_size=(filters_size[0]), strides=(strides[0]),
					                       kernel_regularizer=L2_norm, input_shape=input_shape,
					                       data_format='channels_first'))
			else:
				convBranch.add(tf.keras.layers.Conv2D(filters_numbers[0], kernel_size=(filters_size[0]), strides=(strides[0]),
			                                    kernel_regularizer=L2_norm, activation='relu', input_shape=input_shape,
			                                    data_format='channels_first'))

			convBranch.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), data_format='channels_first'))

			for i in range(1, number_convolutional_layers):
				convBranch.add(tf.keras.layers.Conv2D(filters_numbers[i], kernel_size=(filters_size[i]), strides=(strides[i]),
				                                    kernel_regularizer=L2_norm, activation='relu',
				                                    data_format='channels_first'))

				#if i != number_convolutional_layers - 1:
				convBranch.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), data_format='channels_first'))

			convBranch.add(tf.keras.layers.Flatten(name="flatten"))

			if add_dense:
				# Add dense layer + dropout
				convBranch.add(tf.keras.layers.Dense(ndense_units * 2, name="dense"))
				if dropout > 0:
					convBranch.add(tf.keras.layers.Dropout(dropout, name="drop"))
				convBranch.add(tf.keras.layers.Dense(ndense_units, name="code"))

		return convBranch

	# Fully-convolutional branch
	def build_branch_fc(self, name, input_shape=(50, 60, 60), number_convolutional_layers=4, filters_size=None,
	                    strides=None, filters_numbers=None, weight_decay=0.0005, ndense_units=1024, dropout=0.4):
		if filters_numbers is None:
			filters_numbers = [96, 192, 512, 512]
		L2_norm = tf.keras.regularizers.l2(weight_decay)

		convBranch = tf.keras.Sequential(name=name)

		convBranch.add(tf.keras.layers.Conv2D(filters_numbers[0], kernel_size=(filters_size[0]), strides=(strides[0]),
			                                    kernel_regularizer=L2_norm, activation='relu', input_shape=input_shape,
			                                    data_format='channels_first'))

		convBranch.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), data_format='channels_first'))

		for i in range(1, number_convolutional_layers):
			convBranch.add(tf.keras.layers.Conv2D(filters_numbers[i], kernel_size=(filters_size[i]), strides=(strides[i]),
				                                    kernel_regularizer=L2_norm, activation='relu',
				                                    data_format='channels_first'))

				#if i != number_convolutional_layers - 1:
			convBranch.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), data_format='channels_first'))

		# convBranch.add(tf.keras.layers.Flatten(name="flatten"))

		# Add dense layer + dropout
		# convBranch.add(tf.keras.layers.Dense(ndense_units * 2, name="dense"))
		convBranch.add(tf.keras.layers.Conv2D(ndense_units * 2, kernel_size=1, strides=1, name="fc1",
											  data_format='channels_first'))
		if dropout > 0:
			convBranch.add(tf.keras.layers.Dropout(dropout, name="drop"))
		convBranch.add(tf.keras.layers.Conv2D(ndense_units, kernel_size=1, strides=1, name="code0",
												  data_format='channels_first'))
		# 	convBranch.add(tf.keras.layers.Dense(ndense_units, name="code"))
		convBranch.add(tf.keras.layers.Flatten(name="code"))

		return convBranch

	def build_3Dbranch(self, name, input_shape=(50, 60, 60), number_convolutional_layers=4, filters_size=None,
	                 strides=None, filters_numbers=None, weight_decay=0.0005, ndense_units=4096, dropout=0.4):
		if filters_numbers is None:
			filters_numbers = [96, 192, 512, 4096]
		L2_norm = tf.keras.regularizers.l2(weight_decay)

		import pdb; pdb.set_trace()

		convBranch = tf.keras.Sequential(name=name)

		convBranch.add(tf.keras.layers.Conv3D(filters_numbers[0], kernel_size=(3, filters_size[0], filters_size[0]),
		                                      strides=(1, strides[0], strides[0]), kernel_regularizer=L2_norm,
		                                      activation='relu', input_shape=input_shape, data_format='channels_last'))

		convBranch.add(tf.keras.layers.MaxPooling3D(pool_size=(2, 2, 2), data_format='channels_last'))

		for i in range(1, number_convolutional_layers):
			convBranch.add(tf.keras.layers.Conv2D(filters_numbers[i], kernel_size=(3, filters_size[i], filters_size[i]),
			                                      strides=(1, strides[i], strides[i]), kernel_regularizer=L2_norm,
			                                      activation='relu', data_format='channels_last'))

			if i != number_convolutional_layers - 1:
				convBranch.add( tf.keras.layers.Conv2D(filters_numbers[i], kernel_size=(3, filters_size[i], filters_size[i]),
					                       strides=(1, strides[i], strides[i]), kernel_regularizer=L2_norm,
					                       activation='relu', data_format='channels_last'))

				convBranch.add(tf.keras.layers.MaxPooling2D(pool_size=(2, 2, 2), data_format='channels_last'))
			else:
				convBranch.add(tf.keras.layers.Conv2D(filters_numbers[i], kernel_size=(filters_size[i]),
					                       strides=(1, strides[i], strides[i]), kernel_regularizer=L2_norm,
					                       activation='relu', data_format='channels_last'))

		convBranch.add(tf.keras.layers.Flatten(name="flatten"))

		# Add dense layer + dropout
		convBranch.add(tf.keras.layers.Dense(ndense_units, name="dense"))
		if dropout > 0:
			convBranch.add(tf.keras.layers.Dropout(dropout, name="drop"))

		return convBranch

	def build_3Dbranch_Manuel(self, name, input_shape=(25, 60, 60, 1), ndense_units=512, 
		                      dropout=0.4, kernel_initializer='glorot_uniform', 
		                      filters_size = [(3, 5, 5), (3, 3, 3), (3, 3, 3), (3, 3, 3), (3, 2, 2), (2, 1, 1)], 
		                      filters_numbers = [64, 128, 256, 512, 512, 512]):
		convBranch = tf.keras.Sequential(name=name)

		convBranch.add(tf.keras.layers.Conv3D(filters_numbers[0], filters_size[0], strides=(1, 2, 2), padding='valid', activation='relu',
		                        input_shape=input_shape, data_format='channels_last', kernel_initializer=kernel_initializer))

		convBranch.add(tf.keras.layers.Conv3D(filters_numbers[1], filters_size[1], strides=(1, 2, 2), padding='valid', activation='relu',
		                        input_shape=input_shape, data_format='channels_last', kernel_initializer=kernel_initializer))

		convBranch.add(tf.keras.layers.Conv3D(filters_numbers[2], filters_size[2], strides=(2, 2, 2), padding='valid', activation='relu',
		                        input_shape=input_shape, data_format='channels_last', kernel_initializer=kernel_initializer))

		convBranch.add(tf.keras.layers.Conv3D(filters_numbers[3], filters_size[3], strides=(2, 2, 2), padding='valid', activation='relu',
		                        input_shape=input_shape, data_format='channels_last', kernel_initializer=kernel_initializer))

		convBranch.add(tf.keras.layers.Conv3D(filters_numbers[4], filters_size[4], strides=(1, 1, 1), padding='valid', activation='relu',
		                        input_shape=input_shape, data_format='channels_last', kernel_initializer=kernel_initializer))

		convBranch.add(tf.keras.layers.Conv3D(filters_numbers[5], filters_size[5], strides=(1, 1, 1), padding='valid', activation='relu',
		                        input_shape=input_shape, data_format='channels_last', kernel_initializer=kernel_initializer))

		if dropout > 0:
			convBranch.add(tf.keras.layers.Dropout(dropout, name="drop"))

		# Dense without activation function
		convBranch.add(tf.keras.layers.Conv3D(ndense_units, (1, 1, 1), strides=(1, 1, 1), activation=None,
		                        kernel_regularizer=tf.keras.regularizers.l2(1e-3),
		                        kernel_initializer='he_uniform', name="grayCode"))

		convBranch.add(tf.keras.layers.Flatten(name="code"))

		return convBranch

	def fit(self, epochs, callbacks, training_generator, validation_generator, current_step=0, validation_steps=None, encode_layer=None, steps_per_epoch=None):
		self.hist = self.model.fit(training_generator, validation_data=validation_generator, epochs=epochs,
		                           callbacks=callbacks, validation_steps=validation_steps, initial_epoch=current_step,
		                           verbose=1, steps_per_epoch=steps_per_epoch) #, workers=4, max_queue_size=10, use_multiprocessing=True)

		if encode_layer is None:
			self.model_encode = tf.keras.Model(self.model.input, self.model.layers[-1].input)
		else:
			out_layer = self.model.get_layer(encode_layer).output
			self.model_encode = tf.keras.Model(self.model.input, out_layer)
		return len(self.hist.epoch)

	def predict(self, data, batch_size=128):
		pred = self.model.predict(data, batch_size=batch_size)
		return pred

	def encode(self, data, reshape=False):
		# features = self.model_encode(data)
		if reshape:
			n_data = np.zeros(shape=(data.shape[0], 25, 60, 60, 2))
			for i in range(25):
				n_data[:, i, :, :, 0] = data[:, i*2, :, :]
				n_data[:, i, :, :, 1] = data[:, i*2+1, :, :]
			data = n_data
		features = self.model.predict(data)
		if isinstance(features, list):
			features = features[0]

		# L2 normalize embeddings
		codes_norm_tf = tf.keras.layers.Lambda(lambda x: tf.math.l2_normalize(x, axis=1))(features)

		# Get the numpy matrix
		codes_norm = codes_norm_tf.numpy()
		return codes_norm

	def save(self, epoch=None):
		if epoch is not None:
			self.model.save(os.path.join(self.experdir, "model-state-{:04d}.hdf5".format(epoch)))
		else:
			self.model.save(os.path.join(self.experdir, "model-final.hdf5"))

	def build_gaitset_branch(self, input_layer, input_shape=(25, 60, 60, 1)):
		branch_a = tf.keras.layers.TimeDistributed(tf.keras.layers.ZeroPadding2D(padding=4))(input_layer)
		branch_a = tf.keras.layers.TimeDistributed(
			tf.keras.layers.Conv2D(32, kernel_size=5, activation=None, padding='valid', use_bias=False,
						  data_format='channels_last'))(branch_a)
		branch_a = tf.keras.layers.TimeDistributed(tf.keras.layers.LeakyReLU())(branch_a)

		branch_a = tf.keras.layers.TimeDistributed(tf.keras.layers.ZeroPadding2D(padding=1))(branch_a)
		branch_a = tf.keras.layers.TimeDistributed(
			tf.keras.layers.Conv2D(32, kernel_size=3, activation=None, padding='valid', use_bias=False,
						  input_shape=input_shape, data_format='channels_last'))(branch_a)
		branch_a = tf.keras.layers.TimeDistributed(tf.keras.layers.LeakyReLU())(branch_a)
		branch_a = tf.keras.layers.TimeDistributed(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), data_format='channels_last'))(branch_a)

		branch_b = tf.keras.layers.Lambda(lambda x: tf.math.reduce_max(x, axis=1))(branch_a)
		branch_b = tf.keras.layers.ZeroPadding2D(padding=1)(branch_b)
		branch_b = tf.keras.layers.Conv2D(64, kernel_size=3, activation=None, padding='valid', use_bias=False,
								 data_format='channels_last')(branch_b)
		branch_b = tf.keras.layers.LeakyReLU()(branch_b)
		branch_b = tf.keras.layers.ZeroPadding2D(padding=1)(branch_b)
		branch_b = tf.keras.layers.Conv2D(64, kernel_size=3, activation=None, padding='valid', use_bias=False,
								 data_format='channels_last')(branch_b)
		branch_b = tf.keras.layers.LeakyReLU()(branch_b)
		branch_b = tf.keras.layers.MaxPooling2D(pool_size=(2, 2), data_format='channels_last')(branch_b)

		branch_a = tf.keras.layers.TimeDistributed(tf.keras.layers.ZeroPadding2D(padding=1))(branch_a)
		branch_a = tf.keras.layers.TimeDistributed(
			tf.keras.layers.Conv2D(64, kernel_size=3, activation=None, padding='valid', use_bias=False,
						  input_shape=input_shape, data_format='channels_last'))(branch_a)
		branch_a = tf.keras.layers.TimeDistributed(tf.keras.layers.LeakyReLU())(branch_a)

		branch_a = tf.keras.layers.TimeDistributed(tf.keras.layers.ZeroPadding2D(padding=1))(branch_a)
		branch_a = tf.keras.layers.TimeDistributed(
			tf.keras.layers.Conv2D(64, kernel_size=3, activation=None, padding='valid', use_bias=False,
						  input_shape=input_shape, data_format='channels_last'))(branch_a)
		branch_a = tf.keras.layers.TimeDistributed(tf.keras.layers.LeakyReLU())(branch_a)
		branch_a = tf.keras.layers.TimeDistributed(tf.keras.layers.MaxPooling2D(pool_size=(2, 2), data_format='channels_last'))(branch_a)

		branch_b_ = tf.keras.layers.Lambda(lambda x: tf.math.reduce_max(x, axis=1))(branch_a)
		branch_b = tf.keras.layers.Add()([branch_b, branch_b_])
		branch_b = tf.keras.layers.ZeroPadding2D(padding=1)(branch_b)
		branch_b = tf.keras.layers.Conv2D(128, kernel_size=3, activation=None, padding='valid', use_bias=False,
								 data_format='channels_last')(branch_b)
		branch_b = tf.keras.layers.LeakyReLU()(branch_b)
		branch_b = tf.keras.layers.ZeroPadding2D(padding=1)(branch_b)
		branch_b = tf.keras.layers.Conv2D(128, kernel_size=3, activation=None, padding='valid', use_bias=False,
								 data_format='channels_last')(branch_b)
		branch_b = tf.keras.layers.LeakyReLU()(branch_b)

		branch_a = tf.keras.layers.TimeDistributed(tf.keras.layers.ZeroPadding2D(padding=1))(branch_a)
		branch_a = tf.keras.layers.TimeDistributed(
			tf.keras.layers.Conv2D(128, kernel_size=3, activation=None, padding='valid', use_bias=False,
						  input_shape=input_shape, data_format='channels_last'))(branch_a)
		branch_a = tf.keras.layers.TimeDistributed(tf.keras.layers.LeakyReLU())(branch_a)

		branch_a = tf.keras.layers.TimeDistributed(tf.keras.layers.ZeroPadding2D(padding=1))(branch_a)
		branch_a = tf.keras.layers.TimeDistributed(
			tf.keras.layers.Conv2D(128, kernel_size=3, activation=None, padding='valid', use_bias=False,
						  input_shape=input_shape, data_format='channels_last'))(branch_a)
		branch_a = tf.keras.layers.TimeDistributed(tf.keras.layers.LeakyReLU())(branch_a)
		branch_a = tf.keras.layers.Lambda(lambda x: tf.math.reduce_max(x, axis=1))(branch_a)

		branch_b = tf.keras.layers.Add()([branch_b, branch_a])

		# HPP
		feature = list()
		bin_num = [1, 2, 4, 8, 16]
		# bin_num = [1, 16]
		n, h, w, c = branch_b.shape
		print(branch_b.shape)
		for num_bin in bin_num:
			branch_a_ = tf.keras.layers.Reshape((num_bin, -1, c))(branch_a)
			branch_a_ = tf.keras.layers.Lambda(lambda x: tf.math.reduce_mean(x, axis=2) + tf.math.reduce_max(x, axis=2))(
				branch_a_)
			feature.append(branch_a_)
			branch_b_ = tf.keras.layers.Reshape((num_bin, -1, c))(branch_b)
			branch_b_ = tf.keras.layers.Lambda(lambda x: tf.math.reduce_mean(x, axis=2) + tf.math.reduce_max(x, axis=2))(
				branch_b_)
			feature.append(branch_b_)

		model = tf.keras.layers.Concatenate(axis=1)(feature)
		model = tf.keras.layers.Lambda(lambda x: tf.transpose(x, [1, 0, 2]))(model)
		model = MatMul()(model)
		model = tf.keras.layers.Lambda(lambda x: tf.transpose(x, [1, 0, 2]))(model)
		model = tf.keras.layers.Flatten()(model)

		return model

class MatMul(tf.keras.layers.Layer):
    def __init__(self, bin_num=31, hidden_dim=128, **kwargs):
        super(MatMul, self).__init__(**kwargs)

        self.bin_num = bin_num
        self.hidden_dim = hidden_dim

        # Create a trainable weight variable for this layer.
        w_init = tf.keras.initializers.GlorotUniform()
        self.kernel = tf.Variable(name="MatMul_kernel" + str(np.random.randint(100, size=1)),
                                  initial_value=w_init(shape=(bin_num * 2, 128, hidden_dim), dtype="float32"),
                                  trainable=True)

    def call(self, x):
            # Implicit broadcasting occurs here.
            # Shape x: (BATCH_SIZE, N, M)
            # Shape kernel: (N, M)
            # Shape output: (BATCH_SIZE, N, M)
            return tf.matmul(x, self.kernel)

    def get_config(self):
        config = super().get_config().copy()
        config.update({
            'bin_num': self.bin_num,
            'hidden_dim': self.hidden_dim,
        })
        return config

tensorflow.keras.models.load_model tensorflow.keras.Sequential tensorflow.keras.layers.ConvLSTM2D tensorflow.keras.layers.ZeroPadding2D tensorflow.keras.initializers.GlorotUniform tensorflow.keras.optimizers.SGD tensorflow.keras.layers.Concatenate numpy.random.randint tensorflow.keras.layers.LeakyReLU tensorflow.keras.layers.MaxPooling3D tensorflow.keras.metrics.MeanSquaredError tensorflow.keras.regularizers.l2 tensorflow.keras.layers.Conv2D tensorflow.keras.layers.Conv3D tensorflow.keras.layers.Add numpy.zeros tensorflow.keras.layers.Flatten tensorflow.matmul tensorflow.math.reduce_max tensorflow.keras.layers.Dense tensorflow.math.l2_normalize tensorflow.keras.backend.sum tensorflow.keras.Model tensorflow.keras.backend.abs tensorflow.keras.losses.Huber tensorflow.keras.layers.Reshape tensorflow.keras.backend.switch tensorflow.transpose tensorflow.keras.metrics.SparseCategoricalAccuracy tensorflow.math.reduce_mean tensorflow.keras.layers.LSTM tensorflow.keras.metrics.MeanAbsoluteError tensorflow.keras.layers.Dropout tensorflow.keras.layers.MaxPooling2D tensorflow.keras.layers.Input
[(18, 'tensorflow.keras.backend.abs', 'K.abs', (['(y_true - y_pred)'], {}), True, 'import tensorflow.keras.backend as K\n'), (19, 'tensorflow.keras.backend.switch', 'K.switch', (['(x < HUBER_DELTA)', '(0.5 * x ** 2)', '(HUBER_DELTA * (x - 0.5 * HUBER_DELTA))'], {}), True, 'import tensorflow.keras.backend as K\n'), (20, 'tensorflow.keras.backend.sum', 'K.sum', (['x'], {}), True, 'import tensorflow.keras.backend as K\n'), (25, 'tensorflow.keras.backend.abs', 'K.abs', (['(y_true - y_pred)'], {}), True, 'import tensorflow.keras.backend as K\n'), (26, 'tensorflow.keras.backend.switch', 'K.switch', (['(x < h_delta)', '(0.5 * x ** 2)', '(h_delta * (x - 0.5 * h_delta))'], {}), True, 'import tensorflow.keras.backend as K\n'), (28, 'tensorflow.keras.backend.sum', 'K.sum', (['x'], {}), True, 'import tensorflow.keras.backend as K\n'), (73, 'tensorflow.keras.optimizers.SGD', 'tf.keras.optimizers.SGD', (['(0.01)', '(0.9)'], {}), True, 'import tensorflow as tf\n'), (159, 'tensorflow.keras.optimizers.SGD', 'tf.keras.optimizers.SGD', (['(0.01)', '(0.9)'], {}), True, 'import tensorflow as tf\n'), (327, 'tensorflow.keras.Model', 'tf.keras.Model', ([], {'inputs': 'input', 'outputs': 'outputs', 'name': '"""copynet"""'}), True, 'import tensorflow as tf\n'), (353, 'tensorflow.keras.regularizers.l2', 'tf.keras.regularizers.l2', (['weight_decay'], {}), True, 'import tensorflow as tf\n'), (357, 'tensorflow.keras.Sequential', 'tf.keras.Sequential', ([], {'name': 'name'}), True, 'import tensorflow as tf\n'), (418, 'tensorflow.keras.regularizers.l2', 'tf.keras.regularizers.l2', (['weight_decay'], {}), True, 'import tensorflow as tf\n'), (422, 'tensorflow.keras.Sequential', 'tf.keras.Sequential', ([], {'name': 'name'}), True, 'import tensorflow as tf\n'), (486, 'tensorflow.keras.regularizers.l2', 'tf.keras.regularizers.l2', (['weight_decay'], {}), True, 'import tensorflow as tf\n'), (488, 'tensorflow.keras.Sequential', 'tf.keras.Sequential', ([], {'name': 'name'}), True, 'import tensorflow as tf\n'), (523, 'tensorflow.keras.regularizers.l2', 'tf.keras.regularizers.l2', (['weight_decay'], {}), True, 'import tensorflow as tf\n'), (525, 'pdb.set_trace', 'pdb.set_trace', ([], {}), False, 'import pdb\n'), (527, 'tensorflow.keras.Sequential', 'tf.keras.Sequential', ([], {'name': 'name'}), True, 'import tensorflow as tf\n'), (564, 'tensorflow.keras.Sequential', 'tf.keras.Sequential', ([], {'name': 'name'}), True, 'import tensorflow as tf\n'), (733, 'tensorflow.keras.initializers.GlorotUniform', 'tf.keras.initializers.GlorotUniform', ([], {}), True, 'import tensorflow as tf\n'), (743, 'tensorflow.matmul', 'tf.matmul', (['x', 'self.kernel'], {}), True, 'import tensorflow as tf\n'), (67, 'tensorflow.keras.Model', 'tf.keras.Model', (['self.model.input', 'self.model.layers[-1].input'], {}), True, 'import tensorflow as tf\n'), (70, 'tensorflow.keras.Model', 'tf.keras.Model', (['self.model.input', 'out_layer'], {}), True, 'import tensorflow as tf\n'), (184, 'tensorflow.keras.layers.Input', 'tf.keras.layers.Input', ([], {'shape': '(None, input_shape[0], input_shape[1], input_shape[2])', 'name': '"""input"""'}), True, 'import tensorflow as tf\n'), (319, 'tensorflow.keras.metrics.MeanAbsoluteError', 'tf.keras.metrics.MeanAbsoluteError', ([], {}), True, 'import tensorflow as tf\n'), (320, 'tensorflow.keras.metrics.MeanSquaredError', 'tf.keras.metrics.MeanSquaredError', ([], {}), True, 'import tensorflow as tf\n'), (355, 'tensorflow.keras.regularizers.l2', 'tf.keras.regularizers.l2', (['L2_norm_lstm'], {}), True, 'import tensorflow as tf\n'), (420, 'tensorflow.keras.regularizers.l2', 'tf.keras.regularizers.l2', (['L2_norm_lstm'], {}), True, 'import tensorflow as tf\n'), (490, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['filters_numbers[0]'], {'kernel_size': 'filters_size[0]', 'strides': 'strides[0]', 'kernel_regularizer': 'L2_norm', 'activation': '"""relu"""', 'input_shape': 'input_shape', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (494, 'tensorflow.keras.layers.MaxPooling2D', 'tf.keras.layers.MaxPooling2D', ([], {'pool_size': '(2, 2)', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (508, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['(ndense_units * 2)'], {'kernel_size': '(1)', 'strides': '(1)', 'name': '"""fc1"""', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (512, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['ndense_units'], {'kernel_size': '(1)', 'strides': '(1)', 'name': '"""code0"""', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (515, 'tensorflow.keras.layers.Flatten', 'tf.keras.layers.Flatten', ([], {'name': '"""code"""'}), True, 'import tensorflow as tf\n'), (529, 'tensorflow.keras.layers.Conv3D', 'tf.keras.layers.Conv3D', (['filters_numbers[0]'], {'kernel_size': '(3, filters_size[0], filters_size[0])', 'strides': '(1, strides[0], strides[0])', 'kernel_regularizer': 'L2_norm', 'activation': '"""relu"""', 'input_shape': 'input_shape', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (533, 'tensorflow.keras.layers.MaxPooling3D', 'tf.keras.layers.MaxPooling3D', ([], {'pool_size': '(2, 2, 2)', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (551, 'tensorflow.keras.layers.Flatten', 'tf.keras.layers.Flatten', ([], {'name': '"""flatten"""'}), True, 'import tensorflow as tf\n'), (554, 'tensorflow.keras.layers.Dense', 'tf.keras.layers.Dense', (['ndense_units'], {'name': '"""dense"""'}), True, 'import tensorflow as tf\n'), (566, 'tensorflow.keras.layers.Conv3D', 'tf.keras.layers.Conv3D', (['filters_numbers[0]', 'filters_size[0]'], {'strides': '(1, 2, 2)', 'padding': '"""valid"""', 'activation': '"""relu"""', 'input_shape': 'input_shape', 'data_format': '"""channels_last"""', 'kernel_initializer': 'kernel_initializer'}), True, 'import tensorflow as tf\n'), (569, 'tensorflow.keras.layers.Conv3D', 'tf.keras.layers.Conv3D', (['filters_numbers[1]', 'filters_size[1]'], {'strides': '(1, 2, 2)', 'padding': '"""valid"""', 'activation': '"""relu"""', 'input_shape': 'input_shape', 'data_format': '"""channels_last"""', 'kernel_initializer': 'kernel_initializer'}), True, 'import tensorflow as tf\n'), (572, 'tensorflow.keras.layers.Conv3D', 'tf.keras.layers.Conv3D', (['filters_numbers[2]', 'filters_size[2]'], {'strides': '(2, 2, 2)', 'padding': '"""valid"""', 'activation': '"""relu"""', 'input_shape': 'input_shape', 'data_format': '"""channels_last"""', 'kernel_initializer': 'kernel_initializer'}), True, 'import tensorflow as tf\n'), (575, 'tensorflow.keras.layers.Conv3D', 'tf.keras.layers.Conv3D', (['filters_numbers[3]', 'filters_size[3]'], {'strides': '(2, 2, 2)', 'padding': '"""valid"""', 'activation': '"""relu"""', 'input_shape': 'input_shape', 'data_format': '"""channels_last"""', 'kernel_initializer': 'kernel_initializer'}), True, 'import tensorflow as tf\n'), (578, 'tensorflow.keras.layers.Conv3D', 'tf.keras.layers.Conv3D', (['filters_numbers[4]', 'filters_size[4]'], {'strides': '(1, 1, 1)', 'padding': '"""valid"""', 'activation': '"""relu"""', 'input_shape': 'input_shape', 'data_format': '"""channels_last"""', 'kernel_initializer': 'kernel_initializer'}), True, 'import tensorflow as tf\n'), (581, 'tensorflow.keras.layers.Conv3D', 'tf.keras.layers.Conv3D', (['filters_numbers[5]', 'filters_size[5]'], {'strides': '(1, 1, 1)', 'padding': '"""valid"""', 'activation': '"""relu"""', 'input_shape': 'input_shape', 'data_format': '"""channels_last"""', 'kernel_initializer': 'kernel_initializer'}), True, 'import tensorflow as tf\n'), (592, 'tensorflow.keras.layers.Flatten', 'tf.keras.layers.Flatten', ([], {'name': '"""code"""'}), True, 'import tensorflow as tf\n'), (602, 'tensorflow.keras.Model', 'tf.keras.Model', (['self.model.input', 'self.model.layers[-1].input'], {}), True, 'import tensorflow as tf\n'), (605, 'tensorflow.keras.Model', 'tf.keras.Model', (['self.model.input', 'out_layer'], {}), True, 'import tensorflow as tf\n'), (615, 'numpy.zeros', 'np.zeros', ([], {'shape': '(data.shape[0], 25, 60, 60, 2)'}), True, 'import numpy as np\n'), (652, 'tensorflow.keras.layers.ZeroPadding2D', 'tf.keras.layers.ZeroPadding2D', ([], {'padding': '(1)'}), True, 'import tensorflow as tf\n'), (653, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['(64)'], {'kernel_size': '(3)', 'activation': 'None', 'padding': '"""valid"""', 'use_bias': '(False)', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (655, 'tensorflow.keras.layers.LeakyReLU', 'tf.keras.layers.LeakyReLU', ([], {}), True, 'import tensorflow as tf\n'), (656, 'tensorflow.keras.layers.ZeroPadding2D', 'tf.keras.layers.ZeroPadding2D', ([], {'padding': '(1)'}), True, 'import tensorflow as tf\n'), (657, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['(64)'], {'kernel_size': '(3)', 'activation': 'None', 'padding': '"""valid"""', 'use_bias': '(False)', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (659, 'tensorflow.keras.layers.LeakyReLU', 'tf.keras.layers.LeakyReLU', ([], {}), True, 'import tensorflow as tf\n'), (660, 'tensorflow.keras.layers.MaxPooling2D', 'tf.keras.layers.MaxPooling2D', ([], {'pool_size': '(2, 2)', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (676, 'tensorflow.keras.layers.Add', 'tf.keras.layers.Add', ([], {}), True, 'import tensorflow as tf\n'), (677, 'tensorflow.keras.layers.ZeroPadding2D', 'tf.keras.layers.ZeroPadding2D', ([], {'padding': '(1)'}), True, 'import tensorflow as tf\n'), (678, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['(128)'], {'kernel_size': '(3)', 'activation': 'None', 'padding': '"""valid"""', 'use_bias': '(False)', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (680, 'tensorflow.keras.layers.LeakyReLU', 'tf.keras.layers.LeakyReLU', ([], {}), True, 'import tensorflow as tf\n'), (681, 'tensorflow.keras.layers.ZeroPadding2D', 'tf.keras.layers.ZeroPadding2D', ([], {'padding': '(1)'}), True, 'import tensorflow as tf\n'), (682, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['(128)'], {'kernel_size': '(3)', 'activation': 'None', 'padding': '"""valid"""', 'use_bias': '(False)', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (684, 'tensorflow.keras.layers.LeakyReLU', 'tf.keras.layers.LeakyReLU', ([], {}), True, 'import tensorflow as tf\n'), (699, 'tensorflow.keras.layers.Add', 'tf.keras.layers.Add', ([], {}), True, 'import tensorflow as tf\n'), (717, 'tensorflow.keras.layers.Concatenate', 'tf.keras.layers.Concatenate', ([], {'axis': '(1)'}), True, 'import tensorflow as tf\n'), (721, 'tensorflow.keras.layers.Flatten', 'tf.keras.layers.Flatten', ([], {}), True, 'import tensorflow as tf\n'), (47, 'tensorflow.keras.models.load_model', 'tf.keras.models.load_model', (['netpath'], {'compile': 'compile', 'custom_objects': "{'mj_smoothL1': mj_smoothL1}"}), True, 'import tensorflow as tf\n'), (52, 'os.path.dirname', 'os.path.dirname', (['netpath'], {}), False, 'import os\n'), (53, 'os.path.join', 'os.path.join', (['bdir', '"""model-config.hdf5"""'], {}), False, 'import os\n'), (54, 'deepdish.io.load', 'dd.io.load', (['fconfig'], {}), True, 'import deepdish as dd\n'), (58, 'os.path.basename', 'os.path.basename', (['netpath'], {}), False, 'import os\n'), (59, 'os.path.splitext', 'os.path.splitext', (['bname'], {}), False, 'import os\n'), (60, 'os.path.join', 'os.path.join', (['bdir', "(fparts[0] + '_weights.hdf5')"], {}), False, 'import os\n'), (113, 'tensorflow.keras.Model', 'tf.keras.Model', ([], {'inputs': 'self.model.input', 'outputs': 'main_branch'}), True, 'import tensorflow as tf\n'), (185, 'tensorflow.keras.layers.ConvLSTM2D', 'tf.keras.layers.ConvLSTM2D', (['(16)', '(3)'], {'padding': '"""same"""', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (188, 'tensorflow.keras.layers.Input', 'tf.keras.layers.Input', ([], {'shape': '(None, input_shape[0], input_shape[1], input_shape[2])', 'name': '"""input"""'}), True, 'import tensorflow as tf\n'), (285, 'tensorflow.keras.layers.Dropout', 'tf.keras.layers.Dropout', (['drop_code'], {'name': '"""drop_code"""'}), True, 'import tensorflow as tf\n'), (291, 'tensorflow.keras.layers.Dense', 'tf.keras.layers.Dense', (['nclasses'], {}), True, 'import tensorflow as tf\n'), (375, 'tensorflow.keras.layers.LSTM', 'tf.keras.layers.LSTM', (['lstm_number'], {'dropout': 'dropout_lstm', 'kernel_regularizer': 'L2_norm_lstm'}), True, 'import tensorflow as tf\n'), (392, 'tensorflow.keras.layers.MaxPooling2D', 'tf.keras.layers.MaxPooling2D', ([], {'pool_size': '(2, 2)', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (403, 'tensorflow.keras.layers.Flatten', 'tf.keras.layers.Flatten', ([], {'name': '"""flatten"""'}), True, 'import tensorflow as tf\n'), (442, 'tensorflow.keras.layers.LSTM', 'tf.keras.layers.LSTM', (['lstm_number'], {'dropout': 'dropout_lstm', 'kernel_regularizer': 'L2_norm_lstm'}), True, 'import tensorflow as tf\n'), (460, 'tensorflow.keras.layers.MaxPooling2D', 'tf.keras.layers.MaxPooling2D', ([], {'pool_size': '(2, 2)', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (470, 'tensorflow.keras.layers.Flatten', 'tf.keras.layers.Flatten', ([], {'name': '"""flatten"""'}), True, 'import tensorflow as tf\n'), (497, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['filters_numbers[i]'], {'kernel_size': 'filters_size[i]', 'strides': 'strides[i]', 'kernel_regularizer': 'L2_norm', 'activation': '"""relu"""', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (502, 'tensorflow.keras.layers.MaxPooling2D', 'tf.keras.layers.MaxPooling2D', ([], {'pool_size': '(2, 2)', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (511, 'tensorflow.keras.layers.Dropout', 'tf.keras.layers.Dropout', (['dropout'], {'name': '"""drop"""'}), True, 'import tensorflow as tf\n'), (536, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['filters_numbers[i]'], {'kernel_size': '(3, filters_size[i], filters_size[i])', 'strides': '(1, strides[i], strides[i])', 'kernel_regularizer': 'L2_norm', 'activation': '"""relu"""', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (556, 'tensorflow.keras.layers.Dropout', 'tf.keras.layers.Dropout', (['dropout'], {'name': '"""drop"""'}), True, 'import tensorflow as tf\n'), (585, 'tensorflow.keras.layers.Dropout', 'tf.keras.layers.Dropout', (['dropout'], {'name': '"""drop"""'}), True, 'import tensorflow as tf\n'), (635, 'os.path.join', 'os.path.join', (['self.experdir', '"""model-final.hdf5"""'], {}), False, 'import os\n'), (638, 'tensorflow.keras.layers.ZeroPadding2D', 'tf.keras.layers.ZeroPadding2D', ([], {'padding': '(4)'}), True, 'import tensorflow as tf\n'), (640, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['(32)'], {'kernel_size': '(5)', 'activation': 'None', 'padding': '"""valid"""', 'use_bias': '(False)', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (642, 'tensorflow.keras.layers.LeakyReLU', 'tf.keras.layers.LeakyReLU', ([], {}), True, 'import tensorflow as tf\n'), (644, 'tensorflow.keras.layers.ZeroPadding2D', 'tf.keras.layers.ZeroPadding2D', ([], {'padding': '(1)'}), True, 'import tensorflow as tf\n'), (646, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['(32)'], {'kernel_size': '(3)', 'activation': 'None', 'padding': '"""valid"""', 'use_bias': '(False)', 'input_shape': 'input_shape', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (648, 'tensorflow.keras.layers.LeakyReLU', 'tf.keras.layers.LeakyReLU', ([], {}), True, 'import tensorflow as tf\n'), (649, 'tensorflow.keras.layers.MaxPooling2D', 'tf.keras.layers.MaxPooling2D', ([], {'pool_size': '(2, 2)', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (662, 'tensorflow.keras.layers.ZeroPadding2D', 'tf.keras.layers.ZeroPadding2D', ([], {'padding': '(1)'}), True, 'import tensorflow as tf\n'), (664, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['(64)'], {'kernel_size': '(3)', 'activation': 'None', 'padding': '"""valid"""', 'use_bias': '(False)', 'input_shape': 'input_shape', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (666, 'tensorflow.keras.layers.LeakyReLU', 'tf.keras.layers.LeakyReLU', ([], {}), True, 'import tensorflow as tf\n'), (668, 'tensorflow.keras.layers.ZeroPadding2D', 'tf.keras.layers.ZeroPadding2D', ([], {'padding': '(1)'}), True, 'import tensorflow as tf\n'), (670, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['(64)'], {'kernel_size': '(3)', 'activation': 'None', 'padding': '"""valid"""', 'use_bias': '(False)', 'input_shape': 'input_shape', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (672, 'tensorflow.keras.layers.LeakyReLU', 'tf.keras.layers.LeakyReLU', ([], {}), True, 'import tensorflow as tf\n'), (673, 'tensorflow.keras.layers.MaxPooling2D', 'tf.keras.layers.MaxPooling2D', ([], {'pool_size': '(2, 2)', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (686, 'tensorflow.keras.layers.ZeroPadding2D', 'tf.keras.layers.ZeroPadding2D', ([], {'padding': '(1)'}), True, 'import tensorflow as tf\n'), (688, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['(128)'], {'kernel_size': '(3)', 'activation': 'None', 'padding': '"""valid"""', 'use_bias': '(False)', 'input_shape': 'input_shape', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (690, 'tensorflow.keras.layers.LeakyReLU', 'tf.keras.layers.LeakyReLU', ([], {}), True, 'import tensorflow as tf\n'), (692, 'tensorflow.keras.layers.ZeroPadding2D', 'tf.keras.layers.ZeroPadding2D', ([], {'padding': '(1)'}), True, 'import tensorflow as tf\n'), (694, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['(128)'], {'kernel_size': '(3)', 'activation': 'None', 'padding': '"""valid"""', 'use_bias': '(False)', 'input_shape': 'input_shape', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (696, 'tensorflow.keras.layers.LeakyReLU', 'tf.keras.layers.LeakyReLU', ([], {}), True, 'import tensorflow as tf\n'), (708, 'tensorflow.keras.layers.Reshape', 'tf.keras.layers.Reshape', (['(num_bin, -1, c)'], {}), True, 'import tensorflow as tf\n'), (712, 'tensorflow.keras.layers.Reshape', 'tf.keras.layers.Reshape', (['(num_bin, -1, c)'], {}), True, 'import tensorflow as tf\n'), (111, 'tensorflow.keras.layers.Dense', 'tf.keras.layers.Dense', (['nclasses'], {'activation': '"""softmax"""', 'kernel_initializer': '"""he_uniform"""', 'name': '"""probs"""'}), True, 'import tensorflow as tf\n'), (191, 'tensorflow.keras.layers.Input', 'tf.keras.layers.Input', ([], {'shape': '(None, input_shape[0], input_shape[1], input_shape[2])', 'name': '"""input"""'}), True, 'import tensorflow as tf\n'), (266, 'tensorflow.keras.layers.Concatenate', 'tf.keras.layers.Concatenate', ([], {'axis': '(1)'}), True, 'import tensorflow as tf\n'), (276, 'tensorflow.keras.layers.Dense', 'tf.keras.layers.Dense', (['ndense_units'], {'name': '"""code"""'}), True, 'import tensorflow as tf\n'), (360, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['filters_numbers[0]'], {'kernel_size': 'filters_size[0]', 'strides': 'strides[0]', 'kernel_regularizer': 'L2_norm', 'activation': '"""relu"""', 'input_shape': 'input_shape', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (364, 'tensorflow.keras.layers.MaxPooling2D', 'tf.keras.layers.MaxPooling2D', ([], {'pool_size': '(2, 2)', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (374, 'tensorflow.keras.layers.Flatten', 'tf.keras.layers.Flatten', ([], {'name': '"""flatten"""'}), True, 'import tensorflow as tf\n'), (379, 'tensorflow.keras.layers.Dense', 'tf.keras.layers.Dense', (['ndense_units'], {'name': '"""dense"""'}), True, 'import tensorflow as tf\n'), (384, 'tensorflow.keras.layers.ConvLSTM2D', 'tf.keras.layers.ConvLSTM2D', (['filters_numbers[0]'], {'kernel_size': 'filters_size[0]', 'strides': 'strides[0]', 'kernel_regularizer': 'L2_norm', 'input_shape': 'input_shape', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (388, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['filters_numbers[0]'], {'kernel_size': 'filters_size[0]', 'strides': 'strides[0]', 'kernel_regularizer': 'L2_norm', 'activation': '"""relu"""', 'input_shape': 'input_shape', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (395, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['filters_numbers[i]'], {'kernel_size': 'filters_size[i]', 'strides': 'strides[i]', 'kernel_regularizer': 'L2_norm', 'activation': '"""relu"""', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (407, 'tensorflow.keras.layers.Dense', 'tf.keras.layers.Dense', (['ndense_units'], {'name': '"""dense"""'}), True, 'import tensorflow as tf\n'), (426, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['filters_numbers[0]'], {'kernel_size': 'filters_size[0]', 'strides': 'strides[0]', 'kernel_regularizer': 'L2_norm', 'activation': '"""relu"""', 'input_shape': 'input_shape', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (430, 'tensorflow.keras.layers.MaxPooling2D', 'tf.keras.layers.MaxPooling2D', ([], {'pool_size': '(2, 2)', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (441, 'tensorflow.keras.layers.Flatten', 'tf.keras.layers.Flatten', ([], {'name': '"""flatten"""'}), True, 'import tensorflow as tf\n'), (446, 'tensorflow.keras.layers.Dense', 'tf.keras.layers.Dense', (['(ndense_units * 2)'], {'name': '"""dense"""'}), True, 'import tensorflow as tf\n'), (449, 'tensorflow.keras.layers.Dense', 'tf.keras.layers.Dense', (['ndense_units'], {'name': '"""code"""'}), True, 'import tensorflow as tf\n'), (452, 'tensorflow.keras.layers.ConvLSTM2D', 'tf.keras.layers.ConvLSTM2D', (['filters_numbers[0]'], {'kernel_size': 'filters_size[0]', 'strides': 'strides[0]', 'kernel_regularizer': 'L2_norm', 'input_shape': 'input_shape', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (456, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['filters_numbers[0]'], {'kernel_size': 'filters_size[0]', 'strides': 'strides[0]', 'kernel_regularizer': 'L2_norm', 'activation': '"""relu"""', 'input_shape': 'input_shape', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (463, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['filters_numbers[i]'], {'kernel_size': 'filters_size[i]', 'strides': 'strides[i]', 'kernel_regularizer': 'L2_norm', 'activation': '"""relu"""', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (468, 'tensorflow.keras.layers.MaxPooling2D', 'tf.keras.layers.MaxPooling2D', ([], {'pool_size': '(2, 2)', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (474, 'tensorflow.keras.layers.Dense', 'tf.keras.layers.Dense', (['(ndense_units * 2)'], {'name': '"""dense"""'}), True, 'import tensorflow as tf\n'), (477, 'tensorflow.keras.layers.Dense', 'tf.keras.layers.Dense', (['ndense_units'], {'name': '"""code"""'}), True, 'import tensorflow as tf\n'), (541, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['filters_numbers[i]'], {'kernel_size': '(3, filters_size[i], filters_size[i])', 'strides': '(1, strides[i], strides[i])', 'kernel_regularizer': 'L2_norm', 'activation': '"""relu"""', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (545, 'tensorflow.keras.layers.MaxPooling2D', 'tf.keras.layers.MaxPooling2D', ([], {'pool_size': '(2, 2, 2)', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (547, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['filters_numbers[i]'], {'kernel_size': 'filters_size[i]', 'strides': '(1, strides[i], strides[i])', 'kernel_regularizer': 'L2_norm', 'activation': '"""relu"""', 'data_format': '"""channels_last"""'}), True, 'import tensorflow as tf\n'), (589, 'tensorflow.keras.regularizers.l2', 'tf.keras.regularizers.l2', (['(0.001)'], {}), True, 'import tensorflow as tf\n'), (625, 'tensorflow.math.l2_normalize', 'tf.math.l2_normalize', (['x'], {'axis': '(1)'}), True, 'import tensorflow as tf\n'), (651, 'tensorflow.math.reduce_max', 'tf.math.reduce_max', (['x'], {'axis': '(1)'}), True, 'import tensorflow as tf\n'), (675, 'tensorflow.math.reduce_max', 'tf.math.reduce_max', (['x'], {'axis': '(1)'}), True, 'import tensorflow as tf\n'), (697, 'tensorflow.math.reduce_max', 'tf.math.reduce_max', (['x'], {'axis': '(1)'}), True, 'import tensorflow as tf\n'), (718, 'tensorflow.transpose', 'tf.transpose', (['x', '[1, 0, 2]'], {}), True, 'import tensorflow as tf\n'), (720, 'tensorflow.transpose', 'tf.transpose', (['x', '[1, 0, 2]'], {}), True, 'import tensorflow as tf\n'), (192, 'tensorflow.keras.layers.ConvLSTM2D', 'tf.keras.layers.ConvLSTM2D', (['(50)', '(3)'], {'padding': '"""same"""', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (195, 'tensorflow.keras.layers.Input', 'tf.keras.layers.Input', ([], {'shape': '(None, input_shape[0], input_shape[1], input_shape[2])', 'name': '"""input"""'}), True, 'import tensorflow as tf\n'), (269, 'tensorflow.keras.layers.Dropout', 'tf.keras.layers.Dropout', (['dropout'], {'name': '"""drop_concat"""'}), True, 'import tensorflow as tf\n'), (273, 'tensorflow.keras.layers.Dense', 'tf.keras.layers.Dense', (['(ndense_units * 2)'], {'name': '"""dense"""'}), True, 'import tensorflow as tf\n'), (298, 'tensorflow.math.l2_normalize', 'tf.math.l2_normalize', (['x'], {'axis': '(1)'}), True, 'import tensorflow as tf\n'), (368, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['filters_numbers[i]'], {'kernel_size': 'filters_size[i]', 'strides': 'strides[i]', 'kernel_regularizer': 'L2_norm', 'activation': '"""relu"""', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (372, 'tensorflow.keras.layers.MaxPooling2D', 'tf.keras.layers.MaxPooling2D', ([], {'pool_size': '(2, 2)', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (381, 'tensorflow.keras.layers.Dropout', 'tf.keras.layers.Dropout', (['dropout'], {'name': '"""drop"""'}), True, 'import tensorflow as tf\n'), (401, 'tensorflow.keras.layers.MaxPooling2D', 'tf.keras.layers.MaxPooling2D', ([], {'pool_size': '(2, 2)', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (409, 'tensorflow.keras.layers.Dropout', 'tf.keras.layers.Dropout', (['dropout'], {'name': '"""drop"""'}), True, 'import tensorflow as tf\n'), (434, 'tensorflow.keras.layers.Conv2D', 'tf.keras.layers.Conv2D', (['filters_numbers[i]'], {'kernel_size': 'filters_size[i]', 'strides': 'strides[i]', 'kernel_regularizer': 'L2_norm', 'activation': '"""relu"""', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (439, 'tensorflow.keras.layers.MaxPooling2D', 'tf.keras.layers.MaxPooling2D', ([], {'pool_size': '(2, 2)', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (448, 'tensorflow.keras.layers.Dropout', 'tf.keras.layers.Dropout', (['dropout'], {'name': '"""drop"""'}), True, 'import tensorflow as tf\n'), (476, 'tensorflow.keras.layers.Dropout', 'tf.keras.layers.Dropout', (['dropout'], {'name': '"""drop"""'}), True, 'import tensorflow as tf\n'), (734, 'numpy.random.randint', 'np.random.randint', (['(100)'], {'size': '(1)'}), True, 'import numpy as np\n'), (44, 'nets.triplet_loss_all.TripletBatchAllLoss', 'TripletBatchAllLoss', ([], {}), False, 'from nets.triplet_loss_all import TripletBatchAllLoss\n'), (115, 'tensorflow.keras.metrics.SparseCategoricalAccuracy', 'tf.keras.metrics.SparseCategoricalAccuracy', ([], {}), True, 'import tensorflow as tf\n'), (196, 'tensorflow.keras.layers.ConvLSTM2D', 'tf.keras.layers.ConvLSTM2D', (['(16)', '(7)'], {'padding': '"""same"""', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (199, 'tensorflow.keras.layers.Input', 'tf.keras.layers.Input', ([], {'shape': '(None, input_shape[0], input_shape[1], input_shape[2])', 'name': '"""input"""'}), True, 'import tensorflow as tf\n'), (275, 'tensorflow.keras.layers.Dropout', 'tf.keras.layers.Dropout', (['dropout'], {'name': '"""drop"""'}), True, 'import tensorflow as tf\n'), (308, 'tensorflow.keras.losses.Huber', 'tf.keras.losses.Huber', ([], {'delta': 'hdelta'}), True, 'import tensorflow as tf\n'), (709, 'tensorflow.math.reduce_mean', 'tf.math.reduce_mean', (['x'], {'axis': '(2)'}), True, 'import tensorflow as tf\n'), (709, 'tensorflow.math.reduce_max', 'tf.math.reduce_max', (['x'], {'axis': '(2)'}), True, 'import tensorflow as tf\n'), (713, 'tensorflow.math.reduce_mean', 'tf.math.reduce_mean', (['x'], {'axis': '(2)'}), True, 'import tensorflow as tf\n'), (713, 'tensorflow.math.reduce_max', 'tf.math.reduce_max', (['x'], {'axis': '(2)'}), True, 'import tensorflow as tf\n'), (200, 'tensorflow.keras.layers.ConvLSTM2D', 'tf.keras.layers.ConvLSTM2D', (['(50)', '(7)'], {'padding': '"""same"""', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (203, 'tensorflow.keras.layers.Input', 'tf.keras.layers.Input', ([], {'shape': '(None, input_shape[0], input_shape[1], input_shape[2])', 'name': '"""input"""'}), True, 'import tensorflow as tf\n'), (207, 'tensorflow.keras.layers.Input', 'tf.keras.layers.Input', ([], {'shape': 'input_shape', 'name': '"""input"""'}), True, 'import tensorflow as tf\n'), (262, 'tensorflow.math.l2_normalize', 'tf.math.l2_normalize', (['x'], {'axis': '(1)'}), True, 'import tensorflow as tf\n'), (263, 'tensorflow.math.l2_normalize', 'tf.math.l2_normalize', (['x'], {'axis': '(1)'}), True, 'import tensorflow as tf\n'), (310, 'tensorflow_addons.losses.TripletSemiHardLoss', 'tfa.losses.TripletSemiHardLoss', ([], {'margin': 'margin'}), True, 'import tensorflow_addons as tfa\n'), (204, 'tensorflow.keras.layers.ConvLSTM2D', 'tf.keras.layers.ConvLSTM2D', (['(50)', '(3)'], {'padding': '"""same"""', 'data_format': '"""channels_first"""'}), True, 'import tensorflow as tf\n'), (312, 'tensorflow_addons.losses.TripletHardLoss', 'tfa.losses.TripletHardLoss', ([], {'margin': 'margin'}), True, 'import tensorflow_addons as tfa\n'), (314, 'nets.triplet_loss_all.TripletBatchAllLoss', 'TripletBatchAllLoss', ([], {'margin': 'margin'}), False, 'from nets.triplet_loss_all import TripletBatchAllLoss\n')]