web-dev-qa-db-ja.com

Tensorflow-Liteの事前トレーニング済みモデルはAndroidデモでは機能しません

Tensorflow-Lite Androidデモは、提供されている元のモデルで動作します:mobilenet_quant_v1_224.tflite。参照: https://github.com/tensorflow/tensorflow/tree/master/tensorflow/ contrib/lite

また、ここで他の事前トレーニング済みライトモデルも提供しています: https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/lite/g3doc/models.md

ただし、上記のリンクからいくつかの小さなモデル(mobilenet_v1_0.25_224.tfliteなど)をダウンロードし、デモアプリで_MODEL_PATH = "mobilenet_v1_0.25_224.tflite";_の_ImageClassifier.Java_を変更するだけで、元のモデルをこのモデルに置き換えました。 __。アプリがクラッシュする:

12-11 12:52:34.222 17713-17729 /? E/AndroidRuntime:致命的な例外:CameraBackgroundプロセス:Android.example.com.tflitecamerademo、PID:17713 Java.lang.IllegalArgumentException:入力ディメンションの取得に失敗しました。 0番目の入力は602112バイトである必要がありますが、150528バイトが見つかりました。 org.tensorflow.lite.NativeInterpreterWrapper.getInputDims(Native Method)at org.tensorflow.lite.NativeInterpreterWrapper.run(NativeInterpreterWrapper.Java:82)at org.tensorflow.lite.Interpreter.runForMultipleInputsOutputs(Interpreter.Java:112)at org .tensorflow.lite.Interpreter.run(Interpreter.Java:93)at com.example.Android.tflitecamerademo.ImageClassifier.classifyFrame(ImageClassifier.Java:108)at com.example.Android.tflitecamerademo.Camera2BasicFragment.classifyFrame(Camera2BasicFragment.Java :663)com.example.Android.tflitecamerademo.Camera2BasicFragment.access $ 900(Camera2BasicFragment.Java:69)at com.example.Android.tflitecamerademo.Camera2BasicFragment $ 5.run(Camera2BasicFragment.Java:558)atAndroid.os.Handler。 handleCallback(Handler.Java:751)at Android.os.Handler.dispatchMessage(Handler.Java:95)at Android.os.Looper.loop(Looper.Java:154)at Android.os.HandlerThread.run(HandlerThread.Java :61)

その理由は、モデルに必要な入力サイズが画像サイズの4倍であるためと思われます。そこで、_DIM_BATCH_SIZE = 1_を_DIM_BATCH_SIZE = 4_に変更しました。エラーは次のとおりです。

致命的な例外:CameraBackgroundプロセス:Android.example.com.tflitecamerademo、PID:18241 Java.lang.IllegalArgumentException:タイプFLOAT32のTensorFlowLiteテンソルをJavaタイプ[[B(これは、org.tensorflow.lite.Interpreter.runForMultipleInputsOutputs(Interpreter.Java:122)のorg.tensorflow.lite.Tensor.copyTo(Tensor.Java:36)のTensorFlowLiteタイプUINT8)と互換性があります。 Interpreter.run(Interpreter.Java:93)at com.example.Android.tflitecamerademo.ImageClassifier.classifyFrame(ImageClassifier.Java:108)at com.example.Android.tflitecamerademo.Camera2BasicFragment.classifyFrame(Camera2BasicFragment.Java:663)at com .example.Android.tflitecamerademo.Camera2BasicFragment.access $ 900(Camera2BasicFragment.Java:69)at com.example.Android.tflitecamerademo.Camera2BasicFragment $ 5.run(Camera2BasicFragment.Java:558)at Android.os.Handler.handleCallback(Handler.Java :751)AndroiのAndroid.os.Handler.dispatchMessage(Handler.Java:95)でAndroid.os.HandlerThread.run(HandlerThread.Java:61)のd.os.Looper.loop(Looper.Java:154)

私の質問は、縮小されたMobileNettfliteモデルをTF-liteで動作させる方法ですAndroid Demo。

(実際には、提供されているツールを使用してTFフリーズグラフをTF-liteモデルに変換するなど、他のことも試しました。 https://github.com/tensorflow/tensorflow/blob/master /tensorflow/contrib/lite/toco/g3doc/cmdline_examples.md ただし、変換されたtfliteモデルはAndroidデモ)では機能しません。

9
Seedling

Tensorflow-Lite Androidデモに含まれるImageClassifier.Javaは、quantizedモデルを想定しています。現時点では、1つだけです。 Mobilenetsモデルの一部は量子化された形式で提供されます:Mobilenet 1.0 224 Quant

他のfloatモデルを使用するには、Tensorflow for PoetsTF-LiteデモソースからImageClassifier.Javaを交換します。これはfloatモデル用に書かれています。 https://github.com/googlecodelabs/tensorflow-for-poets-2/blob/master/Android/tflite/app/src/main/Java/com/example/Android/tflitecamerademo/ImageClassifier.Java

差分を実行すると、実装にいくつかの重要な違いがあることがわかります。

考慮すべきもう1つのオプションは、TOCOを使用してフロートモデルを量子化に変換することです。 https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/lite/toco/g3doc/cmdline_examples.md

4
Ash Eldritch

また、苗木と同じエラーが発生していました。 MobilenetFloatモデル用の新しい画像分類ラッパーを作成しました。現在は正常に動作しています。このクラスを画像分類子のデモに直接追加し、これを使用してCamera2BasicFragmentに分類子を作成できます。

classifier = new ImageClassifierFloatMobileNet(getActivity());

以下は、MobilenetFloatモデルの画像分類クラスラッパーです。

    /**
 * This classifier works with the Float MobileNet model.
 */
public class ImageClassifierFloatMobileNet extends ImageClassifier {

  /**
   * An array to hold inference results, to be feed into Tensorflow Lite as outputs.
   * This isn't part of the super class, because we need a primitive array here.
   */
  private float[][] labelProbArray = null;

  private static final int IMAGE_MEAN = 128;
  private static final float IMAGE_STD = 128.0f;

  /**
   * Initializes an {@code ImageClassifier}.
   *
   * @param activity
   */
  public ImageClassifierFloatMobileNet(Activity activity) throws IOException {
    super(activity);
    labelProbArray = new float[1][getNumLabels()];
  }

  @Override
  protected String getModelPath() {
    // you can download this file from
    // https://storage.googleapis.com/download.tensorflow.org/models/tflite/mobilenet_v1_224_Android_quant_2017_11_08.Zip
//    return "mobilenet_quant_v1_224.tflite";
    return "retrained.tflite";
  }

  @Override
  protected String getLabelPath() {
//    return "labels_mobilenet_quant_v1_224.txt";
    return "retrained_labels.txt";
  }

  @Override
  public int getImageSizeX() {
    return 224;
  }

  @Override
  public int getImageSizeY() {
    return 224;
  }

  @Override
  protected int getNumBytesPerChannel() {
    // the Float model uses a 4 bytes
    return 4;
  }

  @Override
  protected void addPixelValue(int val) {
    imgData.putFloat((((val >> 16) & 0xFF)-IMAGE_MEAN)/IMAGE_STD);
    imgData.putFloat((((val >> 8) & 0xFF)-IMAGE_MEAN)/IMAGE_STD);
    imgData.putFloat((((val) & 0xFF)-IMAGE_MEAN)/IMAGE_STD);
  }

  @Override
  protected float getProbability(int labelIndex) {
    return labelProbArray[0][labelIndex];
  }

  @Override
  protected void setProbability(int labelIndex, Number value) {
    labelProbArray[0][labelIndex] = value.byteValue();
  }

  @Override
  protected float getNormalizedProbability(int labelIndex) {
    return labelProbArray[0][labelIndex];
  }

  @Override
  protected void runInference() {
    tflite.run(imgData, labelProbArray);
  }
}
1
vikoo