Open seanshpark opened 1 year ago
related #8217 previous #4528
derived tasks from study
UnidirectionalSequenceLSTM
Op # tflite export for experiments
converter = tf.lite.TFLiteConverter.from_keras_model(m.model)
converter.allow_custom_ops = True
converter.experimental_new_converter = True
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS]
tflite_model = converter.convert()
gives
error: failed to legalize operation 'tf.TensorListReserve' that was explicitly marked illegal error: Lowering tensor list ops is failed. Please consider using Select TF ops and disabling
_experimental_lower_tensor_list_ops
flag in the TFLite converter object. For example, converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS, tf.lite.OpsSet.SELECT_TF_OPS]\n converter._experimental_lower_tensor_list_ops = False
With converter._experimental_lower_tensor_list_ops = False
,
The following operation(s) need TFLite custom op implementation(s): Custom ops: TensorListFromTensor, TensorListGetItem, TensorListReserve, TensorListSetItem, TensorListStack Details: tf.TensorListFromTensor(tensor<4x?x4xf32>, tensor<2xi32>) -> (tensor<!tf_type.variant<tensor<?x4xf32>>>) : {device = ""} tf.TensorListGetItem(tensor<!tf_type.variant<tensor<?x4xf32>>>, tensor
, tensor<2xi32>) -> (tensor<?x4xf32>) : {device = ""} tf.TensorListReserve(tensor<2xi32>, tensor ) -> (tensor<!tf_type.variant<tensor<?x2xf32>>>) : {device = ""} tf.TensorListSetItem(tensor<!tf_type.variant<tensor<?x2xf32>>>, tensor , tensor<?x2xf32>) -> (tensor<!tf_type.variant<tensor<?x2xf32>>>) : {device = ""} tf.TensorListStack(tensor<!tf_type.variant<tensor<?x2xf32>>>, tensor<2xi32>) -> (tensor<?x?x2xf32>) : {device = "", num_elements = -1 : i64} See instructions: https://www.tensorflow.org/lite/guide/ops_custom
Custom ops: TensorListFromTensor, TensorListGetItem, TensorListReserve, TensorListSetItem, TensorListStack
NOT feasible... or is it?
keras.layers.LSTM
has option unroll
, default False
.
Let's give this a True
and see...
--> produces an unrolled tflite
--> there are unknown shape
Operands: T(subgraph index : tensor index) TYPE (shape) (shape_signature) B(buffer index) (variable) OperandName
T(0:0) FLOAT32 (1, 4, 4) (-1, 4, 4) B(1) serving_default_lstm_input:0
...
T(0:12) FLOAT32 (4, 1, 4) (4, -1, 4) B(13) sequential/lstm/transpose
tried...
import tensorflow as tf
import numpy as np
from tensorflow import keras
model = keras.Sequential()
shape = (4, 4)
model.add(keras.layers.LSTM(2, input_shape=shape, unroll=True))
model.compile(optimizer="adam", loss="mse", metrics=["accuracy"])
input_data = np.random.random((1, 4, 4))
target_data = np.random.random((1, 2))
model.fit(input_data, target_data, batch_size=1)
--> no luck
give input with fixed shape?
import tensorflow as tf
import numpy as np
from tensorflow import keras
model = keras.Sequential()
shape = (4, 4)
model.add(keras.layers.InputLayer(input_shape=shape, batch_size=1))
model.add(keras.layers.LSTM(2, input_shape=shape, unroll=True))
--> add InputLayer
with fixed batch size.
--> Yes!
--> also TRIX compilation is also OK
[onecc]
one-import-tf=True
one-import-tflite=False
one-import-bcq=False
one-import-onnx=False
one-optimize=True
one-quantize=True
one-pack=False
one-codegen=False
[one-import-tf]
input_path=lstm_unroll.h5
output_path=lstm_unroll.circle
model_format=keras_model
[one-optimize]
input_path=./lstm_unroll.circle
output_path=./lstm_unroll.opt.circle
[one-quantize]
input_path=./lstm_unroll.opt.circle
output_path=./lstm_unroll.opt.q8.circle
Without unroll=True
argument,
# NOTE tested with TF 2.8.0
import tensorflow as tf
import numpy as np
from tensorflow import keras
model = keras.Sequential()
shape = (4, 4)
model.add(keras.layers.InputLayer(input_shape=shape, batch_size=1))
model.add(keras.layers.LSTM(2, input_shape=shape))
gives tflite with one UnidirectionalSequenceLSTM
Op.
And with return_sequences=True
# NOTE tested with TF 2.8.0
import tensorflow as tf
import numpy as np
from tensorflow import keras
model = keras.Sequential()
shape = (4, 4)
model.add(keras.layers.InputLayer(input_shape=shape, batch_size=1))
model.add(keras.layers.LSTM(2, input_shape=shape, return_sequences=True))
gives single Op.
from https://www.tensorflow.org/lite/models/convert/rnn#bidirectional_lstm,
This is future work
# NOTE tested with TF 2.8.0
import tensorflow as tf
import numpy as np
from tensorflow import keras
model = keras.Sequential() shape = (4, 4)
model.add(keras.layers.InputLayer(input_shape=shape, batch_size=1)) lstmf = keras.layers.LSTM(2, return_sequences=True) lstmb = keras.layers.LSTM(2, return_sequences=True, go_backwards=True) model.add(keras.layers.Bidirectional(lstmf, backward_layer=lstmb, input_shape=shape))
got
![image](https://user-images.githubusercontent.com/4616940/197650446-ad492d9a-9033-4807-baf5-d32340f7a91f.png)
SimpleRNN
with unroll=True
# NOTE tested with TF 2.8.0
import tensorflow as tf
import numpy as np
from tensorflow import keras
model = keras.Sequential()
shape = (4, 4)
model.add(keras.layers.InputLayer(input_shape=shape, batch_size=1))
model.add(keras.layers.SimpleRNN(2, input_shape=shape, unroll=True))
gives
TRIX code generaion is OK
GRU unroll
# NOTE tested with TF 2.8.0
from tensorflow import keras
model = keras.Sequential()
shape = (4, 4)
model.add(keras.layers.InputLayer(input_shape=shape, batch_size=1))
model.add(keras.layers.GRU(2, input_shape=shape, unroll=True))
RNN + LSTMCell
# NOTE tested with TF 2.8.0
from tensorflow import keras
model = keras.Sequential()
shape = (4, 4)
model.add(keras.layers.InputLayer(input_shape=shape, batch_size=1))
lstmcell = keras.layers.LSTMCell(2)
model.add(keras.layers.RNN(lstmcell, input_shape=shape, unroll=True))
TRIX codegen is OK
RNN + GRUCell
# NOTE tested with TF 2.8.0
from tensorflow import keras
model = keras.Sequential()
shape = (4, 4)
model.add(keras.layers.InputLayer(input_shape=shape, batch_size=1))
grucell = keras.layers.GRUCell(2)
model.add(keras.layers.RNN(grucell, input_shape=shape, unroll=True))
Current CFE UnidirectionalSequenceLSTM
status
Items left to enable
(1) Prepare empty classes
(2) fill in with kernels, tests (3) fix tests to success
RNN? GRU? in tflite?
How can we drop RNN
Op from python?
tensorflow/compiler/mlir/lite
...struct LegalizeUnidirectionalSequenceRnn : public RewritePattern
if (op->getNumOperands() != 5) {
op->emitError()
<< "We're expecting 5 inputs for UnidirectionalSequenceRNN, only "
<< op->getNumOperands() << " provided";
return failure();
}
if (op->getNumResults() != 2) {
op->emitError()
<< "We're expecting 2 inputs for UnidirectionalSequenceRNN, only "
<< op->getNumResults() << " found";
return failure();
}
?
in tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc
const char kUnidirectionalSequenceRnnOp[] =
"name: 'UnidirectionalSequenceRnn' input_arg: {name: 'Input' type: "
"DT_FLOAT} input_arg: { name: 'Weights' type: DT_FLOAT } "
"input_arg: { name: 'RecurrentWeights' type: DT_FLOAT } input_arg: { "
"name: 'Bias' type: DT_FLOAT} "
"input_arg: { name: 'HiddenState' type: DT_FLOAT} "
"output_arg: { name: "
"'LastState' type: DT_FLOAT } output_arg: { name: 'Output' type: "
"DT_FLOAT} "
"attr : { name: '_tflite_input_indices' type: 'list(int)'}";
--> how to make this Op(?)/Layer(?) is a question...
from https://www.tensorflow.org/lite/models/convert/rnn#bidirectional_lstm,
- says
This is future work
- tried this like
# NOTE tested with TF 2.8.0 import tensorflow as tf import numpy as np from tensorflow import keras model = keras.Sequential() shape = (4, 4) model.add(keras.layers.InputLayer(input_shape=shape, batch_size=1)) lstmf = keras.layers.LSTM(2, return_sequences=True) lstmb = keras.layers.LSTM(2, return_sequences=True, go_backwards=True) model.add(keras.layers.Bidirectional(lstmf, backward_layer=lstmb, input_shape=shape))
got
According to https://www.tensorflow.org/lite/models/convert/rnn#user-defined_lstm_conversion_examples
Bidirectional LSTM is currently modelled as two UnidirectionalSequenceLSTM operations in TensorFlow Lite. This will be replaced with a single BidirectionalSequenceLSTM op.
Also I studied tensorflow repo and there is recent activity on this. So I am going to implement BidirectionalSequenceLSTM Kernel in ONE - so we can activate this as soon as it will be implemented in tensorflow's converter
Let's findout how to import TensorFlow LSTM operator.
reference: