keras LSTM 模型 - 与 tflite 一起使用的 tf 1.15 等效模型

问题描述

TLDR:如何使用 tf.lite.experimental.nn.TFLiteLSTMCell,tf.lite.experimental.nn.dynamic_rnn 而不是 keras.layers.LSTM 来实现此模型?

enter image description here

我在 keras 中有这个网络:

inputs = keras.Input(shape=(1,52))
state_1_h = keras.Input(shape=(200,))
state_1_c = keras.Input(shape=(200,))
x1,state_1_h_out,state_1_c_out = layers.LSTM(200,return_sequences=True,input_shape=(sequence_length,52),return_state=True)(inputs,initial_state=[state_1_h,state_1_c])
output = layers.Dense(13)(x1)

model = keras.Model([inputs,state_1_h,state_1_c],[output,state_1_c_out])

我需要在 tensorflow 1.15 中实现它,但要以与 tflite 1.15 兼容的方式实现。 ** 这意味着我不能使用 keras.layers.LSTM,因为它与 tflite 1.15 不兼容。 **

按照这个例子,我看到了教程:https://github.com/tensorflow/tensorflow/tree/r1.15/tensorflow/lite/experimental/examples/lstm https://github.com/tensorflow/tensorflow/blob/r1.15/tensorflow/lite/experimental/examples/lstm/TensorFlowLite_LSTM_Keras_Tutorial.ipynb

其中解释了如何以与 tflite 1.15 兼容的方式实现 LSTM。 我知道我需要使用以下层:tf.lite.experimental.nn.TFLiteLSTMCell,tf.lite.experimental.nn.dynamic_rnn

困难的部分是这一行:

x1,state_1_c])

我按照文档来实现它:

dynamic_rnn documentation 解释了如何为动态 rnn 提供初始状态。

我尝试在提供的 buildLstmLayer 函数中使用它(应该实现 LSTM):

def buildLstmLayer(inputs,num_layers,num_units):
  """Build the lstm layer.

  Args:
    inputs: The input data.
    num_layers: How many LSTM layers do we want.
    num_units: The unmber of hidden units in the LSTM cell.
  """
  lstm_cells = []
  for i in range(num_layers):
    lstm_cells.append(
        tf.lite.experimental.nn.TFLiteLSTMCell(
            num_units,forget_bias=0,name='rnn{}'.format(i)))
  lstm_layers = tf.keras.layers.StackedRNNCells(lstm_cells)
  # Assume the input is sized as [batch,time,input_size],then we're going
  # to transpose to be time-majored.
  transposed_inputs = tf.transpose(
      inputs,perm=[1,2])
  outputs,_ = tf.lite.experimental.nn.dynamic_rnn(
      lstm_layers,transposed_inputs,dtype='float32',time_major=True)
  unstacked_outputs = tf.unstack(outputs,axis=0)
  return unstacked_outputs[-1]

这是我的代码

import os
os.environ['TF_ENABLE_CONTROL_FLOW_V2'] = '1'
from tensorflow.keras import Model

import tensorflow as tf
print(f"tf version: {tf.__version__},tf.keras version: {tf.keras.__version__}")
from tensorflow.keras.utils import plot_model

def buildLstmLayer(merged_inputs,num_units):
  inputs = merged_inputs[0]
  state_1_h_keras = merged_inputs[1]
  state_1_c_keras = merged_inputs[2]
  initial_state = tf.nn.rnn_cell.LSTMStateTuple(state_1_h_keras,state_1_c_keras)
  cell = tf.lite.experimental.nn.TFLiteLSTMCell(num_units,state_is_tuple=True)

  outputs,out_states = tf.lite.experimental.nn.dynamic_rnn(
      cell,inputs,time_major=True,initial_state=initial_state)
  state_1_h_out,state_1_c_out = out_states
  return outputs,state_1_c_out

tf.reset_default_graph()

inputs = tf.keras.layers.Input(shape=(1,name='input')
batch_size = tf.shape(inputs)[1]
cell = tf.nn.rnn_cell.BasicLSTMCell(200,state_is_tuple=True)
initial_state = cell.zero_state(batch_size,tf.float32)
state_1_h,state_1_c = initial_state
state_1_h_keras = tf.keras.Input(tensor=(state_1_h),name='state_1_h')
state_1_c_keras = tf.keras.Input(tensor=(state_1_c),name='state_1_c')
x1,state_1_c_out = tf.keras.layers.Lambda(buildLstmLayer,arguments={'num_units': 200})([inputs,state_1_h_keras,state_1_c_keras])
output = tf.keras.layers.Dense(13,activation=tf.nn.softmax,name='output')(x1)
model = Model([inputs,state_1_c_keras],state_1_c_out])
sess = tf.keras.backend.get_session()
inputs_tensors = [sess.graph.get_tensor_by_name(tensor_name) for tensor_name in [x.name for x in model.inputs]]
outputs_tensors = [sess.graph.get_tensor_by_name(tensor_name) for tensor_name in [x.name for x in model.outputs]]

converter = tf.lite.TFLiteConverter.from_session(
    sess,inputs_tensors,outputs_tensors)
tflite_model = converter.convert()
print('Model converted successfully!')

模型似乎是完全相同的模型:

enter image description here

但是,converter.convert() 行返回:

Specified output array "lambda_1/lambda_1/Identity" is not produced by any op in this graph. Is it a typo? This should not happen

这个输出数组是: state_1_h_out 。这意味着 dynamic_rnn 层正在返回的状态未被图中的操作识别。

不使用输出状态:

model = Model([inputs,[output])

代码有效,转换为tflite,甚至加载到设备中!

表示当前的问题是LSTM应该返回的输出状态。 我试图通过以下方式破解它:

all_lambda_outputs = tf.keras.layers.Lambda(buildLstmLayer,state_1_c_keras])
x1 = all_lambda_outputs[0]
state_1_h_out,state_1_c_out = tf.keras.layers.Lambda(lambda tup: (tup[0],tup[1]))(all_lambda_outputs[1])

但是还是不行。

我该如何解决

谢谢

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)