I have a model trained using Keras with Tensorflow as my backend, but now I need to turn my model into a tensorflow graph for a certain application. I attempted to do this and make predictions to insure that it is working correctly, but when comparing to the results gathered from model.predict() I get very different values. For instance:
from keras.models import load_model import tensorflow as tf model = load_model('model_file.h5') x_placeholder = tf.placeholder(tf.float32, shape=(None,7214,1)) y = model(x_placeholder) x = np.ones((1,7214,1)) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) print("Predictions from:\ntf graph: "+str(sess.run(y, feed_dict={x_placeholder:x}))) print("keras predict: "+str(model.predict(x)))
returns:
Predictions from: tf graph: [[-0.1015993 0.07432419 0.0592984 ]] keras predict: [[ 0.39339241 0.57949686 -3.67846966]]
The values from keras predict are correct, but the tf graph results are not.
If it helps to know the final intended application, I am creating a jacobian matrix with the tf.gradients() function, but currently it does not return the correct results when comparing to theano's jacobian function, which gives the correct jacobian. Here is my tensorflow jacobian code:
x = tf.placeholder(tf.float32, shape=(None,7214,1)) y = tf.reshape(model(x)[0],[-1]) y_list = tf.unstack(y) jacobian_list = [tf.gradients(y_, x)[0] for y_ in y_list] jacobian = tf.stack(jacobian_list)
EDIT: Model code
import numpy as np from keras.models import Sequential from keras.layers import Dense, InputLayer, Flatten from keras.layers.convolutional import Conv1D from keras.layers.convolutional import MaxPooling1D from keras.optimizers import Adam from keras.callbacks import EarlyStopping, ReduceLROnPlateau # activation function used following every layer except for the output layers activation = 'relu' # model weight initializer initializer = 'he_normal' # shape of input data that is fed into the input layer input_shape = (None,7214,1) # number of filters used in the convolutional layers num_filters = [4,16] # length of the filters in the convolutional layers filter_length = 8 # length of the maxpooling window pool_length = 4 # number of nodes in each of the hidden fully connected layers num_hidden_nodes = [256,128] # number of samples fed into model at once during training batch_size = 64 # maximum number of interations for model training max_epochs = 30 # initial learning rate for optimization algorithm lr = 0.0007 # exponential decay rate for the 1st moment estimates for optimization algorithm beta_1 = 0.9 # exponential decay rate for the 2nd moment estimates for optimization algorithm beta_2 = 0.999 # a small constant for numerical stability for optimization algorithm optimizer_epsilon = 1e-08 model = Sequential([ InputLayer(batch_input_shape=input_shape), Conv1D(kernel_initializer=initializer, activation=activation, padding="same", filters=num_filters[0], kernel_size=filter_length), Conv1D(kernel_initializer=initializer, activation=activation, padding="same", filters=num_filters[1], kernel_size=filter_length), MaxPooling1D(pool_size=pool_length), Flatten(), Dense(units=num_hidden_nodes[0], kernel_initializer=initializer, activation=activation), Dense(units=num_hidden_nodes[1], kernel_initializer=initializer, activation=activation), Dense(units=3, activation="linear", input_dim=num_hidden_nodes[1]), ]) # compile model loss_function = mean squared error early_stopping_min_delta = 0.0001 early_stopping_patience = 4 reduce_lr_factor = 0.5 reuce_lr_epsilon = 0.0009 reduce_lr_patience = 2 reduce_lr_min = 0.00008 optimizer = Adam(lr=lr, beta_1=beta_1, beta_2=beta_2, epsilon=optimizer_epsilon, decay=0.0) early_stopping = EarlyStopping(monitor='val_loss', min_delta=early_stopping_min_delta, patience=early_stopping_patience, verbose=2, mode='min') reduce_lr = ReduceLROnPlateau(monitor='loss', factor=0.5, epsilon=reuce_lr_epsilon, patience=reduce_lr_patience, min_lr=reduce_lr_min, mode='min', verbose=2) model.compile(optimizer=optimizer, loss=loss_function) model.fit(train_x, train_y, validation_data=(cv_x, cv_y), epochs=max_epochs, batch_size=batch_size, verbose=2, callbacks=[reduce_lr,early_stopping]) model.save('model_file.h5')
Just pull on node y and you'll have what you want. This applies to just about any model you create - you'll have computed the prediction probabilities as one of the last steps before computing the loss.
To give inputs to a machine learning model, you have to create a NumPy array, where you have to input the values of the features you used to train your machine learning model. Then we can use that array in the model. predict() method, and at the end, it will give the predicted value as an output based on the inputs.
@frankyjuang linked me to here
https://github.com/amir-abdi/keras_to_tensorflow
and combining this with code from
https://github.com/metaflow-ai/blog/blob/master/tf-freeze/load.py
and
https://github.com/tensorflow/tensorflow/issues/675
I have found a solution to both predicting using a tf graph and creating the jacobian function:
import tensorflow as tf import numpy as np # Create function to convert saved keras model to tensorflow graph def convert_to_pb(weight_file,input_fld='',output_fld=''): import os import os.path as osp from tensorflow.python.framework import graph_util from tensorflow.python.framework import graph_io from keras.models import load_model from keras import backend as K # weight_file is a .h5 keras model file output_node_names_of_input_network = ["pred0"] output_node_names_of_final_network = 'output_node' # change filename to a .pb tensorflow file output_graph_name = weight_file[:-2]+'pb' weight_file_path = osp.join(input_fld, weight_file) net_model = load_model(weight_file_path) num_output = len(output_node_names_of_input_network) pred = [None]*num_output pred_node_names = [None]*num_output for i in range(num_output): pred_node_names[i] = output_node_names_of_final_network+str(i) pred[i] = tf.identity(net_model.output[i], name=pred_node_names[i]) sess = K.get_session() constant_graph = graph_util.convert_variables_to_constants(sess, sess.graph.as_graph_def(), pred_node_names) graph_io.write_graph(constant_graph, output_fld, output_graph_name, as_text=False) print('saved the constant graph (ready for inference) at: ', osp.join(output_fld, output_graph_name)) return output_fld+output_graph_name
Call:
tf_model_path = convert_to_pb('model_file.h5','/model_dir/','/model_dir/')
Create function to load the tf model as a graph:
def load_graph(frozen_graph_filename): # We load the protobuf file from the disk and parse it to retrieve the # unserialized graph_def with tf.gfile.GFile(frozen_graph_filename, "rb") as f: graph_def = tf.GraphDef() graph_def.ParseFromString(f.read()) # Then, we can use again a convenient built-in function to import a graph_def into the # current default Graph with tf.Graph().as_default() as graph: tf.import_graph_def( graph_def, input_map=None, return_elements=None, name="prefix", op_dict=None, producer_op_list=None ) input_name = graph.get_operations()[0].name+':0' output_name = graph.get_operations()[-1].name+':0' return graph, input_name, output_name
Create a function to make model predictions using the tf graph
def predict(model_path, input_data): # load tf graph tf_model,tf_input,tf_output = load_graph(model_path) # Create tensors for model input and output x = tf_model.get_tensor_by_name(tf_input) y = tf_model.get_tensor_by_name(tf_output) # Number of model outputs num_outputs = y.shape.as_list()[0] predictions = np.zeros((input_data.shape[0],num_outputs)) for i in range(input_data.shape[0]): with tf.Session(graph=tf_model) as sess: y_out = sess.run(y, feed_dict={x: input_data[i:i+1]}) predictions[i] = y_out return predictions
Make predictions:
tf_predictions = predict(tf_model_path,test_data)
Jacobian function:
def compute_jacobian(model_path,input_data): tf_model,tf_input,tf_output = load_graph(model_path) x = tf_model.get_tensor_by_name(tf_input) y = tf_model.get_tensor_by_name(tf_output) y_list = tf.unstack(y) num_outputs = y.shape.as_list()[0] jacobian = np.zeros((num_outputs,input_data.shape[0],input_data.shape[1])) for i in range(input_data.shape[0]): with tf.Session(graph=tf_model) as sess: y_out = sess.run([tf.gradients(y_, x)[0] for y_ in y_list], feed_dict={x: input_data[i:i+1]}) jac_temp = np.asarray(y_out) jacobian[:,i:i+1,:]=jac_temp[:,:,:,0] return jacobian
Compute Jacobian Matrix:
jacobians = compute_jacobian(tf_model_path,test_data)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With