原文:Mastering TensorFlow 1.x
协议:CC BY-NC-SA 4.0
译者:飞龙
本文来自【ApacheCN 深度学习 译文集】,采用译后编辑(MTPE)流程来尽可能提升效率。
不要担心自己的形象,只关心如何实现目标。——《原则》,生活原则 2.3.c
{% raw %}
十六、移动和嵌入式平台上的 TensorFlow 模型
TensorFlow 模型还可用于在移动和嵌入式平台上运行的应用。 TensorFlow Lite 和 TensorFlow Mobile 是资源受限移动设备的两种 TensorFlow。与 TensorFlow Mobile 相比,TensorFlow Lite 支持功能的子集。由于较小的二进制大小和较少的依赖项,TensorFlow Lite 可以获得更好的表现。
要将 TensorFlow 集成到您的应用中,首先,使用我们在整本书中提到的技术训练模型,然后保存模型。现在可以使用保存的模型在移动应用中进行推理和预测。
要了解如何在移动设备上使用 TensorFlow 模型,在本章中我们将介绍以下主题:
- 移动平台上的 TensorFlow
- Android 应用中的 TFMobile
- Android 上的 TFMobile 演示
- iOS 上的 TFMobile 演示
- TensorFlow Lite
- Android 上的 TFLite 演示
- iOS 上的 TFLite 演示
移动平台上的 TensorFlow
TensorFlow 可以集成到移动应用中,用于涉及以下一项或多项机器学习任务的许多用例:
- 语音识别
- 图像识别
- 手势识别
- 光学字符识别
- 图像或文本分类
- 图像,文本或语音合成
- 对象识别
要在移动应用上运行 TensorFlow,我们需要两个主要成分:
- 经过训练和保存的模型,可用于预测
- TensorFlow 二进制文件,可以接收输入,应用模型,生成预测,并将预测作为输出发送
高级架构如下图所示:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0GICozrx-1681566673388)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/mastering-tf-1x-zh/img/e64ec954-a6af-4d25-a484-8fb12d371828.png)]
移动应用代码将输入发送到 TensorFlow 二进制文件,该二进制文件使用训练的模型来计算预测并将预测发回。
Android 应用中的 TFMobile
TensorFlow 生态系统使其能够通过接口类TensorFlowInferenceInterface
,和 jar 文件libandroid_tensorflow_inference_java.jar
中的 TensorFlow Java API 在 Android 应用中使用。您可以使用 JCenter 中的 jar 文件,从ci.tensorflow.org
下载预编译的 jar,也可以自己构建。
推理接口已作为 JCenter 包提供,可以通过将以下代码添加到build.gradle
文件中包含在 Android 项目中:
allprojects {
repositories {
jcenter()
}
}
dependencies {
compile 'org.tensorflow:tensorflow-android:+'
}
您可以按照此链接中的说明使用 Bazel 或 Cmake 自行构建它们,而不是使用 JCenter 中的预构建二进制文件。
在 Android 项目中配置 TF 库后,您可以通过以下四个步骤调用 TF 模型:
- 加载模型:
TensorFlowInferenceInterface inferenceInterface =
new TensorFlowInferenceInterface(assetManager, modelFilename);
- 将输入数据发送到 TensorFlow 二进制文件:
inferenceInterface.feed(inputName,
floatValues, 1, inputSize, inputSize, 3);
- 运行预测或推理:
inferenceInterface.run(outputNames, logStats);
- 接收 TensorFlow 二进制文件的输出:
inferenceInterface.fetch(outputName, outputs);
Android 上的 TFMobile 演示
在本节中,我们将学习如何重新创建 TensorFlow 团队在其官方仓库中提供的 Android 演示应用。 Android 演示将在您的 Android 设备上安装以下四个应用:
-
TF Classify
:这是一个对象识别应用,用于识别设备摄像头输入中的图像,并在其中一个预定义的类中对其进行分类。它不会学习新类型的图片,但会尝试将它们分类为已经学过的类别之一。该应用使用 Google 预训练的初始模型构建。 -
TF Detect
:这是一个物体检测应用,可检测设备相机输入中的多个物体。在连续图像进纸模式下移动相机时,它会继续识别对象。 -
TF Stylize
:这是一个样式转移应用,可将选定的预定义样式之一传输到设备相机的输入。 -
TF Speech
:这是一个语音识别应用,用于识别您的语音,如果它与应用中的某个预定义命令匹配,则它会在设备屏幕上突出显示该特定命令。
示例演示仅适用于 API 级别大于 21 的 Android 设备,并且该设备必须具有支持FOCUS_MODE_CONTINUOUS_PICTURE
的现代相机。如果您的设备相机不支持此功能,则必须添加作者提交给 TensorFlow 的路径。。
在您的设备上构建和部署演示应用的最简单方法是使用 Android Studio。要以这种方式构建它,请按照下列步骤操作:
-
安装 Android Studio。我们通过此链接的说明在 Ubuntu 16.04 上安装了 Android Studio。
-
查看 TensorFlow 仓库,并应用上一篇技巧中提到的补丁。我们假设您检查了主目录中
tensorflow
文件夹中的代码。 -
使用 Android Studio,在路径
~/tensorflow/tensorflow/examples/Android
中打开 Android 项目。您的屏幕看起来与此类似:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9Q9ahycU-1681566673389)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/mastering-tf-1x-zh/img/54f2b586-33a7-4c23-af93-ef41729846c5.png)]
- 从左侧栏中展开 Gradle Scripts 选项,然后打开
build.gradle
文件。 - 在
build.gradle
文件中,找到def nativeBuildSystem
定义并将其设置为'none'
。在我们检出的代码版本中,此定义位于第 43 行:
def nativeBuildSystem = 'none'
- 构建演示并在真实或模拟设备上运行它。我们在这些设备上测试了应用:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o619neLS-1681566673390)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/mastering-tf-1x-zh/img/0bdab06b-2e96-4b33-b86d-bb3c883e919c.png)]
- 您还可以构建 apk 并在虚拟或实际连接的设备上安装 apk 文件。一旦应用安装在设备上,您将看到我们之前讨论的四个应用:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NhJIlis7-1681566673391)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/mastering-tf-1x-zh/img/80c9846f-82a8-408a-9b7d-2e109654839e.png)]
Android 模拟器中的 TF 示例应用
您还可以按照此链接中的说明使用 Bazel 或 Cmake 从源构建整个演示应用。
iOS 应用中的 TFMobile
TensorFlow 通过以下步骤支持 iOS 应用:
- 通过在项目的根目录中添加名为
Profile
的文件,在您的应用中包含 TFMobile。将以下内容添加到Profile
:
target 'Name-Of-Your-Project'
pod 'TensorFlow-experimental'
- 运行
pod install
命令下载并安装 TensorFlow 实验舱。 - 运行
myproject.xcworkspace
命令打开工作区,以便将预测代码添加到应用逻辑中。
要为 iOS 项目创建自己的 TensorFlow 二进制文件,请按照此链接中的说明。
在 iOS 项目中配置 TF 库后,可以通过以下四个步骤调用 TF 模型:
- 加载模型:
PortableReadFileToProto(file_path, &tensorflow_graph);
- 创建会话:
tensorflow::Status s = session->Create(tensorflow_graph);
- 运行预测或推理并获得输出:
std::string input_layer = "input";
std::string output_layer = "output";
std::vectortensorflow::Tensor> outputs;
tensorflow::Status run_status = session->Run(
{{input_layer, image_tensor}},
{output_layer}, {}, &outputs);
- 获取输出数据:
tensorflow::Tensor* output = &outputs[0];
iOS 上的 TFMobile 演示
要在 iOS 上构建演示,您需要 Xcode 7.3 或更高版本。请按照以下步骤构建 iOS 演示应用:
- 查看主目录中
tensorflow
文件夹中的 TensorFlow 代码。 - 打开终端窗口并从主文件夹执行以下命令以下载 InceptionV1 模型,提取标签和图文件,并将这些文件移动到示例应用代码中的数据文件夹中:
$ mkdir -p ~/Downloads
$ curl -o ~/Downloads/inception5h.zip
https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip
&& unzip ~/Downloads/inception5h.zip -d ~/Downloads/inception5h
$ cp ~/Downloads/inception5h/*
~/tensorflow/tensorflow/examples/ios/benchmark/data/
$ cp ~/Downloads/inception5h/*
~/tensorflow/tensorflow/examples/ios/camera/data/
$ cp ~/Downloads/inception5h/*
~/tensorflow/tensorflow/examples/ios/simple/data/
- 导航到其中一个示例文件夹并下载实验窗格:
$ cd ~/tensorflow/tensorflow/examples/ios/camera
$ pod install
- 打开 Xcode 工作区:
$ open tf_simple_example.xcworkspace
- 在设备模拟器中运行示例应用。示例应用将显示“运行模型”按钮。相机应用需要连接 Apple 设备,而其他两个也可以在模拟器中运行。
TensorFlow Lite
在编写本书时,TFLite 是该版块中的新手,并且仍处于开发人员视图中。 TFLite 是 TensorFlow Mobile 和 TensorFlow 的一个非常小的子集,因此使用 TFLite 编译的二进制文件非常小,并提供卓越的表现。除了减小二进制文件的大小,TensorFlow 还采用了各种其他技术,例如:
- 内核针对各种设备和移动架构进行了优化
- 计算中使用的值是量化的
- 激活函数是预融合的
- 它利用设备上可用的专用机器学习软件或硬件,例如 Android NN API
在 TFLite 中使用模型的工作流程如下:
-
获取模型:您可以训练自己的模型或选择可从不同来源获得的预训练模型,并按原样使用预训练或使用您自己的数据再训练,或在修改某些部分后再训练该模型。只要您在文件中使用扩展名为
.pb
或.pbtxt
的训练模型,就可以继续执行下一步。我们在前面的章节中学习了如何保存模型。 - 检查模型:模型文件只包含图的结构,因此需要保存检查点文件。检查点文件包含模型的序列化变量,例如权重和偏差。我们在前面的章节中学习了如何保存检查点。
-
冻结模型:合并检查点和模型文件,也称为冻结图。 TensorFlow 为此步骤提供
freeze_graph
工具,可以按如下方式执行:
$ freeze_graph
--input_graph=mymodel.pb
--input_checkpoint=mycheckpoint.ckpt
--input_binary=true
--output_graph=frozen_model.pb
--output_node_name=mymodel_nodes
-
转换模型:需要使用 TensorFlow 提供的
toco
工具将步骤 3 中的冻结模型转换为 TFLite 格式:
$ toco
--input_file=frozen_model.pb
--input_format=TENSORFLOW_GRAPHDEF
--output_format=TFLITE
--input_type=FLOAT
--input_arrays=input_nodes
--output_arrays=mymodel_nodes
--input_shapes=n,h,w,c
- 现在,在步骤 4 中保存的
.tflite
模型可以在使用 TFLite 二进制文件进行推理的 Android 或 iOS 应用中使用。在您的应用中包含 TFLite 二进制文件的过程不断发展,因此我们建议读者按照此链接中的信息在您的 Android 或 iOS 应用中包含 TFLite 二进制文件。
通常,您可以使用graph_transforms:summarize_graph
工具修剪在步骤 1 中获得的模型。 修剪后的模型将仅具有在推理或预测时从输入到输出的路径。仅删除训练或调试所需的任何其他节点和路径(例如保存检查点),从而使最终模型的大小非常小。
官方 TensorFlow 仓库附带 TFLite 演示,该演示使用预训练的mobilenet
对来自 1001 类别中的设备相机的输入进行分类。演示应用显示前三个类别的概率。
Android 上的 TFLite 演示
要在 Android 上构建 TFLite 演示,请按照下列步骤操作:
-
安装 Android Studio。我们通过此链接的说明在 Ubuntu 16.04 上安装了 Android Studio。
-
查看 TensorFlow 仓库,并应用上一篇技巧中提到的补丁。我们假设您检查了主目录中
tensorflow
文件夹中的代码。 -
使用 Android Studio,从路径
~/tensorflow/tensorflow/contrib/lite/java/demo
打开 Android 项目。如果它抱怨缺少 SDK 或 Gradle 组件,请安装这些组件并同步 Gradle。 -
构建项目并使用
API > 21
在虚拟设备上运行它。
我们收到了以下警告,但构建成功了。 如果构建失败,您可能希望解决警告:
Warning:The Jack toolchain is deprecated and will not run. To enable support for Java 8 language features built into the plugin, remove 'jackOptions { ... }' from your build.gradle file, and add
android.compileOptions.sourceCompatibility 1.8
android.compileOptions.targetCompatibility 1.8
Future versions of the plugin will not support usage of 'jackOptions' in build.gradle.
To learn more, go to https://d.android.com/r/tools/java-8-support-message.html
Warning:The specified Android SDK Build Tools version (26.0.1) is ignored, as it is below the minimum supported version (26.0.2) for Android Gradle Plugin 3.0.1.
Android SDK Build Tools 26.0.2 will be used.
To suppress this warning, remove "buildToolsVersion '26.0.1'" from your build.gradle file, as each version of the Android Gradle Plugin now has a default version of the build tools.
您还可以使用 Bazel 从源代码构建整个演示应用,其中包含此链接中的说明。
iOS 上的 TFLite 演示
要在 iOS 上构建演示,您需要 Xcode 7.3 或更高版本。请按照以下步骤构建 iOS 演示应用:
- 查看主目录中
tensorflow
文件夹中的 TensorFlow 代码。 - 根据此链接中的说明构建适用于 iOS 的 TFLite 二进制文件。
- 导航到示例文件夹并下载 pod:
$ cd ~/tensorflow/tensorflow/contrib/lite/examples/ios/camera
$ pod install
- 打开 Xcode 工作区:
$ open tflite_camera_example.xcworkspace
- 在设备模拟器中运行示例应用。
总结
在本章中,我们学习了在移动应用和设备上使用 TensorFlow 模型。 TensorFlow 提供了两种在移动设备上运行的方式:TFMobile 和 TFLite。我们学习了如何为 iOs 和 Android 构建 TFMobile 和 TFLite 应用。我们在本章中使用了 TensorFlow 演示应用作为示例。鼓励读者探索这些演示应用的源代码,并使用 TFMobile 和 TFLite 通过使用 TensorFlow 构建的机器学习模型为自己的移动应用提供支持。
在下一章中,我们将学习如何在 R 统计软件中使用 TensorFlow 和 RStudio 发布的 R 包。
{% endraw %}
十七、R 中的 TensorFlow 和 Keras
R 是一个开源平台,包括用于统计计算的环境和语言。它还有一个桌面和基于 Web 的 IDE,称为 R Studio。有关 R 的更多信息,请访问此链接。 R 通过提供以下 R 包提供对 TensorFlow 和 Keras 的支持:
-
tensorflow
包提供对 TF 核心 API 的支持 -
tfestimators
包提供对 TF 估计器 API 的支持 -
keras
包提供对 Keras API 的支持 -
tfruns
包用于 TensorBoard 风格的模型和训练类可视化
在本章中,我们将学习如何在 R 中使用 TensorFlow,并将涵盖以下主题:
- 在 R 中安装 TensorFlow 和 Keras 包
- R 中的 TF 核心 API
- R 中的 TF 估计器 API
- R 中的 Keras API
- R 中的 TensorBoard
- R 中的
tfruns
包
在 R 中安装 TensorFlow 和 Keras 包
要在 R 中安装支持 TensorFlow 和 Keras 的三个 R 包,请在 R 中执行以下命令。
- 首先,安装
devtools
:
install.packages("devtools")
- 安装
tensorflow
和tfestimators
包:
devtools::install_github("rstudio/tensorflow")
devtools::install_github("rstudio/tfestimators")
- 加载
tensorflow
库并安装所需的功能:
library(tensorflow)
install_tensorflow()
- 默认情况下,安装功能会创建虚拟环境并在虚拟环境中安装
tensorflow
包。
有四种可用的安装方法,可以使用method
参数指定:
auto |
自动选择当前平台的默认值 |
virtualenv |
安装到位于~/.virtualenvs/r-tensorflow 的虚拟环境中 |
conda |
安装到名为r-tensorflow 的 Anaconda Python 环境中 |
system |
安装到系统 Python 环境中 |
- 默认情况下,安装功能会安装仅限 CPU 的 TensorFlow 版本。要安装 GPU 版本,请使用版本参数:
gpu |
安装tensorflow-gpu
|
nightly |
安装每晚 CPU 的版本 |
nightly-gpu |
安装每晚 GPU 构建 |
n.n.n |
安装特定版本,例如 1.3.0 |
n.n.n-gpu |
安装特定版本的 GPU 版本,例如 1.3.0 |
如果您希望 TensorFlow 库使用特定版本的 Python,请使用以下函数或设置TENSORFLOW_PYTHON
环境变量:
use_python('/usr/bin/python2')
use_virtualenv('~/venv')
use_condaenv('conda-env')
Sys.setenv(TENSORFLOW_PYTHON='/usr/bin/python2')
We installed TensorFLow in R on Ubuntu 16.04 using the following command:
install_tensorflow(version="gpu")
Note that the installation does not support Python 3 at the time of writing this book.
- 安装 Keras 包:
devtools::install_github("rstudio/keras")
- 在虚拟环境中安装 Keras:
library(keras)
install_keras()
- 要安装 GPU 版本,请使用:
install_keras(tensorflow = "gpu")
- 安装
tfruns
包:
devtools::install_github("rstudio/tfruns")
R 中的 TF 核心 API
我们在第 1 章中了解了 TensorFlow 核心 API。在 R 中,该 API 使用tensorflow
R 包实现。
作为一个例子,我们提供了 MLP 模型的演练,用于在此链接中对来自 MNIST 数据集的手写数字进行分类。
您可以按照 Jupyter R 笔记本中的代码ch-17a_TFCore_in_R
。
- 首先,加载库:
library(tensorflow)
- 定义超参数:
batch_size 128
num_classes 10
steps 1000
- 准备数据:
datasets tf$contrib$learn$datasets
mnist datasets$mnist$read_data_sets("MNIST-data", one_hot = TRUE)
数据从 TensorFlow 数据集库加载,并已标准化为[0, 1]
范围。
- 定义模型:
# Create the model
x tf$placeholder(tf$float32, shape(NULL, 784L))
W tf$Variable(tf$zeros(shape(784L, num_classes)))
b tf$Variable(tf$zeros(shape(num_classes)))
y tf$nn$softmax(tf$matmul(x, W) + b)
# Define loss and optimizer
y_ tf$placeholder(tf$float32, shape(NULL, num_classes))
cross_entropy tf$reduce_mean(-tf$reduce_sum(y_ * log(y), reduction_indices=1L))
train_step tf$train$GradientDescentOptimizer(0.5)$minimize(cross_entropy)
- 训练模型:
# Create session and initialize variables
sess tf$Session()
sess$run(tf$global_variables_initializer())
# Train
for (i in 1:steps) {
batches mnist$train$next_batch(batch_size)
batch_xs batches[[1]]
batch_ys batches[[2]]
sess$run(train_step,
feed_dict = dict(x = batch_xs, y_ = batch_ys))
}
- 评估模型:
correct_prediction tf$equal(tf$argmax(y, 1L), tf$argmax(y_, 1L))
accuracy tf$reduce_mean(tf$cast(correct_prediction, tf$float32))
score sess$run(accuracy,
feed_dict = dict(x = mnist$test$images,
y_ = mnist$test$labels))
cat('Test accuracy:', score, 'n')
输出如下:
Test accuracy: 0.9185
太酷了!
通过此链接查找 R 中 TF 核心的更多示例。
有关tensorflow
R 包的更多文档可以在此链接中找到。
R 中的 TF 估计器 API
我们在第 2 章中了解了 TensorFlow 估计器 API。在 R 中,此 API 使用tfestimator
R 包实现。
例如,我们提供了 MLP 模型的演练,用于在此链接中对来自 MNIST 数据集的手写数字进行分类。
您可以按照 Jupyter R 笔记本中的代码ch-17b_TFE_Ttimator_in_R
。
- 首先,加载库:
library(tensorflow)
library(tfestimators)
- 定义超参数:
batch_size 128
n_classes 10
n_steps 100
- 准备数据:
# initialize data directory
data_dir "~/datasets/mnist"
dir.create(data_dir, recursive = TRUE, showWarnings = FALSE)
# download the MNIST data sets, and read them into R
sources list(
train = list(
x = "https://storage.googleapis.com/cvdf-datasets/mnist/train-images-idx3-ubyte.gz",
y = "https://storage.googleapis.com/cvdf-datasets/mnist/train-labels-idx1-ubyte.gz"
),
test = list(
x = "https://storage.googleapis.com/cvdf-datasets/mnist/t10k-images-idx3-ubyte.gz",
y = "https://storage.googleapis.com/cvdf-datasets/mnist/t10k-labels-idx1-ubyte.gz"
)
)
# read an MNIST file (encoded in IDX format)
read_idx function(file) {
# create binary connection to file
conn gzfile(file, open = "rb")
on.exit(close(conn), add = TRUE)
# read the magic number as sequence of 4 bytes
magic readBin(conn, what="raw", n=4, endian="big")
ndims as.integer(magic[[4]])
# read the dimensions (32-bit integers)
dims readBin(conn,what="integer",n=ndims,endian="big")
# read the rest in as a raw vector
data readBin(conn,what="raw",n=prod(dims),endian="big")
# convert to an integer vecto
converted as.integer(data)
# return plain vector for 1-dim array
if (length(dims) == 1)
return(converted)
# wrap 3D data into matrix
matrix(converted,nrow=dims[1],ncol=prod(dims[-1]),byrow=TRUE)
}
mnist rapply(sources,classes="character",how ="list",function(url) {
# download + extract the file at the URL
target file.path(data_dir, basename(url))
if (!file.exists(target))
download.file(url, target)
# read the IDX file
read_idx(target)
})
# convert training data intensities to 0-1 range
mnist$train$x mnist$train$x / 255
mnist$test$x mnist$test$x / 255
从下载的 gzip 文件中读取数据,然后归一化以落入[0, 1]
范围。
- 定义模型:
# construct a linear classifier
classifier linear_classifier(
feature_columns = feature_columns(
column_numeric("x", shape = shape(784L))
),
n_classes = n_classes # 10 digits
)
# construct an input function generator
mnist_input_fn function(data, ...) {
input_fn(
data,
response = "y",
features = "x",
batch_size = batch_size,
...
)
}
- 训练模型:
train(classifier,input_fn=mnist_input_fn(mnist$train),steps=n_steps)
- 评估模型:
evaluate(classifier,input_fn=mnist_input_fn(mnist$test),steps=200)
输出如下:
Evaluation completed after 79 steps but 200 steps was specified
average_loss | 损失 | global_step | 准确率 |
---|---|---|---|
0.35656 | 45.13418 | 100 | 0.9057 |
太酷!!
通过此链接查找 R 中 TF 估计器的更多示例。
有关tensorflow
R 包的更多文档可以在此链接中找到
R 中的 Keras API
我们在第 3 章中了解了 Keras API。在 R 中,此 API 使用keras
R 包实现。keras
R 包实现了 Keras Python 接口的大部分功能,包括顺序 API 和函数式 API。
作为示例,我们提供了 MLP 模型的演练,用于在此链接中对来自 MNIST 数据集的手写数字进行分类。
您可以按照 Jupyter R 笔记本中的代码ch-17c_Keras_in_R
。
- 首先,加载库:
library(keras)
- 定义超参数:
batch_size 128
num_classes 10
epochs 30
- 准备数据:
# The data, shuffled and split between train and test sets
c(c(x_train, y_train), c(x_test, y_test)) % dataset_mnist()
x_train array_reshape(x_train, c(nrow(x_train), 784))
x_test array_reshape(x_test, c(nrow(x_test), 784))
# Transform RGB values into [0,1] range
x_train x_train / 255
x_test x_test / 255
cat(nrow(x_train), 'train samplesn')
cat(nrow(x_test), 'test samplesn')
# Convert class vectors to binary class matrices
y_train to_categorical(y_train, num_classes)
y_test to_categorical(y_test, num_classes)
注释是不言自明的:数据从 Keras 数据集库加载,然后转换为 2D 数组并归一化为[0, 1]
范围。
- 定义模型:
model keras_model_sequential()
model %>%
layer_dense(units=256,activation='relu',input_shape=c(784)) %>%
layer_dropout(rate = 0.4) %>%
layer_dense(units = 128, activation = 'relu') %>%
layer_dropout(rate = 0.3) %>%
layer_dense(units = 10, activation = 'softmax')
summary(model)
model %>% compile(
loss = 'categorical_crossentropy',
optimizer = optimizer_rmsprop(),
metrics = c('accuracy')
)
- 定义和编译顺序模型。我们得到的模型定义如下:
_____________________________________________________
Layer (type) Output Shape Param #
=====================================================
dense_26 (Dense) (None, 256) 200960
_____________________________________________________
dropout_14 (Dropout) (None, 256) 0
_____________________________________________________
dense_27 (Dense) (None, 128) 32896
_____________________________________________________
dropout_15 (Dropout) (None, 128) 0
_____________________________________________________
dense_28 (Dense) (None, 10) 1290
=====================================================
Total params: 235,146
Trainable params: 235,146
Non-trainable params: 0
- 训练模型:
history model %>% fit(
x_train, y_train,
batch_size = batch_size,
epochs = epochs,
verbose = 1,
validation_split = 0.2
)
plot(history)
拟合函数的输出存储在历史对象中,其包含来自训练周期的损失和度量值。绘制历史对象中的数据,结果如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BkohXoDy-1681566673391)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/mastering-tf-1x-zh/img/70f64c1f-5d97-4e56-9bf8-1d6fc719622d.png)]Training and Validation Accuracy (y-axis) in Epochs (x-axis)
- 评估模型:
score model %>% evaluate(
x_test, y_test,
verbose = 0
)
# Output metrics
cat('Test loss:', score[[1]], 'n')
cat('Test accuracy:', score[[2]], 'n')
输出如下:
Test loss: 0.1128517
Test accuracy: 0.9816
太酷!!
在此链接中查找更多关于 R 中的 Keras 的示例。
有关 Keras R 包的更多文档可在此链接中找到。
R 中的 TensorBoard
您可以按照 Jupyter R 笔记本中的代码ch-17d_TensorBoard_in_R
。
您可以使用tensorboard()
函数查看 TensorBoard,如下所示:
tensorboard('logs')
这里,'logs'
是应该创建 TensorBoard 日志的文件夹。
数据将显示为执行周期并记录数据。在 R 中,收集 TensorBoard 的数据取决于所使用的包:
- 如果您使用的是
tensorflow
包,请将tf$summary$scalar
操作附加到图中 - 如果您使用的是
tfestimators
包,则 TensorBoard 数据会自动写入创建估计器时指定的model_dir
参数 - 如果您正在使用
keras
包,则必须在使用fit()
函数训练模型时包含callback_tensorboard()
函数
我们修改了之前提供的 Keras 示例中的训练,如下所示:
# Training the model --------
tensorboard("logs")
history model %>% fit(
x_train, y_train,
batch_size = batch_size,
epochs = epochs,
verbose = 1,
validation_split = 0.2,
callbacks = callback_tensorboard("logs")
)
当我们执行笔记本时,我们获得了训练单元的以下输出:
Started TensorBoard at http://127.0.0.1:4233
当我们点击链接时,我们会看到在 TensorBoard 中绘制的标量:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CVRBDnjH-1681566673392)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/mastering-tf-1x-zh/img/bf95f8b2-7ada-4382-a52a-48a90c0d523b.png)]TensorBoad Visualization of Plots
单击 Graphs 选项卡,我们在 TensorBoard 中看到计算图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C8J2Xjgb-1681566673392)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/mastering-tf-1x-zh/img/83cbba56-ba2c-4062-9310-7d1f2342b6e1.png)]
TensorBoard 计算图的可视化有关 R 中 TensorBoard 的更多文档,请访问此链接。
R 中的tfruns
包
您可以按照 Jupyter R 笔记本中的代码ch-17d_TensorBoard_in_R
。
tfruns
包是 R 中提供的非常有用的工具,有助于跟踪多次运行以训练模型。对于使用keras
tfestimators
包在 R 中构建的模型,tfruns
包自动捕获运行数据。使用tfruns
非常简单易行。只需在 R 文件中创建代码,然后使用training_run()
函数执行该文件。例如,如果你有一个mnist_model.R
文件 ,那么在交互式 R 控制台中使用training_run()
函数执行它,如下所示:
library(tfruns)
training_run('mnist_model.R')
训练完成后,将自动显示显示运行摘要的窗口。我们从tfruns
GitHub 仓库获得的mnist_mlp.R
窗口中获得以下输出。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2KUgl7T1-1681566673392)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/mastering-tf-1x-zh/img/3b4b915f-a80e-4fb6-a420-fbd44e79eaa3.png)]tfruns visualization of the model run
在“查看器”窗口中,输出选项卡包含以下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Bh4k8zJF-1681566673393)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/mastering-tf-1x-zh/img/cf30d6bc-8aea-4c3f-84e1-7567857412db.png)]tfruns visualization of the accuracy and loss values
tfruns
包将一个插件安装到 RStudio,也可以从Addins
菜单选项访问。该包还允许您比较多个运行并将运行报告发布到 RPub 或 RStudio Connect。您还可以选择在本地保存报告。
有关 R 中tfruns
包的更多文档,请访问以下链接:
https://tensorflow.rstudio.com/tools/tfruns/reference/
https://tensorflow.rstudio.com/tools/tfruns/articles/overview.html.
总结
在本章中,我们学习了如何在 R 中使用 TensorFlow 核心,TensorFlow 估计器和 Keras 包来构建和训练机器学习模型。我们提供了来自 RStudio 的 MNIST 示例的演练,并提供了有关 TensorFlow 和 Keras R 包的进一步文档的链接。我们还学习了如何使用 R 中的可视化工具 TensorBoard。我们还介绍了一个来自 R Studio 的新工具tfruns
,它允许您为多次运行创建报告,分析和比较它们,并在本地保存或发布它们。
直接在 R 中工作的能力很有用,因为大量的生产数据科学和机器学习代码是使用 R 编写的,现在您可以将 TensorFlow 集成到相同的代码库中并在 R 环境中运行它。
在下一章中,我们将学习一些用于调试构建和训练 TensorFlow 模型的代码的技术。
十八、调试 TensorFlow 模型
正如我们在本书中所学到的,TensorFlow 程序用于构建和训练可用于各种任务预测的模型。在训练模型时,您可以构建计算图,运行图以进行训练,并评估图以进行预测。重复这些任务,直到您对模型的质量感到满意为止,然后将图与学习的参数一起保存。在生产中,图是从文件构建或恢复的,并使用参数填充。
构建深度学习模型是一项复杂的技术,TensorFlow API 及其生态系统同样复杂。当我们在 TensorFlow 中构建和训练模型时,有时我们会得到不同类型的错误,或者模型不能按预期工作。例如,您经常看到自己陷入以下一种或多种情况:
- 在损失和指标输出中得到了 NaN
- 即使经过多次迭代,损失或其他指标也没有改善
在这种情况下,我们需要调试使用 TensorFlow API 编写的代码。
要修复代码以使其正常工作,可以使用调试器或平台提供的其他方法和工具,例如 Python 中的 Python 调试器(pdb
)和 Linux OS 中的 GNU 调试器(gdb
)。当出现问题时,TensorFlow API 还提供一些额外的支持来修复代码。
在本章中,我们将学习 TensorFlow 中可用的其他工具和技术,以帮助调试:
- 使用
tf.Session.run()
获取张量值 - 使用
tf.Print()
打印张量值 - 用
tf.Assert()
断言条件 - 使用 TensorFlow 调试器进行调试(
tfdbg
)
使用tf.Session.run()
获取张量值
您可以使用tf.Session.run()
获取要打印的张量值。这些值作为 NumPy 数组返回,可以使用 Python 语句打印或记录。这是最简单和最简单的方法,最大的缺点是计算图执行所有相关路径,从获取的张量开始,如果这些路径包括训练操作,那么它前进一步或一个周期。
因此,大多数情况下你不会调用tf.Session.run()
来获取图中间的张量,但你会执行整个图并获取所有张量,你需要调试的那些张量以及你不需要的张量调试。
函数tf.Session.partial_run()
也适用于您可能想要执行图的一部分的情况,但它是一个高度实验性的 API,尚未准备好用于生产。
使用tf.Print()
打印张量值
为调试目的打印值的另一个选项是使用tf.Print()
。当执行包含tf.Print()
节点的路径时,您可以在tf.Print()
中包含张量以在标准错误控制台中打印其值。tf.Print()
函数具有以下签名:
tf.Print(
input_,
data,
message=None,
first_n=None,
summarize=None,
name=None
)
该函数的参数如下:
-
input_
是一个从函数返回的张量,没有任何操作 -
data
是要打印的张量列表 -
message
是一个字符串,它作为打印输出的前缀打印出来 -
first_n
表示打印输出的步骤数;如果此值为负,则只要执行路径,就始终打印该值 -
summarize
表示从张量打印的元素数量;默认情况下,仅打印三个元素
您可以按照 Jupyter 笔记本中的代码ch-18_TensorFlow_Debugging
。
让我们修改之前创建的 MNIST MLP 模型来添加print
语句:
model = tf.Print(input_=model,
data=[tf.argmax(model,1)],
message='y_hat=',
summarize=10,
first_n=5
)
当我们运行代码时,我们在 Jupyter 的控制台中获得以下内容:
I tensorflow/core/kernels/logging_ops.cc:79] y_hat=[0 0 0 7 0 0 0 0 0 0...]
I tensorflow/core/kernels/logging_ops.cc:79] y_hat=[0 7 7 1 8 7 2 7 7 0...]
I tensorflow/core/kernels/logging_ops.cc:79] y_hat=[4 8 0 6 1 8 1 0 7 0...]
I tensorflow/core/kernels/logging_ops.cc:79] y_hat=[0 0 1 0 0 0 0 5 7 5...]
I tensorflow/core/kernels/logging_ops.cc:79] y_hat=[9 2 2 8 8 6 6 1 7 7...]
使用tf.Print()
的唯一缺点是该函数提供了有限的格式化功能。
tf.Assert()
调试 TensorFlow 模型的另一种方法是插入条件断言。tf.Assert()
函数需要一个条件,如果条件为假,则打印给定张量的列表并抛出tf.errors.InvalidArgumentError
。
-
tf.Assert()
函数具有以下特征:
tf.Assert(
condition,
data,
summarize=None,
name=None
)
- 断言操作不会像
tf.Print()
函数那样落入图的路径中。为了确保tf.Assert()
操作得到执行,我们需要将它添加到依赖项中。例如,让我们定义一个断言来检查所有输入是否为正:
assert_op = tf.Assert(tf.reduce_all(tf.greater_equal(x,0)),[x])
- 在定义模型时将
assert_op
添加到依赖项,如下所示:
with tf.control_dependencies([assert_op]):
# x is input layer
layer = x
# add hidden layers
for i in range(num_layers):
layer = tf.nn.relu(tf.matmul(layer, w[i]) + b[i])
# add output layer
layer = tf.matmul(layer, w[num_layers]) + b[num_layers]
- 为了测试这段代码,我们在第 5 周期之后引入了一个杂质,如下:
if epoch > 5:
X_batch = np.copy(X_batch)
X_batch[0,0]=-2
- 代码运行正常五个周期,然后抛出错误:
epoch: 0000 loss = 6.975991
epoch: 0001 loss = 2.246228
epoch: 0002 loss = 1.924571
epoch: 0003 loss = 1.745509
epoch: 0004 loss = 1.616791
epoch: 0005 loss = 1.520804
-----------------------------------------------------------------
InvalidArgumentError Traceback (most recent call last)
...
InvalidArgumentError: assertion failed: [[-2 0 0]...]
...
除了tf.Assert()
函数,它可以采用任何有效的条件表达式,TensorFlow 提供以下断言操作,检查特定条件并具有简单的语法:
assert_equal
assert_greater
assert_greater_equal
assert_integer
assert_less
assert_less_equal
assert_negative
assert_none_equal
assert_non_negative
assert_non_positive
assert_positive
assert_proper_iterable
assert_rank
assert_rank_at_least
assert_rank_in
assert_same_float_dtype
assert_scalar
assert_type
assert_variables_initialized
作为示例,前面提到的示例断言操作也可以写成如下:
assert_op = tf.assert_greater_equal(x,0)
使用 TensorFlow 调试器(tfdbg
)的调试
TensorFlow 调试器(tfdbg
)与其他常用调试器(如pdb
和gdb
)的工作方式相同。要使用调试器,该过程通常如下:
- 在代码中的断点处设置要中断的位置并检查变量
- 在调试模式下运行代码
- 当代码在断点处中断时,检查它然后继续下一步
一些调试器还允许您在代码执行时以交互方式观察变量,而不仅仅是在断点处:
- 为了使用
tfdbg
,首先导入所需的模块并将会话包装在调试器包装器中:
from tensorflow.python import debug as tfd
with tfd.LocalCLIDebugWrapperSession(tf.Session()) as tfs:
- 接下来,将过滤器附加到会话对象。附加过滤器与在其他调试器中设置断点相同。例如,以下代码附加
tfdbg.has_inf_or_nan
过滤器,如果任何中间张量具有nan
或inf
值,则会中断:
tfs.add_tensor_filter('has_inf_or_nan_filter', tfd.has_inf_or_nan)
- 现在,当代码执行
tfs.run()
时,调试器将在控制台中启动调试器接口,您可以在其中运行各种调试器命令来监视张量值。 - 我们提供了在
ch-18_mnist_tfdbg.py
文件中试用tfdbg
的代码。当我们用python3
执行代码文件时,我们看到tfdbg
控制台:
python3 ch-18_mnist_tfdbg.py
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YpIXKend-1681566673393)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/mastering-tf-1x-zh/img/028e301e-7560-4cc4-bc10-63625534c2c3.png)]
- 在
tfdbg>
提示符下输入命令run -f has_inf_or_nan
。代码在第一个周期后中断,因为我们使用np.inf
值填充数据:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0QP2wrsk-1681566673393)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/mastering-tf-1x-zh/img/5d59edaa-a409-4f87-ba9f-c690fbbe820a.png)]
- 现在您可以使用
tfdbg
控制台或可点击界面来检查各种张量的值。例如,我们查看其中一个梯度的值:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wB43gyIl-1681566673394)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/mastering-tf-1x-zh/img/10bbefc3-6401-4e19-bbf2-9e0113f6e035.png)]
您可以在此链接中找到有关使用tfdbg
控制台和检查变量的更多信息。
总结
在本章中,我们学习了如何在 TensorFlow 中调试用于构建和训练模型的代码。我们了解到我们可以使用tf.Session.run()
将张量作为 NumPy 数组获取。我们还可以通过在计算图中添加tf.Print()
操作来打印张量值。我们还学习了,在使用tf.Assert()
和其他tf.assert_*
操作执行期间,某些条件无法保持时如何引发错误。我们通过对 TensorFlow 调试器(tfdbg
)的介绍结束本章,用于设置断点和观察张量值,就像我们在 Python 调试器(pdb
)或 GNU 调试器(gdb
中调试代码一样) )。
本章将我们的旅程带入一个新的里程碑。我们不希望旅程在此结束,但我们相信旅程刚刚开始,您将进一步扩展和应用本书中获得的知识和技能。
我们非常期待听到您的经验,反馈和建议。
十九、张量处理单元
张量处理单元(TPU)是专用集成电路(ASIC),它实现了针对计算要求而优化的硬件电路深度神经网络。 TPU 基于复杂指令集计算机(CISC)指令集,该指令集实现用于训练深度神经网络的复杂任务的高级指令。 TPU 架构的核心在于优化矩阵运算的脉动数组。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qZk11F3r-1681566673394)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/mastering-tf-1x-zh/img/1dc1da7c-6209-49fc-b670-698bcc3c4d42.png)]The Architecture of TPUImage from: https://cloud.google.com/blog/big-data/2017/05/images/149454602921110/tpu-15.png
TensorFlow 提供了一个编译器和软件栈,可将 API 调用从 TensorFlow 图转换为 TPU 指令。以下框图描述了在 TPU 栈顶部运行的 TensorFlow 模型的架构:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BcsrQjZ3-1681566673394)(https://gitcode.net/apachecn/apachecn-dl-zh/-/raw/master/docs/mastering-tf-1x-zh/img/d57598de-e922-4cfe-941c-883553bf35e0.png)]
图像来自这个链接。TPU 架构的更多信息,阅读博客。
TPU 的 TensorFlow API 位于tf.contrib.tpu
模块中。为了在 TPU 上构建模型,使用以下三个 TPU 特定的 TensorFlow 模块:
-
tpu_config
:tpu_config
模块允许您创建配置对象,其中包含有关将运行模型的主机的信息。 -
tpu_estimator
:tpu_estimator
模块将估计器封装在TPUEstimatorSpec
类中。要在 TPU 上运行估计器,我们创建此类的对象。 -
tpu_optimizer
:tpu_optimizer
模块包装优化器。例如,在下面的示例代码中,我们将tpu_optimizer
类中的 SGD 优化器包装在tpu_optimizer
类中。
例如,以下代码使用 TFEstimator API 为 TPU 上的 MNIST 数据集构建 CNN 模型:
以下代码改编自这个页面。
import tensorflow as tf
from tensorflow.contrib.tpu.python.tpu import tpu_config
from tensorflow.contrib.tpu.python.tpu import tpu_estimator
from tensorflow.contrib.tpu.python.tpu import tpu_optimizer
learning_rate = 0.01
batch_size = 128
def metric_fn(labels, logits):
predictions = tf.argmax(logits, 1)
return {
"accuracy": tf.metrics.precision(
labels=labels, predictions=predictions),
}
def model_fn(features, labels, mode):
if mode == tf.estimator.ModeKeys.PREDICT:
raise RuntimeError("mode {} is not supported yet".format(mode))
input_layer = tf.reshape(features, [-1, 28, 28, 1])
conv1 = tf.layers.conv2d(
inputs=input_layer,
filters=32,
kernel_size=[5, 5],
padding="same",
activation=tf.nn.relu)
pool1 = tf.layers.max_pooling2d(inputs=conv1, pool_size=[2, 2],
strides=2)
conv2 = tf.layers.conv2d(
inputs=pool1,
filters=64,
kernel_size=[5, 5],
padding="same",
activation=tf.nn.relu)
pool2 = tf.layers.max_pooling2d(inputs=conv2, pool_size=[2, 2],
strides=2)
pool2_flat = tf.reshape(pool2, [-1, 7 * 7 * 64])
dense = tf.layers.dense(inputs=pool2_flat, units=128,
activation=tf.nn.relu)
dropout = tf.layers.dropout(
inputs=dense, rate=0.4,
training=mode == tf.estimator.ModeKeys.TRAIN)
logits = tf.layers.dense(inputs=dropout, units=10)
onehot_labels = tf.one_hot(indices=tf.cast(labels, tf.int32), depth=10)
loss = tf.losses.softmax_cross_entropy(
onehot_labels=onehot_labels, logits=logits)
if mode == tf.estimator.ModeKeys.EVAL:
return tpu_estimator.TPUEstimatorSpec(
mode=mode,
loss=loss,
eval_metrics=(metric_fn, [labels, logits]))
# Train.
decaying_learning_rate = tf.train.exponential_decay(learning_rate,
tf.train.get_global_step(),
100000,0.96)
optimizer = tpu_optimizer.CrossShardOptimizer(
tf.train.GradientDescentOptimizer(
learning_rate=decaying_learning_rate))
train_op = optimizer.minimize(loss,
global_step=tf.train.get_global_step())
return tpu_estimator.TPUEstimatorSpec(mode=mode,
loss=loss, train_op=train_op)
def get_input_fn(filename):
def input_fn(params):
batch_size = params["batch_size"]
def parser(serialized_example):
features = tf.parse_single_example(
serialized_example,
features={
"image_raw": tf.FixedLenFeature([], tf.string),
"label": tf.FixedLenFeature([], tf.int64),
})
image = tf.decode_raw(features["image_raw"], tf.uint8)
image.set_shape([28 * 28])
image = tf.cast(image, tf.float32) * (1. / 255) - 0.5
label = tf.cast(features["label"], tf.int32)
return image, label
dataset = tf.data.TFRecordDataset(
filename, buffer_size=FLAGS.dataset_reader_buffer_size)
dataset = dataset.map(parser).cache().repeat()
dataset = dataset.apply(
tf.contrib.data.batch_and_drop_remainder(batch_size))
images, labels = dataset.make_one_shot_iterator().get_next()
return images, labels
return input_fn
# TPU config
master = 'local' #URL of the TPU instance
model_dir = '/home/armando/models/mnist'
n_iterations = 50 # number of iterations per TPU training loop
n_shards = 8 # number of TPU chips
run_config = tpu_config.RunConfig(
master=master,
evaluation_master=master,
model_dir=model_dir,
session_config=tf.ConfigProto(
allow_soft_placement=True,
log_device_placement=True
),
tpu_config=tpu_config.TPUConfig(n_iterations,
n_shards
)
)
estimator = tpu_estimator.TPUEstimator(
model_fn=model_fn,
use_tpu=True,
train_batch_size=batch_size,
eval_batch_size=batch_size,
config=run_config)
train_file = '/home/armando/datasets/mnist/train' # input data file
train_steps = 1000 # number of steps to train for
estimator.train(input_fn=get_input_fn(train_file),
max_steps=train_steps
)
eval_file = '/home/armando/datasets/mnist/test' # test data file
eval_steps = 10
estimator.evaluate(input_fn=get_input_fn(eval_file),
steps=eval_steps
)
有关在 TPU 上构建模型的更多示例,请访问此链接。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net