2017-05-31 148 views
14

我有一个使用Keras和Tensorflow训练的模型作为我的后端,但现在我需要将我的模型转换为某个应用程序的张量流图。我试图做到这一点,并做出预测以确保它能够正常工作,但是当与从model.predict()收集的结果进行比较时,我会得到非常不同的值。例如:使用keras模型的张量流图进行预测

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))) 

回报:

Predictions from: 
tf graph:  [[-0.1015993 0.07432419 0.0592984 ]] 
keras predict: [[ 0.39339241 0.57949686 -3.67846966]] 

从keras值预测是正确的,但TF图形效果都没有。

如果有助于了解最终的预期应用程序,我使用tf.gradients()函数创建了一个雅可比矩阵,但是当与theano的雅可比函数比较时,它不会返回正确的结果,从而得到正确的雅可比。这里是我的tensorflow雅可比代码:

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) 

编辑:型号代码

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') 
+0

我不太了解你的代码。你能更清楚地了解你如何加载和导出你的代码? 'load_model'做什么?模型定义在哪里?另外我认为使用'global_variables_initializer'是很危险的,你可以更加明确地说明你如何创建张量流模型? – maxymoo

+0

@maxymoo感谢您的评论,我添加了用于创建张量流模型的代码,并更正了以前的代码以正确定义模型变量。我同意使用'global_variables_initializer'有点令人担忧,但是当我不收到错误:'FailedPreconditionError:试图使用未初始化的值dense_14/bias'。有关如何解决这个问题的任何想法? – Starnetter

+0

你确定它是用TF训练的吗? – frankyjuang

回答

8

@frankyjuang联系我在这里

https://github.com/amir-abdi/keras_to_tensorflow

,这与代码

结合https://github.com/metaflow-ai/blog/blob/master/tf-freeze/load.py

https://github.com/tensorflow/tensorflow/issues/675

我已经找到了解决这两个预测使用TF图形和创建雅可比功能:

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 

电话:

tf_model_path = convert_to_pb('model_file.h5','/model_dir/','/model_dir/') 

创建功能以图表形式加载tf模型:

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 

创建功能,使模型预测使用TF图

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 

作出预测:

tf_predictions = predict(tf_model_path,test_data) 

雅可比功能:

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 

计算雅可比矩阵:

jacobians = compute_jacobian(tf_model_path,test_data) 
+0

是否有某种方式可以通过保存load_graph()函数返回的元组或者甚至可以保存张量值x来加快预测时间和y。我只希望预测能够快速预测只有一个样本的结论。 – Mohsin