Basierend auf dem TensorFlow-Tutorial (Bilderkennung handgeschriebener Bilddaten) habe ich die Netzwerkdaten von Deep Learning geschrieben und eine Demo zur Handschrifterkennung auf Android erstellt.
Schreiben Sie zuerst die Trainingsdaten in Python auf Ihren PC, basierend auf dem Modell von "MNIST For ML Beginners" im TensorFlow-Tutorial.
"MNIST For ML Beginners" https://www.tensorflow.org/versions/master/tutorials/mnist/beginners/index.html
Basierend auf dem Tutorial hier habe ich das Skript zum Exportieren von Diagrammdaten geändert.
https://github.com/miyosuda/TensorFlowAndroidMNIST/blob/master/trainer-script/beginner.py
Um Netzwerkdaten zu exportieren, müssen Diagramminformationen und Tensordaten (gelernte Inhalte) in Variable exportiert werden. Derzeit kann TensorFlow jedoch Diagramminformationen und Variable zusammen speichern. Ich konnte es anscheinend nicht tun.
Bewerten Sie nach dem Lernen den Inhalt von Viriables und konvertieren Sie ihn einmal in ndarray.
# Store variable
_W = W.eval(sess)
_b = b.eval(sess)
Ich habe das ndarray in Konstante konvertiert und es als Ersatz für Variablen verwendet, um das Diagramm zu rekonstruieren und das Diagramm und die Trainingsdaten zusammen zu exportieren.
g_2 = tf.Graph()
with g_2.as_default():
x_2 = tf.placeholder("float", [None, 784], name="input")
Ersetzen Sie # Variablen durch Konstante W_2 = tf.constant(_W, name="constant_W") b_2 = tf.constant(_b, name="constant_b")
y_2 = tf.nn.softmax(tf.matmul(x_2, W_2) + b_2, name="output")
sess_2 = tf.Session()
init_2 = tf.initialize_all_variables()
sess_2.run(init_2)
graph_def = g_2.as_graph_def()
tf.train.write_graph(graph_def, './tmp/beginner-export',
'beginner-graph.pb', as_text=False)
Um es auf der Android-Seite aufzurufen, habe ich die Eingabe- und Ausgabeknoten als "Eingabe" bzw. "Ausgabe" bezeichnet.
Das Trainieren und Exportieren dieses Modells dauerte nur wenige Sekunden.
Die ursprünglich in TensorFlow enthaltene Android-Demo konnte nur in der Bazel-Umgebung erstellt werden. Daher habe ich eine Umgebung erstellt, in der Android-Apps nur mit Android Studio und NDK erstellt werden können.
Ich habe die Bibliotheksdatei (.a-Datei) gespeichert, die beim Erstellen des Android-Beispiels von TensorFlow mit Bazel erstellt werden kann, sodass es nur mit NDK erstellt werden kann.
https://github.com/miyosuda/TensorFlowAndroidMNIST/tree/master/jni-build/jni
Android.mk sieht so aus.
Makefile
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
TENSORFLOW_CFLAGS := -frtti \
-fstack-protector-strong \
-fpic \
-ffunction-sections \
-funwind-tables \
-no-canonical-prefixes \
'-march=armv7-a' \
'-mfpu=vfpv3-d16' \
'-mfloat-abi=softfp' \
'-std=c++11' '-mfpu=neon' -O2 \
TENSORFLOW_SRC_FILES := ./tensorflow_jni.cc \
./jni_utils.cc \
LOCAL_MODULE := tensorflow_mnist
LOCAL_ARM_MODE := arm
LOCAL_SRC_FILES := $(TENSORFLOW_SRC_FILES)
LOCAL_CFLAGS := $(TENSORFLOW_CFLAGS)
LOCAL_LDLIBS := \
-Wl,-whole-archive \
$(LOCAL_PATH)/libs/$(TARGET_ARCH_ABI)/libandroid_tensorflow_lib.a \
$(LOCAL_PATH)/libs/$(TARGET_ARCH_ABI)/libre2.a \
$(LOCAL_PATH)/libs/$(TARGET_ARCH_ABI)/libprotos_all_cc.a \
$(LOCAL_PATH)/libs/$(TARGET_ARCH_ABI)/libprotobuf.a \
$(LOCAL_PATH)/libs/$(TARGET_ARCH_ABI)/libprotobuf_lite.a \
-Wl,-no-whole-archive \
$(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.9/libs/$(TARGET_ARCH_ABI)/libgnustl_static.a \
$(NDK_ROOT)/sources/cxx-stl/gnu-libstdc++/4.9/libs/$(TARGET_ARCH_ABI)/libsupc++.a \
-llog -landroid -lm -ljnigraphics -pthread -no-canonical-prefixes '-march=armv7-a' -Wl,--fix-cortex-a8 -Wl,-S \
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include $(LOCAL_PATH)/genfiles $(LOCAL_PATH)/include/third_party/eigen3
NDK_MODULE_PATH := $(call my-dir)
include $(BUILD_SHARED_LIBRARY)
Wenn die Compileroption und die Linkeroption nicht wie oben festgelegt wurden, konnten die Trainingsdaten (Protokollpufferdaten) nicht korrekt gelesen werden, selbst wenn der Build bestanden wurde.
Bereiten Sie handgeschriebene 28x28-Pixeldaten auf der Java-Seite vor, übergeben Sie sie mit JNI an die c ++ - Seite und geben Sie sie in das Diagramm ein, das basierend auf den Diagrammdaten erstellt wurde.
https://github.com/miyosuda/TensorFlowAndroidMNIST/blob/master/jni-build/jni/tensorflow_jni.cc
Ich konnte es sicher erkennen.
Mit dem obigen Modell liegt die Erkennungsrate bei etwa 91%, daher habe ich sie durch ein Modell mit Deep Learning (Erkennungsrate 99,2%) in "Deep MNIST for Experts" von TensorFlow ersetzt.
"Deep MNIST for Experts" https://www.tensorflow.org/versions/master/tutorials/mnist/pros/index.html
Skript zum Exportieren von Trainingsdaten https://github.com/miyosuda/TensorFlowAndroidMNIST/blob/master/trainer-script/expert.py
Wenn der DropOut-Knoten enthalten ist, ist beim Ausführen auf der Android-Seite ein Fehler aufgetreten. Da der DropOut-Knoten ursprünglich nur zum Lernen erforderlich ist, habe ich ihn beim Exportieren aus dem Diagramm entfernt.
Das Lernen in meiner Umgebung (MacBook Pro) dauerte ungefähr eine Stunde.
Da die Namen des Eingabeknotens und des Ausgabeknotens nach dem Export identisch sind, kann der gesamte Code auf der Android-Seite so ausgeführt werden, wie er ist, indem einfach die Trainingsdaten ersetzt werden.
Als ich die Handschrifterkennung versuchte, konnte ich bestätigen, dass Zahlen von 0 bis 9 ziemlich genau erkannt wurden.
Klicken Sie hier, um die oben genannten Quellen anzuzeigen https://github.com/miyosuda/TensorFlowAndroidMNIST
Recommended Posts