Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a Keras model on a TensorFlow tensor but keep weights

In Keras as a simplified interface to TensorFlow: tutorial they describe how one can call a Keras model on a TensorFlow tensor.

from keras.models import Sequential

model = Sequential()
model.add(Dense(32, activation='relu', input_dim=784))
model.add(Dense(10, activation='softmax'))

# this works! 
x = tf.placeholder(tf.float32, shape=(None, 784))
y = model(x)

They also say:

Note: by calling a Keras model, your are reusing both its architecture and its weights. When you are calling a model on a tensor, you are creating new TF ops on top of the input tensor, and these ops are reusing the TF Variable instances already present in the model.

I interpret this as that the weights of the model will be the same in y as in model. However, for me it seems like the weights in the resulting Tensorflow node are reinitialized. A minimal example can be seen below:

import numpy as np
from keras.models import Sequential
from keras.layers import Dense
# Create model with weight initialized to 1
model = Sequential()
model.add(Dense(1, input_dim=1, kernel_initializer='ones',
                bias_initializer='zeros'))
model.compile(loss='binary_crossentropy', optimizer='adam',
              metrics=['accuracy'])

# Save the weights 
model.save_weights('file')

# Create another identical model except with weight initialized to 0
model2 = Sequential()
model2.add(Dense(1, input_dim=1, kernel_initializer='zeros',
                 bias_initializer='zeros'))
model2.compile(loss='binary_crossentropy', optimizer='adam',
               metrics=['accuracy'])
# Load the weight from the first model
model2.load_weights('file')
# Call model with Tensorflow tensor
v = tf.Variable([[1, ], ], dtype=tf.float32)
node = model2(v)
sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)
print(sess.run(node), model2.predict(np.array([[1, ], ])))
# Prints (array([[ 0.]], dtype=float32), array([[ 1.]], dtype=float32))

Why I want to do this:

I want to use a trained network in another minimization scheme were the network "punish" places in the search space that are not allowed. So if you have ideas not involving this specific approach, that is also very appreciated.

like image 531
Emil Johansson Avatar asked Oct 17 '17 12:10

Emil Johansson


People also ask

How do you save model weights in Keras?

Save Your Neural Network Model to JSON The weights are saved directly from the model using the save_weights() function and later loaded using the symmetrical load_weights() function.

Does model compile reset weights?

What does compile do? Compile defines the loss function, the optimizer and the metrics. That's all. It has nothing to do with the weights and you can compile a model as many times as you want without causing any problem to pretrained weights.

How do I save the Keras model in TensorFlow?

Using save_weights() method Now you can simply save the weights of all the layers using the save_weights() method. It saves the weights of the layers contained in the model. It is advised to use the save() method to save h5 models instead of save_weights() method for saving a model using tensorflow.


1 Answers

Finally found the answer. There are two problems in the example from the question.

1:

The first and most obvious was that I called the tf.global_variables_intializer() function which will re-initialize all variables in the session. Instead I should have called the tf.variables_initializer(var_list) where var_list is a list of variables to initialize.

2:

The second problem was that Keras did not use the same session as the native Tensorflow objects. This meant that to be able to run the tensorflow object model2(v) with my session sess it needed to be reinitialized. Again Keras as a simplified interface to tensorflow: Tutorial was able to help

We should start by creating a TensorFlow session and registering it with Keras. This means that Keras will use the session we registered to initialize all variables that it creates internally.

import tensorflow as tf
sess = tf.Session()

from keras import backend as K
K.set_session(sess)

If we apply these changes to the example provided in my question we get the following code that does exactly what is expected from it.

from keras import backend as K
from keras.models import Sequential
from keras.layers import Dense
sess = tf.Session()
# Register session with Keras
K.set_session(sess)
model = Sequential()
model.add(Dense(1, input_dim=1, kernel_initializer='ones',
                bias_initializer='zeros'))
model.compile(loss='binary_crossentropy', optimizer='adam',
              metrics=['accuracy'])
model.save_weights('test')

model2 = Sequential()
model2.add(Dense(1, input_dim=1, kernel_initializer='zeros',
                 bias_initializer='zeros'))
model2.compile(loss='binary_crossentropy', optimizer='adam',
               metrics=['accuracy'])
model2.load_weights('test')
v = tf.Variable([[1, ], ], dtype=tf.float32)
node = model2(v)
init = tf.variables_initializer([v, ])
sess.run(init)
print(sess.run(node), model2.predict(np.array([[1, ], ])))
# prints: (array([[ 1.]], dtype=float32), array([[ 1.]], dtype=float32))

Conclusion:

The lesson is that when mixing Tensorflow and Keras, make sure everything uses the same session.

like image 73
Emil Johansson Avatar answered Sep 24 '22 07:09

Emil Johansson