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デモ)では機能しません。
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
また、苗木と同じエラーが発生していました。 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);
}
}