import tensorflow as tf

	x2d, x3d = x
	with tf.GradientTape() as tape:
		pred, K, reprojected, crit_fake = model(x2d)
		crit_real = model.crit(x3d)

		crit_dis = tf.reduce_mean(tf.square(crit_real - tf.ones_like(crit_real))) + tf.reduce_mean(tf.square(crit_fake - tf.zeros_like(crit_fake)))
		crit_gen = tf.reduce_mean(tf.square(crit_fake - tf.ones_like(crit_fake)))

		rep_loss = tf.reduce_mean(tf.square(pred - x2d))

		KK = tf.matmul(K, K, transpose_b=True)
		K_trace = tf.expand_dims(tf.expand_dims(tf.trace(KK), -1), -1)
		K_loss = tf.reduce_mean(tf.abs(KK / K_trace - tf.eye(2))) 

		loss_total_gen = crit_gen + rep_loss + K_loss

	gen_var = model.get_gen_vars()
	dis_var = model.dis.trainable_variables
	grads = tape.gradient([loss_total_gen, crit_dis], [gen_var, dis_var])
	return grads, [crit_dis, crit_gen, rep_loss, K_loss]

reader = datareader.DataReader(16)
