首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >根据TFLite官方示例无法加载TFLite模型

根据TFLite官方示例无法加载TFLite模型
EN

Stack Overflow用户
提问于 2021-07-30 15:15:26
回答 1查看 416关注 0票数 0

我正在尝试使用TFLite创建一个智能回复应用程序,我正在跟踪来自github的预建实例

当从git克隆引用的项目并编译时,它工作得完美无缺。

但是,当我将引用的项目代码(也是gradle依赖项、资产、库和其他东西)复制到我的项目时,它不能加载tflite模型并抛出一个Runtime错误:

代码语言:javascript
复制
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.legendsayantan.replai, PID: 14279
java.lang.UnsatisfiedLinkError: No implementation found for long com.legendsayantan.replai.SmartReplyClient.loadJNI(java.nio.MappedByteBuffer, java.lang.String[]) (tried Java_com_legendsayantan_replai_SmartReplyClient_loadJNI and Java_com_legendsayantan_replai_SmartReplyClient_loadJNI__Ljava_nio_MappedByteBuffer_2_3Ljava_lang_String_2)
    at com.legendsayantan.replai.SmartReplyClient.loadJNI(Native Method)
    at com.legendsayantan.replai.SmartReplyClient.loadModel(SmartReplyClient.java:64)
    at com.legendsayantan.replai.MainActivity.lambda$onStart$0(MainActivity.java:90)
    at com.legendsayantan.replai.-$$Lambda$MainActivity$Xdq7R5vPx_buuatNOneWHck6N2o.run(Unknown Source:0)
    at android.os.Handler.handleCallback(Handler.java:888)
    at android.os.Handler.dispatchMessage(Handler.java:100)
    at android.os.Looper.loop(Looper.java:213)
    at android.app.ActivityThread.main(ActivityThread.java:8178)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)

这是我的MainActivity.java-

代码语言:javascript
复制
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;

import android.view.Menu;


import com.google.android.material.navigation.NavigationView;

import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import org.tensorflow.lite.Interpreter;

public class MainActivity extends AppCompatActivity {

private AppBarConfiguration mAppBarConfiguration;
public static SharedPreferences sharedPreferences;
public static Context context;

public static final String TAG = "SmartReply";
public static SmartReplyClient client;
public static Handler handler;
public static Interpreter model;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    context=getApplicationContext();
    setContentView(R.layout.activity_main);

    client = new SmartReplyClient(getApplicationContext());
    handler = new Handler();

    sharedPreferences = getPreferences(Context.MODE_PRIVATE);
    Toolbar toolbar = findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    DrawerLayout drawer = findViewById(R.id.drawer_layout);
    NavigationView navigationView = findViewById(R.id.nav_view);
    // Passing each menu ID as a set of Ids because each
    // menu should be considered as top level destinations.
    mAppBarConfiguration = new AppBarConfiguration.Builder(
            R.id.nav_home, R.id.nav_gallery, R.id.nav_slideshow)
            .setDrawerLayout(drawer)
            .build();
    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    NavigationUI.setupActionBarWithNavController(this, navController, mAppBarConfiguration);
    NavigationUI.setupWithNavController(navigationView, navController);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onSupportNavigateUp() {
    NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
    return NavigationUI.navigateUp(navController, mAppBarConfiguration)
            || super.onSupportNavigateUp();
}

@Override
protected void onStart() {
    super.onStart();
    Log.v(TAG, "onStart");
    handler.post(
            () -> {
               client.loadModel();
            });
}

@Override
protected void onStop() {
    super.onStop();
    Log.v(TAG, "onStop");
    handler.post(
            () -> {
                client.unloadModel();
            });
}

private static void send(final String message) {
    handler.post(
            () -> {
                StringBuilder textToShow = new StringBuilder();
                textToShow.append("Input: ").append(message).append("\n\n");

                // Get suggested replies from the model.
                SmartReply[] ans = client.predict(new String[] {message});
                for (SmartReply reply : ans) {
                    textToShow.append("Reply: ").append(reply.getText()).append("\n");
                }
                textToShow.append("------").append("\n");


            });
      }
}

下面是SmartReplyClient.java (与参考github项目完全相同的文件):

代码语言:javascript
复制
import android.content.Context;
import android.content.res.AssetFileDescriptor;

import androidx.annotation.Keep;
import androidx.annotation.WorkerThread;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;


public class SmartReplyClient implements AutoCloseable {
  private static final String TAG = "SmartReplyDemo";
  private static final String MODEL_PATH = "smartreply.tflite";
  private static final String BACKOFF_PATH = "backoff_response.txt";
  private static final String JNI_LIB = "smartreply_jni";

  private final Context context;
  private long storage;
  private MappedByteBuffer model;

  private volatile boolean isLibraryLoaded;

  public SmartReplyClient(Context context) {
    this.context = context;
  }

  public boolean isLoaded() {
    return storage != 0;
  }

  @WorkerThread
  public synchronized void loadModel() {
    if (!isLibraryLoaded) {
      System.loadLibrary(JNI_LIB);
      isLibraryLoaded = true;
    }

    try {
      model = loadModelFile();
      String[] backoff = loadBackoffList();
      storage = loadJNI(model, backoff); //This line is throwing the error
      // But this same java file works nice in the reference project
    } catch (Exception e) {
      System.out.println(e.getMessage());
      return;
    }
  }

  @WorkerThread
  public synchronized SmartReply[] predict(String[] input) {
    if (storage != 0) {
      return predictJNI(storage, input);
    } else {
      return new SmartReply[] {};
    }
  }

  @WorkerThread
  public synchronized void unloadModel() {
     close();
  }

  @Override
  public synchronized void close() {
    if (storage != 0) {
      unloadJNI(storage);
      storage = 0;
    }
  }

  public MappedByteBuffer loadModelFile() throws IOException {
     try (AssetFileDescriptor fileDescriptor =
         AssetsUtil.getAssetFileDescriptorOrCached(context, MODEL_PATH);
         FileInputStream inputStream = new FileInputStream(fileDescriptor.getFileDescriptor())) {
         FileChannel fileChannel = inputStream.getChannel();
         long startOffset = fileDescriptor.getStartOffset();
         long declaredLength = fileDescriptor.getDeclaredLength();
         return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
     }
  }

   private String[] loadBackoffList() throws IOException {
    List<String> labelList = new ArrayList<String>();
    try (BufferedReader reader =
        new BufferedReader(new InputStreamReader(context.getAssets().open(BACKOFF_PATH)))) {
      String line;
      while ((line = reader.readLine()) != null) {
        if (!line.isEmpty()) {
          labelList.add(line);
        }
      }
    }
    String[] ans = new String[labelList.size()];
    labelList.toArray(ans);
    return ans;
  }

  @Keep
  private native long loadJNI(MappedByteBuffer buffer, String[] backoff);

  @Keep
  private native SmartReply[] predictJNI(long storage, String[] text);

  @Keep
  private native void unloadJNI(long storage);
}

我还在build.gradle中实现了与参考示例相同的tensorflow版本:

代码语言:javascript
复制
implementation 'org.tensorflow:tensorflow-lite:0.0.0-nightly-SNAPSHOT'

在这里抛出上面提到的错误.

为了避免错误,我还尝试使用活动TFLite中的Interpreter加载onCreate模型。

代码语言:javascript
复制
Interpreter interpreter;
        try {
            interpreter=new Interpreter(loadmodelfile());
        } catch (IOException e) {
            e.printStackTrace();
        }

方法loadmodelfile()

代码语言:javascript
复制
public MappedByteBuffer loadmodelfile() throws IOException {
        AssetFileDescriptor assetFileDescriptor = this.getAssets().openFd("smartreply.tflite");
        FileInputStream fileInputStream = new FileInputStream(assetFileDescriptor.getFileDescriptor());
        FileChannel fileChannel = fileInputStream.getChannel();
        long startoff = assetFileDescriptor.getStartOffset();
        long length = assetFileDescriptor.getDeclaredLength();
        return fileChannel.map(FileChannel.MapMode.READ_ONLY,startoff,length);
    }

还有,我发现了一个错误:

代码语言:javascript
复制
E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.legendsayantan.tflitesmartreplyremake, PID: 10879
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.legendsayantan.tflitesmartreplyremake/com.legendsayantan.tflitesmartreplyremake.MainActivity}: java.lang.IllegalStateException: Internal error: Unexpected failure when preparing tensor allocations: Encountered unresolved custom op: Normalize.
    Node number 0 (Normalize) failed to prepare.
    
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3782)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3961)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2386)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:213)
        at android.app.ActivityThread.main(ActivityThread.java:8178)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1101)
     Caused by: java.lang.IllegalStateException: Internal error: Unexpected failure when preparing tensor allocations: Encountered unresolved custom op: Normalize.
    Node number 0 (Normalize) failed to prepare.

请告诉我一些我错过的东西,或者我在这些尝试中所犯的任何错误。

我是Tensorflow的新手,但不是开发android应用程序的新手,我只是不知道我在这里还犯了什么错。

任何帮助或建议都将不胜感激!

EN

回答 1

Stack Overflow用户

发布于 2021-08-02 00:32:49

遇到未解决的自定义操作:规范化。

看起来您的模型有一个自定义op,即正常化,这意味着您需要实现自己的TFLite自定义op并将其注册到TFLite解释器。如果您没有实现自定义op的计划,请考虑使用Select选项,它可以在移动上利用TensorFlow op。

选择

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68593356

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档