【发布时间】:2018-11-17 13:22:20
【问题描述】:
TLDR:如何在 Android 上使用冻结的张量流图中的变量?
1.我想做什么
我有一个 Tensorflow 模型,它在多个变量中保持内部状态,创建于:state_var = tf.Variable(tf.zeros(shape, dtype=tf.float32), name='state', trainable=False)。
此状态在推理期间被修改:
tf.assign(state_var, new_value)
我现在想在 Android 上部署模型。我能够让 Tensorflow 示例应用程序运行。在那里,加载了一个冻结的模型,效果很好。
2.从冻结图恢复变量不起作用
但是,当您使用freeze_graph script 冻结图形时,所有变量都将转换为常量。这对于网络的权重来说很好,但对于内部状态则不然。推理失败并显示以下消息。我将此解释为“assign 不适用于常量张量”
java.lang.RuntimeException: Failed to load model from 'file:///android_asset/model.pb'
at org.tensorflow.contrib.android.TensorFlowInferenceInterface.<init>(TensorFlowInferenceInterface.java:113)
...
Caused by: java.io.IOException: Not a valid TensorFlow Graph serialization: Input 0 of node layer_1/Assign was passed float from layer_1/state:0 incompatible with expected float_ref.
幸运的是,您可以将被转换为常量的变量列入黑名单。但是,这也不起作用,因为冻结的图形现在包含未初始化的变量。
java.lang.IllegalStateException: Attempting to use uninitialized value layer_7/state
3.恢复 SavedModel 在 Android 上不起作用
我尝试过的最后一个版本是使用SavedModel 格式,它应该包含冻结图和变量。不幸的是,调用 restore 方法在 Android 上不起作用。
SavedModelBundle bundle = SavedModelBundle.load(modelFilename, modelTag);
// produces error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: org.tensorflow.demo, PID: 27451
java.lang.UnsupportedOperationException: Loading a SavedModel is not supported in Android. File a bug at https://github.com/tensorflow/tensorflow/issues if this feature is important to you at org.tensorflow.SavedModelBundle.load(Native Method)
4.我怎样才能做到这一点?
我不知道我还能尝试什么。这是我的想象,但我不知道如何使它工作:
- 找出在 Android 上初始化变量的方法
- 找出另一种冻结模型的方法,以便初始化程序操作可能也是冻结图的一部分,并且可以从 Android 运行
- 了解 RNN/LSTM 是否/如何在内部实现,因为它们也应该具有在推理期间使用变量的相同要求(我假设 LSTM 能够部署在 Android 上)。
- ???
【问题讨论】:
-
你想对变量做什么?如果它只是在推理过程中使用的局部变量,那么您可以使用控制依赖项 (
with tf.control_dependencies([var.assign(initial_value)]):) 对其进行初始化。然后你在控制依赖块中放置的任何东西都将在变量初始化后运行。但这不适用于保持模型的状态。如果您想这样做,您需要在单独的运行调用中初始化变量(例如,从检查点恢复它或提供初始值)。另一种选择是提供值而不是使用变量。 -
感谢您的评论。我走了你建议的最后一条路线(“提供值而不是使用变量”),因为这是我发现在 Android 上工作的最佳解决方案。我已经用更多细节自己回答了这个问题
标签: android python tensorflow