译者| 王天宇、林椿眄
责编| Jane、琥珀
出品| AI科技大本营
深度学习发展势头迅猛,但近两年涌现的诸多深度学习框架让初学者无所适从。如 Google 的 TensorFlow、亚马逊的 MXNet、Facebook 支持的 PyTorch、Theano、Caffe、CNTK、Chainer、百度的 PaddlePaddle、DSSTNE、DyNet、BigDL、Neon 等等。
在这其中,TensorFlow 作为最为著名的用于深度学习生产环境的框架,它有一个非常强大的生态体系支持,然而,相比其他框架,TensorFlow 也有其劣势,如速度较慢、使用上手难。而基于 TensorFlow 基础上构建的 Keras 提供了简单易用的 API 接口,非常适合初学者使用。
2017 年 1 月,随着 Keras 的作者、谷歌 AI 研究员 Francois Chollet 的一条消息的宣布,Keras 成为第一个被添加到 TensorFlow 核心的高级别框架,Keras 从此成为 Tensorflow 的默认 API。
“那么,我应该在项目中使用 Keras 还是 TensorFlow?Keras 和 TensorFlow 究竟哪个会更好?我应该把时间花在研究 TensorFlow 还是 Keras 上?”
在与深度学习的研究人员、从业者包括工程师在内的交谈中,“Deep Learning for Computer Vision with Python ”一书作者 Adrian Rosebrock 听到了他们的困惑。
就 Keras 和 TensorFlow 而言,Rosebrock 认为开发者更应该关注的是当 Keras 实际上已被完全采用并整合到 TensorFlow 后,自己可以:
- 使用 Keras 易于使用的界面定义模型。
- 如果需要 TensorFlow 的特定功能,或需要实现 Keras 不支持但 TensorFlow 支持的自定义功能,则调入 TensorFlow。
他给出的建议是先使用 Keras ,然后下载 TensorFlow 以获取可能需要的任何特定功能。文本中,Rosebrock 展示了如何训练使用 Keras 的神经网络和使用直接构建在 TensorFlow 库中的 Keras TensorFlow 集成(具有自定义功能)的模型。
下面开始正文:
▌对比 Keras 和 TensorFlow 没什么意义
前些年,深度学习领域的研究人员、开发人员和工程师必须经常做出一些选择:
- 我应该选择易于使用但自定义困难的 Keras 库?
- 还是应该使用难度更大的 TensorFlow API,编写大量代码?(更不用说一个不那么容易使用的 API 了。)
如果你陷于“我应该使用 Keras 还是 TensorFlow”这样的问题,你可以退一步再看,其实这是一个错误的问题,因为你可以选择同时使用两个。
我会使用基于 TensorFlow 的标准 keras 模块和 tf.keras 模块,来实现一个卷积神经网络(CNN)。然后,基于一个示例数据集,来训练这些 CNN,然后检查所得结果,你会发现,Keras 和 TensorFlow 是可以和谐共处的。
虽然自一年多之前,TensorFlow 就宣称 Keras 将被并入 TensorFlow 的官方发布版本中,但令我诧异的是,仍有很多深度学习开发者没有意识到,他们可以通过 tf.keras 子模块来调用 Keras。更重要的是,Keras 与 TensorFlow 是无缝衔接的,使得我们将 TensorFlow 的源代码直接写入 Keras 模型中。
在 TensorFlow 中结合 Keras 使用,会有双赢效果:
- 你可以使用 Keras 提供的简单、原生 API 来创建自己的模型。
- Keras 的 API 类似于 scikit-learn 的,都可称为机器学习的优质 API。
- Keras 的 API 是模块化的、基于 Python ,并且极其易于使用。
- 当你需要实现一个自定义的层或更复杂的损失函数时,你可以深入使用 TensorFlow,将代码自动地与 Keras 模型相结合。
▌Keras 通过 tf.keras 模块构建到 TensorFlow 中
可以看到,我们通过引入 TensorFlow (tf) 并调用 tf.keras,在 Python shell 中展示了 Keras 实际上是 TensorFlow 的一部分。
tf.keras 中的 Keras 允许我们使用标准的 Keras 包获取下面这样简单的前馈神经网络:
接下来基于 TensorFlow 的一部分 —— tf.keras 子模块,来实现同样的网络:
然而这是否意味着你必须使用 tf.keras?从而现在放弃使用标准 Keras 包了吗?当然不是!
Keras 依然作为一个库,与 TensorFlow 分开,进行独立操作,所以仍存在未来两者会分开的可能性;然而,我们知道 Google 官方同时支持 Keras 和 TensorFlow,分开似乎又是极不可能发生的。
但重点在于:
如果你更喜欢只基于 Keras 来编程,那就这么做吧,以后可以一直如此。但如果你是 TensorFlow 用户,你应该开始考虑 Keras API 了,因为:
- 它是基于 TensorFlow 创建的
- 它更易于使用
- 当你需要用纯 TensorFlow 实现特定性能或功能时,它可以直接用于你的 Keras。
▌示例数据集
CIFAR-10 数据集有10个类,我们用该数据集来展示本文的观点
为了简单起见,我们就在 CIFAR-10 数据集上训练两个单独的卷积神经网络 (CNN),方案如下:
方法 1 :以 TensorFlow 作为后端的 Keras 模型
方法 2 :使用 tf.keras 中 Keras 子模块
在介绍的过程中我还会展示如何把自定义的 TensorFlow 代码写入你的 Keras 模型中。
CIFAR-10 数据集包括10个单独的类,50,000 张训练图片和 10,000 张测试图片。
▌项目结构
我们可以在终端使用 tree 指令来查看该项目的结构:
pyimagesearch 模块被包括在与网络条目相关的下载中。它不能通过 pip 来安装,但包含在 "Downloads"后的结果中。我们先回顾一下该模块中两个重要的 Python 文件:
- minivggnetkeras.py:此文件是基于 Keras 实现的 MiniVGGNet 网络,一个基于 VGGNet 的深度学习模型。
- minivggnettf.py:此文件是基于 TensorFlow Keras (如 tf.keras)实现的 MiniVGGNet 网络。
该项目的根目录包含两个 Python 文件:
- train_network_keras.py:用 Keras 实现的训练脚本;
- train_network_tf.py: TensorFlow Keras 实现需要的训练脚本,与前者基本相同;但我们仍会进行说明,并标出不同之处。
每个脚本都会生成各自训练的 accuracy 和 loss 曲线:
- plot_keras.png
- plot_tf.png
接下来就会向大家介绍基于 Keras 和 TensorFlow Keras (tf.keras) 实现的 MiniVGGNet 网络和他们的训练过程。
▌用 Keras 训练一个神经网络
用 Keras 实现的一个 miniVGGNet 卷积神经网络结构
训练我们网络的第一步是在 Keras 中构建网络的架构。
如果你已经熟悉 Keras 训练神经网络的基础知识,那么我们就开始吧 (如果你对此并不了解的话,请参考相关的介绍性文章)。
相关链接:https://www.pyimagesearch.com/2018/09/10/keras-tutorial-how-to-get-started-with-keras-deep-learning-and-python/
首先,打开 minivggnetkeras.py 文件并插入以下代码:
从导入一系列所需的 Keras 库开始构建模型。
然后,定义一个的 MiniVGGNetKeras 类:
我们在第 12 行定义了 build 方法,并定义 inputShape 和 input 参数。 我们假定以 channel last 的规则排序,所以 inputShape 参数中最后一个值应该对应的是 depth 值。
下面开始定义卷积神经网络的主体结构:
从上面这段代码你可以观察到我们在每次应用池化 (pooling) 之前都堆叠了一系列卷积 (conv2D),ReLU 激活函数和批规范化层 (batch normalization),以降低卷积操作后的空间维度。此外,我们还使用 Dropout 技术来防止模型的过拟合现象。
对于图层类型和有关术语的知识,可以参考以前的 Keras 教程
https://www.pyimagesearch.com/2018/09/10/keras-tutorial-how-to-get-started-with-keras-deep-learning-and-python/
如果想深入研究的话,推荐书“Deep Learning for Computer Vision with Python ” https://www.pyimagesearch.com/deep-learning-computer-vision-python-book/
然后,将全连接层 (FC) 添加到网络结构中,代码如下:
我们将 FC 层和 Softmax 分类器添加到网络中。随后我们定义神经网络模型并将其返回给回调函数 (calling function)。
现在我们已经在 Keras 中实现了 CNN 模型的定义。下面,我们创建用于训练该模型的程序脚本。
打开 train_network_keras.py 文件并插入以下代码:
我们首先在代码的第 2-13 行导入我们模型训练所需的包。
需要注意的是:
- 在第 3 行,将 Matplotlib 的后端设置为 Agg,以便我们可以能将训练图保存为图像文件。
- 在第 6 行,我们导入 MiniVGGNetKeras 类。
- 我们使用 scikit-learn 库中的 LabelBinarizer 方法进行独热编码 (one-hot encoding),并使用其 classification_report 方法打印出分类精度统计结果 (分别对应第 7 行和第 8 行)。
- 我们在第 10 行导入训练所需的数据库。
如何使用自定义的数据集,可参考
https://www.pyimagesearch.com/2018/09/10/keras-tutorial-how-to-get-started-with-keras-deep-learning-and-python/
https://www.pyimagesearch.com/2018/04/16/keras-and-convolutional-neural-networks-cnns/
此外,我们还在第 16-19 行解析了一个命令行参数 (输出 --plot path)。
下面我们就加载 CIFAR-10 数据集,并对标签进行编码操作,代码如下:
在第 24 行和第 25 行中,我们分别加载并提取训练和测试所需的数据,同时在第 26 和 27 行将数据进行 floating point scale 转化。
第 30-36 行我们对标签进行编码并初始化真实的 labelNames。
模型定义和数据集导入的工作都已经完成。现在可以开始训练我们的模型,代码如下:
在第 40-46 行,我们设置训练过程所需的一些参数和模型优化方法。
然后在第 47-50 行,我们使用 MiniVGGNetKeras.build 方法初始化我们的模型并进行编译。
最后,在第 54 和 55 行启动模型的训练程序。
下面,我们将对网络模型进行评估并生成一个结果图:
在这里,我们利用测试数据来评估我们的模型,并生成 classification_report。最后,我们将评估结果集成并导出结果图。
需要注意的是,通常在这里我们会将模型序列化并导出我们的模型,以便可以在图像或视频处理脚本中使用它,但在这篇教程中我们不介绍这部分的内容。
如果你想要运行以上的脚本,请确认下载本文的源代码。
然后,打开一个终端并执行以下命令就可以用 Keras 实现一个神经网络:
在我的电脑 cpu 上运行每个训练 epoch 只需要 5 多分钟。训练结果图如下:
用 Keras 实现的神经网络模型,以 Matplotlib 画出训练过程的 accuracy/loss 曲线
正如我们从上面终端的输出看到那样,我们的模型取得75%的准确度。虽然这不是最先进的模型,但它能比随机猜测 (1/10) 要好得多。
相比起小型的神经网络,我们模型的结果实际上是非常好的!
此外,正如我们在输出图6中所示,我们模型并不会发生过拟合现象。
▌用 Tensorflow 和 tf.keras 训练一个神经网络模型
使用 tf.keras (内置于 TensorFlow 中的模块) 构建的 MiniVGGNet CNN 架构与我们直接使用 Keras 构建的模型是相同的。在此,出于演示的目的,我改变了其中的激活函数,其他的结构都是相同的。
上面我们已经能够使用 Keras 库实现并训练了一个简单的 CNN 模型。接下来,我们要做的是:
1.学习如何使用 TensorFlow 中的 tf.keras 模块实现相同的网络架构
2.在我们的 Keras 模型中包含一个 TensorFlow 激活函数,而该函数未在Keras中实现。
下面,让我们开始吧。
首先,打开 minivggnettf.py 文件,我们将实现 TensorFlow 版的 MiniVGGNet 模型,代码如下:
在这个 .py 文件中,请注意第 2 行我们需要导入所需的 tensorflow 依赖库,而 tensorflow 中自带 tf.keras 子模块,该子模块包含我们可以直接调用的所有 Keras 功能。
在模型定义中,我使用 Lambda 层,如代码中的黄色突出显示,它可以用于插入自定义激活函数 CRELU (Concatenated ReLUs),
激活函数 CRELU 是由 Shang 等人在论文“Understanding and Improving Convolutional Neural Network”中所提出。
CRELU 激活函数在 Keras 中没有相应的实现,但是在 TensorFlow 中可以。你可以在 TensorFlow 中的 tf.keras 模块,使用一行代码来将 CRELU 函数添加到我们的 Keras 模型中。
还需要注意的是:CRELU 函数有两个输出,一个 positive ReLU 和一个 negative ReLU,二者连接在一起。对于正值 x,CRELU 函数的返回值是 [x,0];而对于负值 x,CRELU 函数的返回值是 [0,x]。有关该函数的详细介绍可以参考 Shang 等人的论文。
接下来,我们将用 TensorFlow Keras 来定义用于训练 MiniVGGNetTF 模型的程序。打开 train_network_tf.py 并插入如下代码:
在 2-12 行,我们导入训练过程所需的依赖库。与我们之前的 Keras 版的训练脚本相比,唯一的变化在于我们导入了 MiniVGGNetTF 类及 tensorflow as tf 而不是使用 Keras。而在第 15-18 行是我们的命令行参数解析部分。
和之前一样,我们在第 23 行加载模型训练所需的数据。脚本剩余的部分和之前 Keras 版的训练过程是一样的,即提取并分离训练和测试集数据并编码我们的标签。
下面,让我们开始训练我们的模型,代码如下:
在第 39-54 行,是与 Keras 版训练过程不同的地方,我们用黄色突出显示,其余部分都是相同的。
在第 58-73 行,我们用测试数据评估我们的模型并绘制最终的结果。
正如你所看到的,我们只是更换了所使用的方法 (使用 tf.keras),实现了几乎一样的训练流程。
然后,打开一个终端并执行以下命令就可以使用 tensorflow tf.keras 训练一个神经网络模型:
训练完成后,你可以得到如上类似的训练结果图:
用 Tensorflow tf.keras 实现的神经网络模型,以 Matplotlib 画出训练过程的 accuracy/loss 曲线
可以看到,我们用 CRELU 代替原有的 RELU 激活函数,获得 76% 的准确率; 然而,1% 的准确性提升增加可能是由于网络中权重的随机初始化导致的,这还需进行交叉验证实验来进一步证明 CRELU 激活函数是否确实能够提升模型的准确性。当然,原始精度并不是本节所重点关注的内容。
相反,更需要我们注意的是,如何在 Keras 模型内部,用 TensorFlow 的激活函数替换标准 Keras 激活函数!
此外,你也可以使用自定义的激活函数、损失/成本函数或图层来执行以上相同的操作。
▌总结
在今天的文章中,关于 Keras 和 TensorFlow 我们主要讨论了以下几个问题:
- 我是否应该在我的项目中使用 Keras 或 TensorFlow?
- TensorFlow 比 Keras 要好吗?
- 我是否要花时间学习 TensorFlow 或者 Keras?
最终,我们发现,试图在 Keras 和 TensorFlow 之间作出抉择变成一个越来越无关紧要的问题。Keras 库已经通过 tf.keras 模块直接集成到 TensorFlow 中了。
本质上来说,你可以通过易于使用的 Keras API 来编码模型和训练过程,然后用纯 TensorFlow 进行自定义实现。
所以,如果你正准备开始学习深度学习,或在纠结下一个项目是“用 Keras 还是 TensorFlow ?”或就是在思考他们两者间“谁更好?”这些问题,现在正是寻找答案和动力的时候了,而我给你的建议非常简单:
- 不多说,先开始!
- 在你的 Python 项目中输入 import keras 或者 import tensorflow as tf (这样你就可以访问 tf.keras 了)然后开始后续的工作。
- TensorFlow 可以直接集成到你的模型和训练过程中,所以不用去比较特性,功能或易用性,你都可以直接在项目中使用 TensorFlow 或 Keras。
▌读者的疑问
对此,有读者提出了尖锐的疑问:
根据上述以及我的了解,不少开发者仍纠缠在 Keras 和 TensorFlow 究竟是什么的问题,可能对此我也不甚了解,但我还是希望提出一些澄清性的问题:
一是在这二者中,将一个视为计算引擎,另一个作为一种工具包是否正确?如果这样的话,我猜测 TensorFlow 是工具包而 Keras 是计算后端?
二是你也提到 TensorFlow 与 Caffe 的整合,但为了支持 Keras 已经放弃了 Caffe。您能分享您为什么会这样的原因吗?是 Caffe不再可用,还是因为 Keras 有了更多功能?
对此,Adrian Rosebrock 回应道:
是的,Keras 本身依赖于 TensorFlow、Theano、CNTK 等后端来执行实际的计算。
Caffe 仍存在,只是其他功能已经分解为 Caffe2 。TensorFlow 从未成为 Caffe 的一部分。我们仍使用 Caffe,尤其是研究人员。但从业者尤其是 Python 的从业者更喜欢编程友好的库如 TensorFlow、Keras、PyTorch 或 mxnet。
对此,你又有何疑问或看法呢?欢迎留言。
相关链接:https://www.pyimagesearch.com/2018/10/08/keras-vs-tensorflow-which-one-is-better-and-which-one-should-i-learn/
【完】