Как получить выходной тензор из определенного слоя?

Я хотел бы выяснить, возможно ли получить вывод из определенного слоя, используя tensorflow lite для среды Android. На данный момент я знаю, что с помощью: 'interpreter.run()' мы получаем "стандартный" вывод, но это не то, что я ищу. Спасибо за любой совет.


person Simo    schedule 27.05.2020    source источник
comment
В настоящее время я не думаю, что есть способ сделать это. Когда прогон логического вывода завершен, интересующий вас промежуточный вывод может быть или не быть доступным в памяти, потому что TFLite агрессивно пытается повторно использовать ранее использованную тензорную память на более поздних этапах. Каков именно ваш вариант использования?   -  person yyoon    schedule 28.05.2020
comment
Не могли бы вы лучше объяснить мне ту часть, когда вы сказали, что Tflite повторно использует ранее использованный тензор? Я задал этот вопрос, потому что мне нужно получить выходные данные с другого уровня сети для некоторых экспериментов в мобильной среде. Я видел, что объект интерпретатора имеет метод getOutputTensor(int index), который теоретически (потому что я не могу найти API для объяснения) дает тензор по указанному индексу, но я не совсем понял, как это работает...   -  person Simo    schedule 28.05.2020
comment
Конечно. Для пояснения упростим и скажем, что граф имеет 4 узла, выполняемых последовательно: вход -> A -> B -> C -> D -> вывод. К тому времени, когда вы выполняете узел C, вывод A уже был использован B и, следовательно, больше не нужен в памяти. Таким образом, память, используемая для хранения выходных данных узла А, может быть повторно использована для хранения выходных данных узла С. После того, как вывод полностью выполнен, вы не можете получить вывод A, потому что он уже перезаписан выводом другого узла. См. этот комментарий: github.com/tensorflow/ тензорный поток/блоб/мастер/тензорный поток/облегченный/   -  person yyoon    schedule 28.05.2020
comment
Значит, нет возможности получить вывод, например, из узла C?   -  person Simo    schedule 28.05.2020
comment
Технически это возможно, если получить объект TfLiteNode конкретного узла, а затем проверить выходные данные. См. мой недавний ответ на аналогичный вопрос здесь: stackoverflow.com/a/62015028/922135. В вашем случае вы хотели бы проверить выходы. Но опять же, имейте в виду, что значение, которое вы читаете, может быть неправильным, если позже оно будет перезаписано другими слоями.   -  person yyoon    schedule 28.05.2020
comment
Но для этого мне нужно использовать C++ API, верно? Есть ли способ сделать это в Java?   -  person Simo    schedule 28.05.2020
comment
К сожалению, я не думаю, что эта функциональность представлена ​​в Java API, так как обычно вам не нужно это делать.   -  person yyoon    schedule 28.05.2020
comment
Хорошо, большое спасибо, ценю!   -  person Simo    schedule 28.05.2020
comment
Где я могу найти C++ API?   -  person Simo    schedule 28.05.2020
comment
См. tensorflow.org/lite/guide/android#build_c_libraries для сборки C++ API. инструкции для Android и tensorflow.org/lite/api_docs/cc для справки по API. документация.   -  person yyoon    schedule 28.05.2020
comment
Извините, что снова вас беспокою, но у меня есть вопрос. В своем первом комментарии вы сказали, что после завершения логического вывода промежуточный вывод не может быть доступен в памяти. И с этим я понял, почему, но вместо этого есть ли способ не выполнять полный вывод, а запуск, который заканчивается на промежуточном слое, на котором я хочу извлечь тензор? Или это одно и то же?   -  person Simo    schedule 29.05.2020
comment
Нет, частично выполнить вашу модель невозможно. Возможно, для ваших нужд лучше использовать обычный TF вместо TFLite. Есть ли причина использовать именно TFLite?   -  person yyoon    schedule 30.05.2020
comment
Мне нужен Tflite, потому что я хотел бы провести некоторые эксперименты в мобильной среде, и для этого мне нужны эти тензоры, взятые из определенного слоя. Вы знаете другой способ добиться этого?   -  person Simo    schedule 30.05.2020
comment
Если использование TF действительно не ваш вариант, я не думаю, что есть простой способ сделать это. Вы можете изменить исходный код TFLite и создать свой собственный TFLite для достижения этой цели, но я боюсь, что не смогу помочь с этим процессом.   -  person yyoon    schedule 30.05.2020
comment
Что ж, базовый Tf может быть вариантом, если есть способ интегрировать его в мобильную среду.   -  person Simo    schedule 30.05.2020
comment
Привет, еще раз, извините, но я не понимаю, как настроить мой проект Android для использования tensorflow lite C++ API, у вас есть предложения?   -  person Simo    schedule 03.06.2020


Ответы (1)


@Simo Я напишу здесь обходной путь этой проблемы. Как насчет сохранения части модели, которую вы хотите, в файл .tflite. Позвольте мне объяснить себя. Вместо того, чтобы делать ниже и сохранять всю модель:

# WHOLE MODEL
tflite_model = tf.keras.models.load_model('face_recog.weights.best.hdf5')
converter = tf.lite.TFLiteConverter.from_keras_model(tflite_model)
tflite_save = converter.convert()
open("face_recog.tflite", "wb").write(tflite_save)

Вы можете распечатать слои вашей модели keras:

print([layer.name for layer in keras_model.layers])
Output:
['anchor', 'positive', 'negative', 'model', 'lambda']

print([layer.name for layer in keras_model.get_layer('model').layers])
Output:  
['input_1', 'Conv1_pad', 'Conv1', 'bn_Conv1', 'Conv1_relu', 'expanded_conv_depthwise', 'expanded_conv_depthwise_BN', 'expanded_conv_depthwise_relu', 'expanded_conv_project', 'expanded_conv_project_BN', 'block_1_expand', 'block_1_expand_BN', 'block_1_expand_relu', 'block_1_pad', 'block_1_depthwise', 'block_1_depthwise_BN', 'block_1_depthwise_relu', 'block_1_project', 'block_1_project_BN', 'block_2_expand', 'block_2_expand_BN', 'block_2_expand_relu', 'block_2_depthwise', 'block_2_depthwise_BN', 'block_2_depthwise_relu', 'block_2_project', 'block_2_project_BN', 'block_2_add', 'block
# PART OF MODEL
tflite_model = tf.keras.models.load_model('face_recog.weights.best.hdf5')
converter = tf.lite.TFLiteConverter.from_keras_model(tflite_model.get_layer('model'))
tflite_save = converter.convert()
open("face_recog.tflite", "wb").write(tflite_save)
expand', 'block
# PART OF MODEL
tflite_model = tf.keras.models.load_model('face_recog.weights.best.hdf5')
converter = tf.lite.TFLiteConverter.from_keras_model(tflite_model.get_layer('model'))
tflite_save = converter.convert()
open("face_recog.tflite", "wb").write(tflite_save)
expand_BN', 'block
# PART OF MODEL
tflite_model = tf.keras.models.load_model('face_recog.weights.best.hdf5')
converter = tf.lite.TFLiteConverter.from_keras_model(tflite_model.get_layer('model'))
tflite_save = converter.convert()
open("face_recog.tflite", "wb").write(tflite_save)
expand_relu', 'block
# PART OF MODEL
tflite_model = tf.keras.models.load_model('face_recog.weights.best.hdf5')
converter = tf.lite.TFLiteConverter.from_keras_model(tflite_model.get_layer('model'))
tflite_save = converter.convert()
open("face_recog.tflite", "wb").write(tflite_save)
pad', 'block
# PART OF MODEL
tflite_model = tf.keras.models.load_model('face_recog.weights.best.hdf5')
converter = tf.lite.TFLiteConverter.from_keras_model(tflite_model.get_layer('model'))
tflite_save = converter.convert()
open("face_recog.tflite", "wb").write(tflite_save)
depthwise', 'block
# PART OF MODEL
tflite_model = tf.keras.models.load_model('face_recog.weights.best.hdf5')
converter = tf.lite.TFLiteConverter.from_keras_model(tflite_model.get_layer('model'))
tflite_save = converter.convert()
open("face_recog.tflite", "wb").write(tflite_save)
depthwise_BN', 'block
# PART OF MODEL
tflite_model = tf.keras.models.load_model('face_recog.weights.best.hdf5')
converter = tf.lite.TFLiteConverter.from_keras_model(tflite_model.get_layer('model'))
tflite_save = converter.convert()
open("face_recog.tflite", "wb").write(tflite_save)
depthwise_relu', 'block
# PART OF MODEL
tflite_model = tf.keras.models.load_model('face_recog.weights.best.hdf5')
converter = tf.lite.TFLiteConverter.from_keras_model(tflite_model.get_layer('model'))
tflite_save = converter.convert()
open("face_recog.tflite", "wb").write(tflite_save)
project', 'block
# PART OF MODEL
tflite_model = tf.keras.models.load_model('face_recog.weights.best.hdf5')
converter = tf.lite.TFLiteConverter.from_keras_model(tflite_model.get_layer('model'))
tflite_save = converter.convert()
open("face_recog.tflite", "wb").write(tflite_save)
project_BN', 'block
interpreter = tf.lite.Interpreter('face_recog.tflite')
print(interpreter.get_output_details())
interpreter.get_tensor_details()
expand', 'block
interpreter = tf.lite.Interpreter('face_recog.tflite')
print(interpreter.get_output_details())
interpreter.get_tensor_details()
expand_BN', 'block
interpreter = tf.lite.Interpreter('face_recog.tflite')
print(interpreter.get_output_details())
interpreter.get_tensor_details()
expand_relu', 'block
interpreter = tf.lite.Interpreter('face_recog.tflite')
print(interpreter.get_output_details())
interpreter.get_tensor_details()
depthwise', 'block
interpreter = tf.lite.Interpreter('face_recog.tflite')
print(interpreter.get_output_details())
interpreter.get_tensor_details()
depthwise_BN', 'block
interpreter = tf.lite.Interpreter('face_recog.tflite')
print(interpreter.get_output_details())
interpreter.get_tensor_details()
depthwise_relu', 'block
interpreter = tf.lite.Interpreter('face_recog.tflite')
print(interpreter.get_output_details())
interpreter.get_tensor_details()
project', 'block
interpreter = tf.lite.Interpreter('face_recog.tflite')
print(interpreter.get_output_details())
interpreter.get_tensor_details()
project_BN', 'block
interpreter = tf.lite.Interpreter('face_recog.tflite')
print(interpreter.get_output_details())
interpreter.get_tensor_details()
add', 'block
// Initialize interpreter
@Throws(IOException::class)
private suspend fun initializeInterpreter(app: Application) = withContext(Dispatchers.IO) {
    // Load the TF Lite model from asset folder and initialize TF Lite Interpreter without NNAPI enabled.
    val assetManager = app.assets
    val model = loadModelFile(assetManager, "face_recog_model_layer.tflite")
    val options = Interpreter.Options()
    options.setUseNNAPI(false)
    interpreter = Interpreter(model, options)
    // Reads type and shape of input and output tensors, respectively.
    val imageTensorIndex = 0
    val imageShape: IntArray =
        interpreter.getInputTensor(imageTensorIndex).shape() 
    Log.i("INPUT_TENSOR_WHOLE", Arrays.toString(imageShape))
    val imageDataType: DataType =
        interpreter.getInputTensor(imageTensorIndex).dataType()
    Log.i("INPUT_DATA_TYPE", imageDataType.toString())
    val probabilityTensorIndex = 0
    val probabilityShape: IntArray =
        interpreter.getOutputTensor(probabilityTensorIndex).shape()
    Log.i("OUTPUT_TENSOR_SHAPE", Arrays.toString(probabilityShape))
    val probabilityDataType: DataType =
        interpreter.getOutputTensor(probabilityTensorIndex).dataType()
    Log.i("OUTPUT_DATA_TYPE", probabilityDataType.toString())
    Log.i(TAG, "Initialized TFLite interpreter.")

}

@Throws(IOException::class)
private fun loadModelFile(assetManager: AssetManager, filename: String): MappedByteBuffer {
    val fileDescriptor = assetManager.openFd(filename)
    val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
    val fileChannel = inputStream.channel
    val startOffset = fileDescriptor.startOffset
    val declaredLength = fileDescriptor.declaredLength
    return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
}
expand', 'block
// Initialize interpreter
@Throws(IOException::class)
private suspend fun initializeInterpreter(app: Application) = withContext(Dispatchers.IO) {
    // Load the TF Lite model from asset folder and initialize TF Lite Interpreter without NNAPI enabled.
    val assetManager = app.assets
    val model = loadModelFile(assetManager, "face_recog_model_layer.tflite")
    val options = Interpreter.Options()
    options.setUseNNAPI(false)
    interpreter = Interpreter(model, options)
    // Reads type and shape of input and output tensors, respectively.
    val imageTensorIndex = 0
    val imageShape: IntArray =
        interpreter.getInputTensor(imageTensorIndex).shape() 
    Log.i("INPUT_TENSOR_WHOLE", Arrays.toString(imageShape))
    val imageDataType: DataType =
        interpreter.getInputTensor(imageTensorIndex).dataType()
    Log.i("INPUT_DATA_TYPE", imageDataType.toString())
    val probabilityTensorIndex = 0
    val probabilityShape: IntArray =
        interpreter.getOutputTensor(probabilityTensorIndex).shape()
    Log.i("OUTPUT_TENSOR_SHAPE", Arrays.toString(probabilityShape))
    val probabilityDataType: DataType =
        interpreter.getOutputTensor(probabilityTensorIndex).dataType()
    Log.i("OUTPUT_DATA_TYPE", probabilityDataType.toString())
    Log.i(TAG, "Initialized TFLite interpreter.")

}

@Throws(IOException::class)
private fun loadModelFile(assetManager: AssetManager, filename: String): MappedByteBuffer {
    val fileDescriptor = assetManager.openFd(filename)
    val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
    val fileChannel = inputStream.channel
    val startOffset = fileDescriptor.startOffset
    val declaredLength = fileDescriptor.declaredLength
    return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
}
expand_BN', 'block
// Initialize interpreter
@Throws(IOException::class)
private suspend fun initializeInterpreter(app: Application) = withContext(Dispatchers.IO) {
    // Load the TF Lite model from asset folder and initialize TF Lite Interpreter without NNAPI enabled.
    val assetManager = app.assets
    val model = loadModelFile(assetManager, "face_recog_model_layer.tflite")
    val options = Interpreter.Options()
    options.setUseNNAPI(false)
    interpreter = Interpreter(model, options)
    // Reads type and shape of input and output tensors, respectively.
    val imageTensorIndex = 0
    val imageShape: IntArray =
        interpreter.getInputTensor(imageTensorIndex).shape() 
    Log.i("INPUT_TENSOR_WHOLE", Arrays.toString(imageShape))
    val imageDataType: DataType =
        interpreter.getInputTensor(imageTensorIndex).dataType()
    Log.i("INPUT_DATA_TYPE", imageDataType.toString())
    val probabilityTensorIndex = 0
    val probabilityShape: IntArray =
        interpreter.getOutputTensor(probabilityTensorIndex).shape()
    Log.i("OUTPUT_TENSOR_SHAPE", Arrays.toString(probabilityShape))
    val probabilityDataType: DataType =
        interpreter.getOutputTensor(probabilityTensorIndex).dataType()
    Log.i("OUTPUT_DATA_TYPE", probabilityDataType.toString())
    Log.i(TAG, "Initialized TFLite interpreter.")

}

@Throws(IOException::class)
private fun loadModelFile(assetManager: AssetManager, filename: String): MappedByteBuffer {
    val fileDescriptor = assetManager.openFd(filename)
    val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
    val fileChannel = inputStream.channel
    val startOffset = fileDescriptor.startOffset
    val declaredLength = fileDescriptor.declaredLength
    return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
}
expand_relu', 'block
// Initialize interpreter
@Throws(IOException::class)
private suspend fun initializeInterpreter(app: Application) = withContext(Dispatchers.IO) {
    // Load the TF Lite model from asset folder and initialize TF Lite Interpreter without NNAPI enabled.
    val assetManager = app.assets
    val model = loadModelFile(assetManager, "face_recog_model_layer.tflite")
    val options = Interpreter.Options()
    options.setUseNNAPI(false)
    interpreter = Interpreter(model, options)
    // Reads type and shape of input and output tensors, respectively.
    val imageTensorIndex = 0
    val imageShape: IntArray =
        interpreter.getInputTensor(imageTensorIndex).shape() 
    Log.i("INPUT_TENSOR_WHOLE", Arrays.toString(imageShape))
    val imageDataType: DataType =
        interpreter.getInputTensor(imageTensorIndex).dataType()
    Log.i("INPUT_DATA_TYPE", imageDataType.toString())
    val probabilityTensorIndex = 0
    val probabilityShape: IntArray =
        interpreter.getOutputTensor(probabilityTensorIndex).shape()
    Log.i("OUTPUT_TENSOR_SHAPE", Arrays.toString(probabilityShape))
    val probabilityDataType: DataType =
        interpreter.getOutputTensor(probabilityTensorIndex).dataType()
    Log.i("OUTPUT_DATA_TYPE", probabilityDataType.toString())
    Log.i(TAG, "Initialized TFLite interpreter.")

}

@Throws(IOException::class)
private fun loadModelFile(assetManager: AssetManager, filename: String): MappedByteBuffer {
    val fileDescriptor = assetManager.openFd(filename)
    val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
    val fileChannel = inputStream.channel
    val startOffset = fileDescriptor.startOffset
    val declaredLength = fileDescriptor.declaredLength
    return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
}
depthwise', 'block
// Initialize interpreter
@Throws(IOException::class)
private suspend fun initializeInterpreter(app: Application) = withContext(Dispatchers.IO) {
    // Load the TF Lite model from asset folder and initialize TF Lite Interpreter without NNAPI enabled.
    val assetManager = app.assets
    val model = loadModelFile(assetManager, "face_recog_model_layer.tflite")
    val options = Interpreter.Options()
    options.setUseNNAPI(false)
    interpreter = Interpreter(model, options)
    // Reads type and shape of input and output tensors, respectively.
    val imageTensorIndex = 0
    val imageShape: IntArray =
        interpreter.getInputTensor(imageTensorIndex).shape() 
    Log.i("INPUT_TENSOR_WHOLE", Arrays.toString(imageShape))
    val imageDataType: DataType =
        interpreter.getInputTensor(imageTensorIndex).dataType()
    Log.i("INPUT_DATA_TYPE", imageDataType.toString())
    val probabilityTensorIndex = 0
    val probabilityShape: IntArray =
        interpreter.getOutputTensor(probabilityTensorIndex).shape()
    Log.i("OUTPUT_TENSOR_SHAPE", Arrays.toString(probabilityShape))
    val probabilityDataType: DataType =
        interpreter.getOutputTensor(probabilityTensorIndex).dataType()
    Log.i("OUTPUT_DATA_TYPE", probabilityDataType.toString())
    Log.i(TAG, "Initialized TFLite interpreter.")

}

@Throws(IOException::class)
private fun loadModelFile(assetManager: AssetManager, filename: String): MappedByteBuffer {
    val fileDescriptor = assetManager.openFd(filename)
    val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
    val fileChannel = inputStream.channel
    val startOffset = fileDescriptor.startOffset
    val declaredLength = fileDescriptor.declaredLength
    return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
}
depthwise_BN', 'block
// Initialize interpreter
@Throws(IOException::class)
private suspend fun initializeInterpreter(app: Application) = withContext(Dispatchers.IO) {
    // Load the TF Lite model from asset folder and initialize TF Lite Interpreter without NNAPI enabled.
    val assetManager = app.assets
    val model = loadModelFile(assetManager, "face_recog_model_layer.tflite")
    val options = Interpreter.Options()
    options.setUseNNAPI(false)
    interpreter = Interpreter(model, options)
    // Reads type and shape of input and output tensors, respectively.
    val imageTensorIndex = 0
    val imageShape: IntArray =
        interpreter.getInputTensor(imageTensorIndex).shape() 
    Log.i("INPUT_TENSOR_WHOLE", Arrays.toString(imageShape))
    val imageDataType: DataType =
        interpreter.getInputTensor(imageTensorIndex).dataType()
    Log.i("INPUT_DATA_TYPE", imageDataType.toString())
    val probabilityTensorIndex = 0
    val probabilityShape: IntArray =
        interpreter.getOutputTensor(probabilityTensorIndex).shape()
    Log.i("OUTPUT_TENSOR_SHAPE", Arrays.toString(probabilityShape))
    val probabilityDataType: DataType =
        interpreter.getOutputTensor(probabilityTensorIndex).dataType()
    Log.i("OUTPUT_DATA_TYPE", probabilityDataType.toString())
    Log.i(TAG, "Initialized TFLite interpreter.")

}

@Throws(IOException::class)
private fun loadModelFile(assetManager: AssetManager, filename: String): MappedByteBuffer {
    val fileDescriptor = assetManager.openFd(filename)
    val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
    val fileChannel = inputStream.channel
    val startOffset = fileDescriptor.startOffset
    val declaredLength = fileDescriptor.declaredLength
    return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
}
depthwise_relu', 'block
// Initialize interpreter
@Throws(IOException::class)
private suspend fun initializeInterpreter(app: Application) = withContext(Dispatchers.IO) {
    // Load the TF Lite model from asset folder and initialize TF Lite Interpreter without NNAPI enabled.
    val assetManager = app.assets
    val model = loadModelFile(assetManager, "face_recog_model_layer.tflite")
    val options = Interpreter.Options()
    options.setUseNNAPI(false)
    interpreter = Interpreter(model, options)
    // Reads type and shape of input and output tensors, respectively.
    val imageTensorIndex = 0
    val imageShape: IntArray =
        interpreter.getInputTensor(imageTensorIndex).shape() 
    Log.i("INPUT_TENSOR_WHOLE", Arrays.toString(imageShape))
    val imageDataType: DataType =
        interpreter.getInputTensor(imageTensorIndex).dataType()
    Log.i("INPUT_DATA_TYPE", imageDataType.toString())
    val probabilityTensorIndex = 0
    val probabilityShape: IntArray =
        interpreter.getOutputTensor(probabilityTensorIndex).shape()
    Log.i("OUTPUT_TENSOR_SHAPE", Arrays.toString(probabilityShape))
    val probabilityDataType: DataType =
        interpreter.getOutputTensor(probabilityTensorIndex).dataType()
    Log.i("OUTPUT_DATA_TYPE", probabilityDataType.toString())
    Log.i(TAG, "Initialized TFLite interpreter.")

}

@Throws(IOException::class)
private fun loadModelFile(assetManager: AssetManager, filename: String): MappedByteBuffer {
    val fileDescriptor = assetManager.openFd(filename)
    val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
    val fileChannel = inputStream.channel
    val startOffset = fileDescriptor.startOffset
    val declaredLength = fileDescriptor.declaredLength
    return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
}
project', 'block
// Initialize interpreter
@Throws(IOException::class)
private suspend fun initializeInterpreter(app: Application) = withContext(Dispatchers.IO) {
    // Load the TF Lite model from asset folder and initialize TF Lite Interpreter without NNAPI enabled.
    val assetManager = app.assets
    val model = loadModelFile(assetManager, "face_recog_model_layer.tflite")
    val options = Interpreter.Options()
    options.setUseNNAPI(false)
    interpreter = Interpreter(model, options)
    // Reads type and shape of input and output tensors, respectively.
    val imageTensorIndex = 0
    val imageShape: IntArray =
        interpreter.getInputTensor(imageTensorIndex).shape() 
    Log.i("INPUT_TENSOR_WHOLE", Arrays.toString(imageShape))
    val imageDataType: DataType =
        interpreter.getInputTensor(imageTensorIndex).dataType()
    Log.i("INPUT_DATA_TYPE", imageDataType.toString())
    val probabilityTensorIndex = 0
    val probabilityShape: IntArray =
        interpreter.getOutputTensor(probabilityTensorIndex).shape()
    Log.i("OUTPUT_TENSOR_SHAPE", Arrays.toString(probabilityShape))
    val probabilityDataType: DataType =
        interpreter.getOutputTensor(probabilityTensorIndex).dataType()
    Log.i("OUTPUT_DATA_TYPE", probabilityDataType.toString())
    Log.i(TAG, "Initialized TFLite interpreter.")

}

@Throws(IOException::class)
private fun loadModelFile(assetManager: AssetManager, filename: String): MappedByteBuffer {
    val fileDescriptor = assetManager.openFd(filename)
    val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
    val fileChannel = inputStream.channel
    val startOffset = fileDescriptor.startOffset
    val declaredLength = fileDescriptor.declaredLength
    return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
}
project_BN', 'block
// Initialize interpreter
@Throws(IOException::class)
private suspend fun initializeInterpreter(app: Application) = withContext(Dispatchers.IO) {
    // Load the TF Lite model from asset folder and initialize TF Lite Interpreter without NNAPI enabled.
    val assetManager = app.assets
    val model = loadModelFile(assetManager, "face_recog_model_layer.tflite")
    val options = Interpreter.Options()
    options.setUseNNAPI(false)
    interpreter = Interpreter(model, options)
    // Reads type and shape of input and output tensors, respectively.
    val imageTensorIndex = 0
    val imageShape: IntArray =
        interpreter.getInputTensor(imageTensorIndex).shape() 
    Log.i("INPUT_TENSOR_WHOLE", Arrays.toString(imageShape))
    val imageDataType: DataType =
        interpreter.getInputTensor(imageTensorIndex).dataType()
    Log.i("INPUT_DATA_TYPE", imageDataType.toString())
    val probabilityTensorIndex = 0
    val probabilityShape: IntArray =
        interpreter.getOutputTensor(probabilityTensorIndex).shape()
    Log.i("OUTPUT_TENSOR_SHAPE", Arrays.toString(probabilityShape))
    val probabilityDataType: DataType =
        interpreter.getOutputTensor(probabilityTensorIndex).dataType()
    Log.i("OUTPUT_DATA_TYPE", probabilityDataType.toString())
    Log.i(TAG, "Initialized TFLite interpreter.")

}

@Throws(IOException::class)
private fun loadModelFile(assetManager: AssetManager, filename: String): MappedByteBuffer {
    val fileDescriptor = assetManager.openFd(filename)
    val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
    val fileChannel = inputStream.channel
    val startOffset = fileDescriptor.startOffset
    val declaredLength = fileDescriptor.declaredLength
    return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
}
add', 'block_6_expand', 'block_6_expand_BN', 'block_6_expand_relu', 'block_6_pad', 'block_6_depthwise', 'block_6_depthwise_BN', 'block_6_depthwise_relu', 'block_6_project', 'block_6_project_BN', 'block_7_expand', 'block_7_expand_BN', 'block_7_expand_relu', 'block_7_depthwise', 'block_7_depthwise_BN', 'block_7_depthwise_relu', 'block_7_project', 'block_7_project_BN', 'block_7_add', 'block_8_expand', 'block_8_expand_BN', 'block_8_expand_relu', 'block_8_depthwise', 'block_8_depthwise_BN', 'block_8_depthwise_relu', 'block_8_project', 'block_8_project_BN', 'block_8_add', 'block_9_expand', 'block_9_expand_BN', 'block_9_expand_relu', 'block_9_depthwise', 'block_9_depthwise_BN', 'block_9_depthwise_relu', 'block_9_project', 'block_9_project_BN', 'block_9_add', 'block_10_expand', 'block_10_expand_BN', 'block_10_expand_relu', 'block_10_depthwise', 'block_10_depthwise_BN', 'block_10_depthwise_relu', 'block_10_project', 'block_10_project_BN', 'block_11_expand', 'block_11_expand_BN', 'block_11_expand_relu', 'block_11_depthwise', 'block_11_depthwise_BN', 'block_11_depthwise_relu', 'block_11_project', 'block_11_project_BN', 'block_11_add', 'block_12_expand', 'block_12_expand_BN', 'block_12_expand_relu', 'block_12_depthwise', 'block_12_depthwise_BN', 'block_12_depthwise_relu', 'block_12_project', 'block_12_project_BN', 'block_12_add', 'block_13_expand', 'block_13_expand_BN', 'block_13_expand_relu', 'block_13_pad', 'block_13_depthwise', 'block_13_depthwise_BN', 'block_13_depthwise_relu', 'block_13_project', 'block_13_project_BN', 'block_14_expand', 'block_14_expand_BN', 'block_14_expand_relu', 'block_14_depthwise', 'block_14_depthwise_BN', 'block_14_depthwise_relu', 'block_14_project', 'block_14_project_BN', 'block_14_add', 'block_15_expand', 'block_15_expand_BN', 'block_15_expand_relu', 'block_15_depthwise', 'block_15_depthwise_BN', 'block_15_depthwise_relu', 'block_15_project', 'block_15_project_BN', 'block_15_add', 'block_16_expand', 'block_16_expand_BN', 'block_16_expand_relu', 'block_16_depthwise', 'block_16_depthwise_BN', 'block_16_depthwise_relu', 'block_16_project', 'block_16_project_BN', 'Conv_1', 'Conv_1_bn', 'out_relu', 'global_average_pooling2d', 'predictions', 'dense', 'dense_1']

И затем вы можете взять любой слой из своей модели и сохранить его в .tflite:

# PART OF MODEL
tflite_model = tf.keras.models.load_model('face_recog.weights.best.hdf5')
converter = tf.lite.TFLiteConverter.from_keras_model(tflite_model.get_layer('model'))
tflite_save = converter.convert()
open("face_recog.tflite", "wb").write(tflite_save)

Таким образом, используя приведенный выше код, файл .tflite будет иметь входной тензор = "input_1" и выход = "dense_1"

Затем внутри Android вы должны использовать входные данные для конкретной модели слоя, и вы получите выходные данные определенной формы, как при печати выходных данных в python:

interpreter = tf.lite.Interpreter('face_recog.tflite')
print(interpreter.get_output_details())
interpreter.get_tensor_details()

Android-часть:

// Initialize interpreter
@Throws(IOException::class)
private suspend fun initializeInterpreter(app: Application) = withContext(Dispatchers.IO) {
    // Load the TF Lite model from asset folder and initialize TF Lite Interpreter without NNAPI enabled.
    val assetManager = app.assets
    val model = loadModelFile(assetManager, "face_recog_model_layer.tflite")
    val options = Interpreter.Options()
    options.setUseNNAPI(false)
    interpreter = Interpreter(model, options)
    // Reads type and shape of input and output tensors, respectively.
    val imageTensorIndex = 0
    val imageShape: IntArray =
        interpreter.getInputTensor(imageTensorIndex).shape() 
    Log.i("INPUT_TENSOR_WHOLE", Arrays.toString(imageShape))
    val imageDataType: DataType =
        interpreter.getInputTensor(imageTensorIndex).dataType()
    Log.i("INPUT_DATA_TYPE", imageDataType.toString())
    val probabilityTensorIndex = 0
    val probabilityShape: IntArray =
        interpreter.getOutputTensor(probabilityTensorIndex).shape()
    Log.i("OUTPUT_TENSOR_SHAPE", Arrays.toString(probabilityShape))
    val probabilityDataType: DataType =
        interpreter.getOutputTensor(probabilityTensorIndex).dataType()
    Log.i("OUTPUT_DATA_TYPE", probabilityDataType.toString())
    Log.i(TAG, "Initialized TFLite interpreter.")

}

@Throws(IOException::class)
private fun loadModelFile(assetManager: AssetManager, filename: String): MappedByteBuffer {
    val fileDescriptor = assetManager.openFd(filename)
    val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
    val fileChannel = inputStream.channel
    val startOffset = fileDescriptor.startOffset
    val declaredLength = fileDescriptor.declaredLength
    return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
}

Я надеюсь, что это поможет кому-то. И, конечно, если вам нужно что-то еще, отметьте меня :)

person Farmaker    schedule 31.05.2020
comment
Привет, я не думаю, что это решение может подойти для моей проблемы, потому что мне нужно динамически выбирать, из какого слоя извлечь вывод. - person Simo; 02.06.2020
comment
Привет, Симо. Взгляните на эту страницу. Возможно, вы найдете ответ tensorflow.org/lite/performance/delegates - person Farmaker; 03.06.2020
comment
Спасибо, но на данный момент я пытаюсь понять, как использовать API С++ для Tflite, но я действительно не понимаю, я установил tensorflow с помощью команды pip и bazel, следуя инструкции, но при запуске команды bazel выдает ошибки, не могли бы вы помочь мне? - person Simo; 03.06.2020
comment
Извини Симо, я не играл с Базелем. Я надеюсь, что вы скоро преуспеете в этом! - person Farmaker; 04.06.2020