Firebase本地模型引发“找不到内置操作码'CONV_2D'版本'2'的操作”

问题描述

我得到了一个看起来像这样的模型并对其进行了训练:

      keras.layers.Conv2D(128,(3,3),activation='relu',input_shape=(150,150,3)),keras.layers.MaxPooling2D(2,2),keras.layers.Dropout(0.5),keras.layers.Conv2D(256,activation='relu'),keras.layers.Conv2D(512,keras.layers.Flatten(),keras.layers.Dropout(0.3),keras.layers.Dense(280,keras.layers.Dense(4,activation='softmax')
    ])

我使用以下代码将其转换为.tflite:

import tensorflow as tf
converter = tf.compat.v1.lite.TFLiteConverter.from_keras_model_file("model.h5")
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.post_training_quantize=True
converter.allow_custom_ops=True

tflite_model = converter.convert()

open("model.tflite","wb").write(tflite_model)

然后我要它与本地Firebase一起使用:

 val bitmap = Bitmap.createScaledBitmap(image,true)

        val batchNum = 0
        val input = Array(1) { Array(150) { Array(150) { FloatArray(3) } } }
        for (x in 0..149) {
            for (y in 0..149) {
                val pixel = bitmap.getPixel(x,y)
                input[batchNum][x][y][0] = (Color.red(pixel) - 127) / 255.0f
                input[batchNum][x][y][1] = (Color.green(pixel) - 127) / 255.0f
                input[batchNum][x][y][2] = (Color.blue(pixel) - 127) / 255.0f
            }


        }
        val localModel = FirebaseCustomLocalModel.Builder()
            .setAssetFilePath("model.tflite")
            .build()
val interpreter = FirebaseModelInterpreter.getInstance(FirebaseModelInterpreterOptions.Builder(localModel).build())
                val inputOutputoptions = FirebaseModelInputOutputoptions.Builder()
                    .setInputFormat(0,FirebaseModelDataType.FLOAT32,intArrayOf(1,3))
                    .setoutputFormat(0,4))
                    .build()

                val inputs = FirebaseModelInputs.Builder()
                    .add(input)
                    .build()
                interpreter?.run(inputs,inputOutputoptions)
                    ?.addOnSuccessListener { result ->
                        val output = result.getoutput<Array<FloatArray>>(0)
                        val probabilities = output[0]




但是它会引发此错误


Internal error: Cannot create interpreter: Didn't find op for builtin opcode 'CONV_2D' version '2'

有人知道我在做什么错吗?我正在使用tensorflow-gpu和tensorflow-estimator 2.3.0

解决方法

查看你在训练时使用的 Tensorflow 版本,在 android build.gridle(app) 中使用相同的版本。 我在训练时使用 tensorflow 2.4.0(这是最新的),所以我把(实现 'org.tensorflow:tensorflow-lite:2.4.0')放在我的 android build.gridle(app) 中

,

TFLite运算符具有不同的versions。看来您已使用较新版本的Conv2D转换了模型,而当前的解释器不支持它。

尝试scheme时,我在Android上遇到了该问题。因此,我建议您在一开始就放弃优化和自定义操作:

converter.optimizations = [tf.lite.Optimize.DEFAULT]
,

我通过以下更改修复了它:

我像这样 (tf-gpu 2.2.0) 或通过我的回调 (.pb) 保存了我的模型:

tf.saved_model.save(trainedModel,path)

在 build.gradle 中我添加了:

implementation 'org.tensorflow:tensorflow-lite:0.0.0-nightly'
implementation'org.tensorflow:tensorflow-lite-gpu:0.0.0-nightly'

我通过运行将我的 tensorflow 版本(仅用于转换器)更新为 tf-nightly (2.5.0):

pip3 install tf-nightly

并使用此代码(感谢 Alex K.):

new_model= tf.keras.models.load_model(filepath=path)
converter = tf.lite.TFLiteConverter.from_keras_model(new_model)
converter.optimizations = []
converter.allow_custom_ops=False
converter.experimental_new_converter = True
tflite_model = converter.convert()
open("model.tflite","wb").write(tflite_model)

就是这样。