【问题标题】:How to load Tensorflow model from internal storage?如何从内部存储加载 TensorFlow 模型?
【发布时间】:2019-07-09 20:26:37
【问题描述】:

我想知道是否可以从 Android 设备的内部存储而不是资产文件夹中存储和读取经过训练的 .tflite 模型?

以下是从资产文件夹加载模型的原始代码(有效)。

private MappedByteBuffer loadLocalModelFile() throws IOException {
  AssetFileDescriptor fileDescriptor = getAssets().openFd(MODEL_PATH);
  FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor());
  long startOffset = fileDescriptor.getStartOffset();
  long declaredLength = fileDescriptor.getDeclaredLength();

  FileChannel fileChannel = inputStream.getChannel();
  return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
}

有没有办法从内部存储器加载模型,并且仍然获得 fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength) 的 startOffset 和 declaredLength?如果没有,在从内部存储读取原始二进制文件时,有没有办法计算新模型的 startOffset 及其声明的长度?

我尝试使用 AssetManager 中的 openNonAssetFd() 函数为位于内部存储中的文件获取 AssetFileDescriptor。

private MappedByteBuffer loadOnlineModelFile() throws IOException {
    FileInputStream inputStream = openFileInput(MODEL);

    AssetManager manager = getAssets();
    AssetFileDescriptor afd = manager.openNonAssetFd(getFilesDir() + "/graph.lite");

    long startOffset = afd.getStartOffset();
    long declaredLength = afd.getDeclaredLength();

    FileChannel fileChannel = inputStream.getChannel();
    return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
  }

但是,这将导致“java.lang.IllegalArgumentException: Model ByteBuffer 应该是模型文件的 MappedByteBuffer 或使用包含模型内容字节的 ByteOrder.nativeOrder() 的直接 ByteBuffer”和“java.io. FileNotFoundException”。

【问题讨论】:

    标签: java android tensorflow


    【解决方案1】:

    嗯,我一直在到处寻找,终于弄明白了。这很简单。
    出于某种原因,我认为AssetFileDescriptorgetStartOffset 与实际的tflite model 有关,但事实并非如此。我认为getStartOffset 给出了应用程序资产中文件的start 点。对于tflite modelstartOffset 应该是0,因为这是文件开始的地方,因为它只是一个文件。 所以,代码应该是

    File file = new File('path_to_model');
    FileInputStream is = new FileInputStream(file);
    
    return is.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());
    

    【讨论】:

      【解决方案2】:

      您可以直接从内部存储中访问该文件。 这是一个演示代码,用于从位于内部存储的示例文件夹中读取名为 model.tflite 的 tflite 模型。

       @NonNull
        public MappedByteBuffer loadMappedFile(@NonNull Context context, @NonNull String filePath) throws IOException {
          SupportPreconditions.checkNotNull(context, "Context should not be null.");
          SupportPreconditions.checkNotNull(filePath, "File path cannot be null.");
          File file = new File(Environment.getExternalStorageDirectory() + "/sample/" + filePath);
      
          MappedByteBuffer var9;
          try {
            FileInputStream inputStream = new FileInputStream(file);
            try {
              FileChannel fileChannel = inputStream.getChannel();
              var9 = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
            } catch (Throwable var12) {
              try {
                inputStream.close();
              } catch (Throwable var11) {
                var12.addSuppressed(var11);
              }
              throw var12;
            }
      
            inputStream.close();
          } catch (Throwable var13) {
            throw var13;
          }
      
          return var9;
        }
      

      文件路径将是模型的名称。这里是model.tflite。 我们可以这样调用方法,

      loadMappedFile(Classifier.this, "model.tflite");
      

      【讨论】:

        猜你喜欢
        • 2021-02-07
        • 2020-02-14
        • 2021-04-09
        • 2020-06-02
        • 1970-01-01
        • 1970-01-01
        • 2022-08-02
        • 2019-06-07
        • 1970-01-01
        相关资源
        最近更新 更多