Open Luonic opened 7 years ago
Кажется, отсутствуют нужные вычислительные ядра в этой нативной библиотеке. Возможно, придётся собрать свою с параметром -DANDROID_TYPES=ANDROID_TYPES_FULL
.
java.lang.IllegalArgumentException: No OpKernel was registered to support Op 'Transpose' with these attrs. Registered devices: [CPU], Registered kernels:
device='CPU'; T in [DT_BFLOAT16]; Tperm in [DT_INT32]
device='CPU'; T in [DT_FLOAT]; Tperm in [DT_INT32]
device='CPU'; T in [DT_INT32]; Tperm in [DT_INT32]
[[Node: transpose = Transpose[T=DT_UINT8, Tperm=DT_INT32](Placeholder, transpose/perm)]]
at org.tensorflow.Session.run(Native Method)
at org.tensorflow.Session.access$100(Session.java:48)
at org.tensorflow.Session$Runner.runHelper(Session.java:295)
at org.tensorflow.Session$Runner.run(Session.java:245)
at org.tensorflow.contrib.android.TensorFlowInferenceInterface.run(TensorFlowInferenceInterface.java:144)
at org.tensorflow.contrib.android.TensorFlowInferenceInterface.run(TensorFlowInferenceInterface.java:113)
at pw.thedrhax.captcharecognition.CaptchaRecognition.recognize(CaptchaRecognition.java:52)
at pw.thedrhax.captcharecognition.CaptchaRecognitionTest.recognize(CaptchaRecognitionTest.java:48)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:59)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:262)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1932)
Отказывается загружаться с ошибкой Not a valid TensorFlow Graph serialization
.
java.lang.RuntimeException: Failed to load model from 'file:///android_asset/quantized_graph.pb'
at org.tensorflow.contrib.android.TensorFlowInferenceInterface.<init>(TensorFlowInferenceInterface.java:102)
at pw.thedrhax.captcharecognition.CaptchaRecognition.<init>(CaptchaRecognition.java:40)
at pw.thedrhax.captcharecognition.CaptchaRecognitionTest.recognize(CaptchaRecognitionTest.java:40)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:59)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:262)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1932)
Caused by: java.io.IOException: Not a valid TensorFlow Graph serialization: NodeDef expected inputs '' do not match 1 inputs specified; Op<name=Const; signature= -> output:dtype; attr=value:tensor; attr=dtype:type>; NodeDef: RNN/StackRNN/Layer0/bidirectional_rnn/bw/bw/while/bw/gru_cell/candidate/candidate/concat/axis = Const[dtype=DT_INT32, value=Tensor<type: int32 shape: [] values: 1>](RNN/StackRNN/Layer0/bidirectional_rnn/bw/bw/while/Switch:1)
at org.tensorflow.contrib.android.TensorFlowInferenceInterface.loadGraph(TensorFlowInferenceInterface.java:439)
at org.tensorflow.contrib.android.TensorFlowInferenceInterface.<init>(TensorFlowInferenceInterface.java:98)
... 29 more
Сейчас пойду компилировать TensorFlow. Если сборка удастся, то можно будет сразу и AOT опробовать.
@TheDrHax если не получится собрать библиотеку из графа, то я могу убрать транспонирование, пускай оно будет в java коде, и сделаю новый граф И еще, в этом проекте, в версии, которая сейчас в Google Play почему-то библиотеки для разных архитектур все в одном apk. Я думал, что они уже разбиты на разные файлы
собрать библиотеку из графа
Возникла ещё одна проблема. Выполнил всё по инструкциям и примерам, но tfcompiler, похоже, очень не любит двунаправленные сети.
INVALID ARGUMENTS: Missing Exit successor to RNN/StackRNN/Layer0/bidirectional_rnn/fw/fw/while/Switch
В одном из тикетов находится патч, который обходит именно это исключение, но дальше встречается только ужасный каскад ошибок О_о
Я немного разобрался в том, как вообще происходит сборка, так что попробую собрать новую версию нативной библиотеки. Возможно, что транспонирование убирать не придётся.
И еще, в этом проекте, в версии, которая сейчас в Google Play почему-то библиотеки для разных архитектур все в одном apk. Я думал, что они уже разбиты на разные файлы
Выбор "вводить капчу или поставить тяжелый модуль" всё-таки лучше, чем "ставить приложение или не ставить приложение" :)
С чего все начиналось: прошлый тред Репозиторий с кодом для распознавания: tf-cnn-lstm-ocr-captcha
Я смог уменьшить размер графа с 7.4мб до 283кб! Теперь на вход подается такая картинка, которая приходит от WiFi AP. То есть, не транспонированная, в uint8, в RGB, все преобразования включены в граф frozen_graph.pb.zip При этом, текущее среднее расстояние левенштейна на тестовом датасете составляет всего 0.0074 (99.26%)
Я попробовал квантизировать веса и операции в графе, но его размер только увеличился (356кб), видимо, описание самого графа уже занимает больше места, чем веса, а квантизация привносит множество дополнительных операций. Но в теории, этот граф должен работать несколько быстрее на телефонах, но с небольшой потерей точности (обычно 1.1%) quantized_graph.pb.zip
Работаю над тем, чтобы скомпилировать граф в отдельную библиотеку UPD: граф в библиотеку лучше собирать самостоятельно @TheDrHax Потому что надо собирать под разные архитектуры и писать свой код вызова Тут есть инструкция, надо собрать TF из сорцов и обязательно с поддержкой XLA (это указывается при вызове ./configure): инструкция
Думаю, можно смело выкатывать этот граф в приложение, убирая старый код с преобразованиями изображений