• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

如何在Android应用程序中使用TensorFlow Mobile

借助当今最流行的机器学习框架之一TensorFlow,您可以轻松创建和训练深度模型(通常也称为深度前馈神经网络),以解决各种复杂问题,例如图像分类、目标检测和自然语言理解。TensorFlow Mobile是一个旨在帮助您在移动应用程序中利用这些模型的库。

在本教程中,我将向您展示如何在 android Studio 项目中使用 TensorFlow Mobile。

先决条件

为了能够遵循本教程,您需要:

  • Android Studio  3.0 或更高版本

  • TensorFlow 1.5.0 或更高版本

  • 运行api级别 21 或更高级别的 Android 设备

  • 以及对 TensorFlow 框架的基本了解

1.创建模型

在我们开始使用 TensorFlow Mobile 之前,我们需要一个经过训练的 TensorFlow 模型。现在让我们创建一个。

我们的模型将非常基础。它的行为就像一个异或门,接受两个输入,两个输入都可以是零或一,并产生一个输出,如果两个输入相同,则输出为零,否则为一个。此外,因为它将是一个深度模型,它将有两个隐藏层,一个有四个神经元,另一个有三个神经元。您可以自由更改隐藏层的数量和它们包含的神经元数量。

为了使本教程简短,我们将使用TFLearn,而不是直接使用低级 TensorFlow API,这是一个流行的 TensorFlow 包装框架,提供更直观和简洁的 API。如果您还没有它,请使用以下命令将其安装到您的 TensorFlow 虚拟环境中:

pip install tflearn

要开始创建模型,请创建一个名为create_model.py的 python 脚本,最好在一个空目录中,然后使用您喜欢的文本编辑器打开它。

在文件中,我们需要做的第一件事是导入 TFLearn API。

import tflearn

接下来,我们必须创建训练数据。对于我们的简单模型,只有四个可能的输入和输出,类似于 XOR 门的真值表的内容。

X = [
    [0, 0],
    [0, 1],
    [1, 0],
    [1, 1]
]

Y = [
    [0],  # Desired output for inputs 0, 0
    [1],  # Desired output for inputs 0, 1
    [1],  # Desired output for inputs 1, 0
    [0]   # Desired output for inputs 1, 1
]

在为隐藏层中的所有神经元分配初始权重时,使用从均匀分布中挑选的随机值通常是一个好主意。要生成值,请使用该uniform() 方法。

weights = tflearn.initializations.uniform(minval = -1, maxval = 1)

此时,我们可以开始创建神经网络的层。要创建输入层,我们必须使用input_data() 方法,它允许我们指定网络可以接受的输入数量。一旦输入层准备就绪,我们可以 fully_connected() 多次调用该方法以向网络添加更多层。

# Input layer
net = tflearn.input_data(
        shape = [None, 2],
        name = 'my_input'
)

# Hidden layers
net = tflearn.fully_connected(net, 4,
        activation = 'sigmoid',
        weights_init = weights
)
net = tflearn.fully_connected(net, 3,
        activation = 'sigmoid',
        weights_init = weights
)

# Output layer
net = tflearn.fully_connected(net, 1,
        activation = 'sigmoid', 
        weights_init = weights,
        name = 'my_output'
)

请注意,在上面的代码中,我们为输入和输出层赋予了有意义的名称。这样做很重要,因为我们在通过 Android 应用程序使用网络时需要它们。另请注意,隐藏层和输出层正在使用sigmoid 激活函数。您可以自由尝试其他激活函数,例如 softmax、 tanh和relu。

作为我们网络的最后一层,我们必须使用该 regression() 函数创建一个回归层,它期望一些超参数作为其参数,例如网络的学习率以及它应该使用的优化器和损失函数。以下代码向您展示了如何使用随机梯度下降(简称 SGD)作为优化函数,使用均方作为损失函数:

net = tflearn.regression(net,
        learning_rate = 2,
        optimizer = 'sgd',
        loss = 'mean_square'
)

接下来,为了让TFLearn框架知道我们的网络模型实际上是一个深度神经网络模型,我们必须调用DNN() 函数。

model = tflearn.DNN(net)

模型现已准备就绪。我们现在需要做的就是使用我们之前创建的训练数据对其进行训练。因此,调用fit() 模型的方法,并与训练数据一起指定要运行的训练 epoch 数。因为训练数据非常小,我们的模型需要数千个 epoch 才能达到合理的准确度。

model.fit(X, Y, 5000)

训练完成后,我们可以调用predict() 模型的方法来检查它是否正在生成所需的输出。以下代码向您展示了如何检查所有有效输入的输出:

print("1 XOR 0 = %f" % model.predict([[1,0]]).item(0))
print("1 XOR 1 = %f" % model.predict([[1,1]]).item(0))
print("0 XOR 1 = %f" % model.predict([[0,1]]).item(0))
print("0 XOR 0 = %f" % model.predict([[0,0]]).item(0))

如果您现在运行 Python 脚本,您应该会看到如下所示的输出:

如何在Android应用程序中使用TensorFlow Mobile  第1张请注意,输出永远不会恰好是 0 或 1。相反,它们是接近于零或接近于 1 的浮点数。因此,在使用输出时,您可能希望使用 Python 的round() 函数。

除非我们在训练后明确保存模型,否则脚本一结束我们就会丢失它。幸运的是,使用 TFLearn,对该方法的简单调用可以save() 保存模型。但是,为了能够在 TensorFlow Mobile 中使用保存的模型,在保存它之前,我们必须确保我们删除了 tf.GraphKeys.TRAIN_OPS 集合中存在的所有与训练相关的操作,这些操作与它相关联。以下代码向您展示了如何执行此操作:

# Remove train ops
with net.graph.as_default():
    del tf.get_collection_ref(tf.GraphKeys.TRAIN_OPS)[:]

# Save the model
model.save('xor.tflearn')

如果再次运行该脚本,您会看到它生成了一个检查点文件、一个元数据文件、一个索引文件和一个数据文件,所有这些一起使用时可以快速重新创建我们训练好的模型。

2.冻结模型

除了保存模型外,我们还必须先将其冻结,然后才能将其与 TensorFlow Mobile 一起使用。正如您可能已经猜到的那样,冻结模型的过程涉及将其所有变量转换为常量。此外,冻结模型必须是符合 Google Protocol Buffers 序列化格式的单个二进制文件。

创建一个名为freeze_model.py的新 Python 脚本 并使用文本编辑器打开它。我们将编写所有代码以将模型冻结在此文件中。

因为 TFLearn 没有任何冻结模型的功能,所以我们现在必须直接使用 TensorFlow API。通过将以下行添加到文件中来导入它们:

import tensorflow as tf

在整个脚本中,我们将使用单个 TensorFlow 会话。要创建会话,请使用Session 类的构造函数。

with tf.Session() as session:
    # rest of the code goes here

此时,我们必须Saver 通过调用该 import_meta_graph() 函数并将模型元数据文件的名称传递给它来创建一个对象。除了返回一个Saver 对象外,该import_meta_graph() 函数还会自动将模型的图定义添加到会话的图定义中。

创建保存程序后,我们可以通过调用该方法初始化图形定义中存在的所有变量,该restore() 方法需要包含模型最新检查点文件的目录的路径。

my_saver = tf.train.import_meta_graph('xor.tflearn.meta')
my_saver.restore(session, tf.train.latest_checkpoint('.'))

此时,我们可以调用该convert_variables_to_constants() 函数来创建一个冻结图定义,其中模型的所有变量都用常量替换d。作为其输入,该函数需要当前会话、当前会话的图形定义以及包含模型输出层名称的列表。

frozen_graph = tf.graph_util.convert_variables_to_constants(
    session,
    session.graph_def,
    ['my_output/Sigmoid']
)

调用SerializeToString() 冻结图定义的方法为我们提供了模型的二进制 protobuf 表示。通过使用 Python 的基本文件 I/O 工具,我建议您将其保存为名为freeze_model.pb的文件。

with open('frozen_model.pb', 'wb') as f:
    f.write(frozen_graph.SerializeToString())

您现在可以运行脚本来生成冻结模型。

我们现在拥有开始使用 TensorFlow Mobile 所需的一切。

3. Android Studio 项目设置

TensorFlow Mobile 库在 JCenter 上可用,因此我们可以直接将其作为 implementation 依赖项添加到app 模块的build.gradle 文件中。

implementation 'org.tensorflow:tensorflow-android:1.7.0'

要将冻结模型添加到项目中,请将freeze_model.pb 文件放在项目的资产 文件夹中。

4.初始化 TensorFlow 接口

TensorFlow Mobile 提供了一个简单的界面,我们可以使用它来与我们的冻结模型进行交互。要创建接口,请使用TensorFlowInferenceInterface 类的构造函数,它需要一个AssetManager 实例和冻结模型的文件名。

thread {
    val tfInterface = TensorFlowInferenceInterface(assets,
                                        "frozen_model.pb")
	
    // More code here
}

在上面的代码中,您可以看到我们正在生成一个新线程。建议这样做,尽管并非总是必要的,以确保应用程序的 UI 保持响应。

为了确保 TensorFlow Mobile 能够正确读取我们的模型文件,现在让我们尝试打印模型图中存在的所有操作的名称。要获得对图的引用,我们可以使用graph() 接口的方法,而要获得所有的操作,可以使用图的operations() 方法。以下代码向您展示了如何:

val graph = tfInterface.graph()
graph.operations().forEach {
    println(it.name())
}

如果您现在运行该应用程序,您应该能够在 Android Studio 的Logcat 窗口中看到十多个操作名称。在所有这些名称中,如果在冻结模型时没有错误,您将能够找到输入和输出层的名称:  my_input/X 和my_output/Sigmoid。

如何在Android应用程序中使用TensorFlow Mobile  第2张

5.使用模型

要使用模型进行预测,我们必须将数据放入其输入层并从其输出层检索数据。要将数据放入输入层,请使用feed() 接口的方法,该方法需要层的名称、包含输入的数组以及数组的维度。以下代码向您展示了如何将数字发送 0 到 1 输入层:

tfInterface.feed("my_input/X",
            floatArrayOf(0f, 1f), 1, 2)

将数据加载到输入层后,我们必须使用该 run() 方法运行推理操作,该方法需要输出层的名称。一旦操作完成,输出层将包含模型的预测。要将预测加载到kotlin数组中,我们可以使用该fetch() 方法。以下代码向您展示了如何执行此操作:

tfInterface.run(arrayOf("my_output/Sigmoid"))

val output = floatArrayOf(-1f)
tfInterface.fetch("my_output/Sigmoid", output)

你如何使用预测当然取决于你。现在,我建议您简单地打印它。

println("Output is ${output[0]}")

您现在可以运行应用程序来查看模型的预测是否正确。

如何在Android应用程序中使用TensorFlow Mobile  第3张随意更改您提供给输入层的数字,以确认模型的预测始终正确。

结论

您现在知道如何创建一个简单的 TensorFlow 模型并将其与 Android 应用程序中的 TensorFlow Mobile 一起使用。不过,您不必总是将自己限制在自己的模型中。凭借您今天学到的技能,您应该可以毫无问题地使用 TensorFlow模型动物园中可用的更大模型,例如 MobileNet 和 Inception 。但请注意,此类模型会导致更大的 APK,这可能会给使用低端设备的用户带来问题。


文章目录
  • 先决条件
  • 1.创建模型
  • 2.冻结模型
  • 3. Android Studio 项目设置
  • 4.初始化 TensorFlow 接口
  • 5.使用模型
  • 结论