1

我有一个简单的张量流模型,它由 lstm 层组成 - 例如tf.contrib.rnn.LSTMBlockCelltf.keras.layers.LSTM(如果需要,我也可以提供示例代码)。我想在 iOS 应用程序上运行模型。然而,我看过几个网站说目前没有办法在 iOS 应用程序上转换和运行由 LSTM 层组成的 tensorflow 模型

我已经尝试使用这些工具/库将 tensorflow 模型转换为 .mlmodel 格式(或 .tflite 格式)
1. Swift for Tensorflow
2. Tensorflow Lite for iOS
3. tfcoreml

但是,这些工具似乎也无法将 lstm 层模型转换为 .mlmodel 格式。但是,这些工具允许使用要添加的自定义层。但我不知道如何添加 LSTM 自定义层。

我说不支持在 iOS 应用程序中运行 tensorflow lstm 模型是错误的吗?如果是,那么请指导我如何继续将模型包含在 iOS 应用程序中。是否有任何其他工具/库可用于将其转换为 .mlmodel 格式。如果没有,那么是否有计划在未来包括对 iOS 的 tensorflow 支持?

模型

import tensorflow as tf
from tensorflow.contrib import rnn
from tensorflow.contrib.rnn import *

# Import MNIST data
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("/tmp/data/", one_hot=True)


#Summary parameters
logs_path = "logs/"

# Training Parameters
learning_rate = 0.001
training_steps = 1000
batch_size = 128
display_step = 200

# Network Parameters
num_input = 28 # MNIST data input (img shape: 28*28)
timesteps = 28 # timesteps
num_hidden = 128 # hidden layer num of features
num_classes = 10 # MNIST total classes (0-9 digits)

# tf Graph input
X = tf.placeholder("float", [None, timesteps, num_input])
Y = tf.placeholder("float", [None, num_classes])

# Define weights
weights = {
    'out': tf.Variable(tf.random_normal([num_hidden, num_classes]))
}
biases = {
    'out': tf.Variable(tf.random_normal([num_classes]))
}


def RNN(x, weights, biases):
    # Unstack to get a list of 'timesteps' tensors of shape (batch_size, n_input)
    x = tf.unstack(x, timesteps, 1)

    # Define a lstm cell with tensorflow
    lstm_cell = rnn.LSTMBlockCell(num_hidden, forget_bias = 1.0)
    #lstm_cell = tf.keras.layers.LSTMCell(num_hidden, unit_forget_bias=True)

    # Get lstm cell output
    outputs, states = rnn.static_rnn(lstm_cell, x, dtype=tf.float32)

    # Linear activation, using rnn inner loop last output
    return tf.matmul(outputs[-1], weights['out']) + biases['out']

logits = RNN(X, weights, biases)
with tf.name_scope('Model'):
    prediction = tf.nn.softmax(logits, name = "prediction_layer")

with tf.name_scope('Loss'):
    # Define loss and optimizer
    loss_op = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=Y, name = "loss_layer"), name = "reduce_mean_loss")

with tf.name_scope('SGD'):
    optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate, name = "Gradient_Descent")
    train_op = optimizer.minimize(loss_op, name = "minimize_layer")


with tf.name_scope('Accuracy'):
    # Evaluate model (with test logits, for dropout to be disabled)
    correct_pred = tf.equal(tf.argmax(prediction, 1), tf.argmax(Y, 1), name = "correct_pred_layer")
    accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32), name = "reduce_mean_acc_layer")

# Initialize the variables (i.e. assign their default value)
init = tf.global_variables_initializer()

#Create a summary to monitor cost tensor
tf.summary.scalar("loss", loss_op)
#Create a summary to monitor accuracy tensor
tf.summary.scalar("accuracy", accuracy)
#Merge all summaries into a single op
merged_summary_op = tf.summary.merge_all()

saver = tf.train.Saver()
save_path = ""
model_save = "model.ckpt"

# Start training
with tf.Session() as sess:

    # Run the initializer
    sess.run(init)

    # op to write logs to Tensorboard
    summary_writer = tf.summary.FileWriter(logs_path, graph=tf.get_default_graph())

    for step in range(1, training_steps+1):
        total_batch = int(mnist.train.num_examples/batch_size)

        batch_x, batch_y = mnist.train.next_batch(batch_size)
        # Reshape data to get 28 seq of 28 elements
        batch_x = batch_x.reshape((batch_size, timesteps, num_input))
        # Run optimization op (backprop)
        sess.run(train_op, feed_dict={X: batch_x, Y: batch_y})
        if step % display_step == 0 or step == 1:
            # Calculate batch loss and accuracy
            loss, acc, summary = sess.run([loss_op, accuracy, merged_summary_op], feed_dict={X: batch_x,
                                                                 Y: batch_y})

            # Write logs at every iteration
            summary_writer.add_summary(summary, step * total_batch)

            print("Step " + str(step) + ", Minibatch Loss= " + \
                  "{:.4f}".format(loss) + ", Training Accuracy= " + \
                  "{:.3f}".format(acc))
    saver.save(sess, model_save)
    tf.train.write_graph(sess.graph_def, save_path, 'save_graph.pbtxt')
    #print(sess.graph.get_operations())

    print("Optimization Finished!")

    print("Run the command line:\n" \
            "--> tensorboard --logdir=logs/ " \
            "\nThen open http://0.0.0.0:6006/ into your web browser")

    # Calculate accuracy for 128 mnist test images
    test_len = 128
    test_data = mnist.test.images[:test_len].reshape((-1, timesteps, num_input))
    test_label = mnist.test.labels[:test_len]
    print("Testing Accuracy:", \
        sess.run(accuracy, feed_dict={X: test_data, Y: test_label}))

生成冻结模型的代码

import tensorflow as tf
import numpy as np
from tensorflow.python.tools import freeze_graph

save_path = ""
model_name = "test_model_tf_keras_layers_lstm"
input_graph_path = save_path + "save_graph.pbtxt"
checkpoint_path = save_path + "model.ckpt"
input_saver_def_path = ""
input_binary = False
output_node_names = "Model/prediction_layer" #output node's name. Should match to that mentioned in the code
restore_op_name = 'save/restore_all'
filename_tensor_name = 'save/const:0'
output_frozen_graph_name = save_path + 'frozen_model' + '.pb'   # name of .pb file that one would like to give
clear_devices = True

freeze_graph.freeze_graph(input_graph_path, input_saver_def_path, input_binary, checkpoint_path, output_node_names, restore_op_name, filename_tensor_name, output_frozen_graph_name, clear_devices, "")
print("Model Freezed")

生成 .mlmodel 格式文件的转换代码

import tfcoreml

coreml_model = tfcoreml.convert(tf_model_path = 'frozen_model_test_model_tf_keras_layers_lstm.pb', 
                      mlmodel_path = 'test_model.mlmodel', 
                      output_feature_names = ['Model/prediction_layer:0'], 
                      add_custom_layers = True)


coreml_model.save("test_model.mlmodel")

显示的错误消息 lstm_cell = rnn.BasicLSTMCell(num_hidden, name = "lstm_cell")

Value Error: Split op case not handled. Input shape = [1, 512], output shape = [1, 128]

显示的错误消息 lstm_cell = rnn.LSTMBlockCell(num_hidden, name = "lstm_cell")

InvalidArgumentError (see above for traceback): No OpKernel was registered to support Op 'LSTMBlockCell' used by node rnn/lstm_cell/LSTMBlockCell (defined at /anaconda2/lib/python2.7/site-packages/tfcoreml/_tf_coreml_converter.py:153) with these attrs: [forget_bias=1, use_peephole=false, cell_clip=-1, T=DT_FLOAT]
Registered devices: [CPU]
Registered kernels:
  <no registered kernels>

     [[node rnn/lstm_cell/LSTMBlockCell (defined at /anaconda2/lib/python2.7/site-packages/tfcoreml/_tf_coreml_converter.py:153) ]]

我希望冻结的张量流模型可以转换为 .mlmodel 格式。

4

0 回答 0