# Loading the Weights and Biases into a New Model
# Sometimes you might want to adjust, or "finetune" a model that you have already trained and saved.

# However, loading saved Variables directly into a modified model can generate errors.
# Let's go over how to avoid these problems.

# Naming Error
# TensorFlow uses a string identifier for Tensors and Operations called name.
# If a name is not given, TensorFlow will create one automatically.
# TensorFlow will give the first node the name <Type>, and then give the
# name <Type>_<number> for the subsequent nodes.

# Let's see how this can affect loading a model with a different order of weights and bias:

import tensorflow as tf

# Remove the previous weights and bias
tf.reset_default_graph()

save_file = 'model.ckpt'

# Two Tensor Variables: weights and bias
weights = tf.Variable(tf.truncated_normal([2, 3]))
bias = tf.Variable(tf.truncated_normal([3]))

saver = tf.train.Saver()

# Print the name of Weights and Bias
print('Save Weights: {}'.format(weights.name))
print('Save Bias: {}'.format(bias.name))

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    saver.save(sess, save_file)

# Remove the previous weights and bias
tf.reset_default_graph()

# Two Variables: weights and bias
bias = tf.Variable(tf.truncated_normal([3]))
weights = tf.Variable(tf.truncated_normal([2, 3]))

saver = tf.train.Saver()

# Print the name of Weights and Bias
print('Load Weights: {}'.format(weights.name))
print('Load Bias: {}'.format(bias.name))

with tf.Session() as sess:
    # Load the weights and bias - ERROR
    saver.restore(sess, save_file)

# The code above prints out the following:
# Save Weights: Variable:0
# Save Bias: Variable_1:0
# Load Weights: Variable_1:0
# Load Bias: Variable:0
# ...

# InvalidArgumentError (see above for traceback): Assign requires shapes of both tensors to match.


# You'll notice that the name properties for weights and bias are different than
# when you saved the model. This is why the code produces the "Assign requires shapes
# of both tensors to match" error. The code saver.restore(sess, save_file) is trying
# to load weight data into bias and bias data into weights.

# Instead of letting TensorFlow set the name property, let's set it manually:

import tensorflow as tf

tf.reset_default_graph()

save_file = 'model.ckpt'

# Two Tensor Variables: weights and bias
weights = tf.Variable(tf.truncated_normal([2, 3]), name='weights_0')
bias = tf.Variable(tf.truncated_normal([3]), name='bias_0')

saver = tf.train.Saver()

# Print the name of Weights and Bias
print('Save Weights: {}'.format(weights.name))
print('Save Bias: {}'.format(bias.name))

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    saver.save(sess, save_file)

# Remove the previous weights and bias
tf.reset_default_graph()

# Two Variables: weights and bias
bias = tf.Variable(tf.truncated_normal([3]), name='bias_0')
weights = tf.Variable(tf.truncated_normal([2, 3]) ,name='weights_0')

saver = tf.train.Saver()

# Print the name of Weights and Bias
print('Load Weights: {}'.format(weights.name))
print('Load Bias: {}'.format(bias.name))

with tf.Session() as sess:
    # Load the weights and bias - No Error
    saver.restore(sess, save_file)

print('Loaded Weights and Bias successfully.')

# The code above prints out the following:
# Save Weights: weights_0:0
# Save Bias: bias_0:0
# Load Weights: weights_0:0
# Load Bias: bias_0:0
# Loaded Weights and Bias successfully.

# That worked! The Tensor names match and the data loaded correctly.