[infobox title="神经网络剖析"]
训练神经网络主要围绕以下四个方面。
层,多个层组合成网络(或模型)。
输入数据和相应的目标。
损失函数,即用于学习的反馈信号。
优化器,决定学习过程如何进行。
将这四者的关系可视化,如下图所示:多个层链接在一起组成了网络,将输入数据映射为预测值。然后损失函数将这些预测值与目标进行比较,得到损失值,用于衡量网络预测值与预期结果的匹配程度。优化器使用这个损失值来更新网络的权重。
[successbox title="层:深度学习的基础组件"]
神经网络的基本数据结构是层。层是一个数据处理模块,将一个或多个输入张量转换为一个或多个输出张量。有些层是无状态的,但大多数的层是有状态的,即层的权重。权重是利用随机梯度下降学到的一个或多个张量,其中包含网络的知识。
不同的张量格式与不同的数据处理类型需要用到不同的层。例如,简单的向量数据保存在形状为 (samples, features) 的 2D 张量中,通常用密集连接层[densely connected layer,也叫全连接层(fully connected layer)或密集层(dense layer),对应于 Keras 的 Dense 类]来处理。序列数据保存在形状为 (samples, timesteps, features) 的 3D 张量中,通常用循环层(recurrent layer,比如 Keras 的 LSTM 层)来处理。图像数据保存在 4D 张量中,通常用二维
卷积层(Keras 的 Conv2D)来处理。
你可以将层看作深度学习的乐高积木,Keras 等框架则将这种比喻具体化。在 Keras 中,构建深度学习模型就是将相互兼容的多个层拼接在一起,以建立有用的数据变换流程。这里层兼容性(layer compatibility)具体指的是每一层只接受特定形状的输入张量,并返回特定形状的输出张量。
from keras import layers
# 有 32 个输出单元的密集层
layer = layers.Dense(32, input_shape=(784,))
我们创建了一个层,只接受第一个维度大小为 784 的 2D 张量(第 0 轴是批量维度,其大小没有指定,因此可以任意取值)作为输入。这个层将返回一个张量,第一个维度的大小变成了 32。
因此,这个层后面只能连接一个接受 32 维向量作为输入的层。使用 Keras 时,你无须担心兼容性,因为向模型中添加的层都会自动匹配输入层的形状,例如下面这段代码。
from keras import layers
from keras import models
model = models.Sequential()
# 有 32 个输出单元的密集层
model.add(layers.Dense(32, input_shape=(784,)))
model.add(layers.Dense(32))
其中第二层没有输入形状(input_shape)的参数,相反,它可以自动推导出输入形状等于上一层的输出形状。
[/successbox]
[successbox title="模型:层构成的网络"]
深度学习模型是层构成的有向无环图。最常见的例子就是层的线性堆叠,将单一输入映射为单一输出。
但随着深入学习,你会接触到更多类型的网络拓扑结构。一些常见的网络拓扑结构如下。
双分支(two-branch)网络
多头(multihead)网络
Inception 模块
网络的拓扑结构定义了一个假设空间(hypothesis space)。你可能还记得第 1 章里机器学习的定义:“在预先定义好的可能性空间中,利用反馈信号的指引来寻找输入数据的有用表示。”选定了网络拓扑结构,意味着将可能性空间(假设空间)限定为一系列特定的张量运算,将输入数据映射为输出数据。然后,你需要为这些张量运算的权重张量找到一组合适的值。
选择正确的网络架构更像是一门艺术而不是科学。虽然有一些最佳实践和原则,但只有动手实践才能让你成为合格的神经网络架构师。后面几章将教你构建神经网络的详细原则,也会帮你建立直觉,明白对于特定问题哪些架构有用、哪些架构无用。
[/successbox]
[successbox title="损失函数与优化器:配置学习过程的关键"]
一旦确定了网络架构,你还需要选择以下两个参数。
损失函数(目标函数)——在训练过程中需要将其最小化。它能够衡量当前任务是否已成功完成。
优化器——决定如何基于损失函数对网络进行更新。它执行的是随机梯度下降(SGD)的某个变体。
具有多个输出的神经网络可能具有多个损失函数(每个输出对应一个损失函数)。但是,梯度下降过程必须基于单个标量损失值。因此,对于具有多个损失函数的网络,需要将所有损失函数取平均,变为一个标量值。
选择正确的目标函数对解决问题是非常重要的。网络的目的是使损失尽可能最小化,因此,如果目标函数与成功完成当前任务不完全相关,那么网络最终得到的结果可能会不符合你的预期。想象一下,利用 SGD 训练一个愚蠢而又无所不能的人工智能,给它一个蹩脚的目标函数:“将所有活着的人的平均幸福感最大化”。为了简化自己的工作,这个人工智能可能会选择杀死绝大多数人类,只留几个人并专注于这几个人的幸福——因为平均幸福感并不受人数的影响。这可能并不是你想要的结果!请记住,你构建的所有神经网络在降低损失函数时和上述的人工智能一样无情。因此,一定要明智地选择目标函数,否则你将会遇到意想不到的副作用。
幸运的是,对于分类、回归、序列预测等常见问题,你可以遵循一些简单的指导原则来选择正确的损失函数。例如,对于二分类问题,你可以使用二元交叉熵(binary crossentropy)损失函数;对于多分类问题,可以用分类交叉熵(categorical crossentropy)损失函数;对于回归问题,可以用均方误差(mean-squared error)损失函数;对于序列学习问题,可以用联结主义时序分类(CTC,connectionist temporal classification)损失函数,等等。只有在面对真正全新的研究问题时,你才需要自主开发目标函数。在后面几章里,我们将详细说明对于各种常见任务应选择哪种损失函数。
[/successbox]
[/infobox]
[infobox title="Keras 简介"]
。Keras 是一个 Python 深度学习框架,可以方便地定义和训练几乎所有类型的深度学习模型。Keras 最开始是为研究人员开发的,其目的在于快速
实验。
Keras 具有以下重要特性。
相同的代码可以在 CPU 或 GPU 上无缝切换运行。
具有用户友好的 API,便于快速开发深度学习模型的原型。
内置支持卷积网络(用于计算机视觉)、循环网络(用于序列处理)以及二者的任意组合。
支持任意网络架构:多输入或多输出模型、层共享、模型共享等。这也就是说,Keras能够构建任意深度学习模型,无论是生成式对抗网络还是神经图灵机。
Keras 基于宽松的 MIT 许可证发布,这意味着可以在商业项目中免费使用它。它与所有版本的 Python 都兼容(截至 2017 年年中,从 Python 2.7 到 Python 3.6 都兼容)。
Keras 已有 200 000 多个用户,既包括创业公司和大公司的学术研究人员和工程师,也包括研究生和业余爱好者。Google、Netflix、Uber、CERN、Yelp、Square 以及上百家创业公司都在用 Keras 解决各种各样的问题。Keras 还是机器学习竞赛网站 Kaggle 上的热门框架,最新的深度学习竞赛中,几乎所有的优胜者用的都是 Keras 模型。
[successbox title="Keras、TensorFlow、Theano 和 CNTK"]
Keras 是一个模型级(model-level)的库,为开发深度学习模型提供了高层次的构建模块。它不处理张量操作、求微分等低层次的运算。相反,它依赖于一个专门的、高度优化的张量库来完成这些运算,这个张量库就是 Keras 的后端引擎(backend engine)。Keras 没有选择单个张量库并将 Keras 实现与这个库绑定,而是以模块化的方式处理这个问题。因此,几个不同的后端引擎都可以无缝嵌入到 Keras 中。目前,Keras 有三个后端实现:TensorFlow 后端、Theano 后端和微软认知工具包(CNTK,Microsoft cognitive toolkit)后端。未来 Keras 可能会扩展到支持更多的深度学习引擎。
TensorFlow、CNTK 和 Theano 是当今深度学习的几个主要平台。Theano 由蒙特利尔大学的MILA 实验室开发,TensorFlow 由 Google 开发,CNTK 由微软开发。你用 Keras 写的每一段代码都可以在这三个后端上运行,无须任何修改。也就是说,你在开发过程中可以在两个后端之间无缝切换,这通常是很有用的。例如,对于特定任务,某个后端的速度更快,那么我们就可以无缝切换过去。我们推荐使用 TensorFlow 后端作为大部分深度学习任务的默认后端,因为它的应用最广泛,可扩展,而且可用于生产环境。
通过 TensorFlow(或 Theano、CNTK),Keras 可以在 CPU 和 GPU 上无缝运行。在 CPU 上运行时,TensorFlow 本身封装了一个低层次的张量运算库,叫作 Eigen;在 GPU 上运行时,TensorFlow封装了一个高度优化的深度学习运算库,叫作 NVIDIA CUDA 深度神经网络库(cuDNN)。
[/successbox]
[successbox title="使用 Keras 开发:概述"]
你已经见过一个 Keras 模型的示例,就是 MNIST 的例子。典型的 Keras 工作流程就和那个例子类似。
(1) 定义训练数据:输入张量和目标张量。
(2) 定义层组成的网络(或模型),将输入映射到目标。
(3) 配置学习过程:选择损失函数、优化器和需要监控的指标。
(4) 调用模型的 fit 方法在训练数据上进行迭代。
定义模型有两种方法:一种是使用 Sequential 类(仅用于层的线性堆叠,这是目前最常见的网络架构),另一种是函数式 API(functional API,用于层组成的有向无环图,让你可以构建任意形式的架构)。
前面讲过,这是一个利用 Sequential 类定义的两层模型(注意,我们向第一层传入了输入数据的预期形状)
from keras import models
from keras import layers
from keras import optimizers
model = models.Sequential
# Sequential 模型
model.add(layers.Dense(32, activation="relu", input_shape=(784,)))
model.add(layers.Dense(10, activation="softmax"))
# 函数式 API 定义的相同模型
# 利用函数式 API,你可以操纵模型处理的数据张量,并将层应用于这个张量,就好像这些层是函数一样。
'''
input_tensor = layers.Input(shape=(784,))
x = layers.Dense(32, activation="relu")(input_tensor)
output_tensor = layers.Dense(10, activation="softmax")(x)
model = models.Model(inputs=input_tensor, outputs=output_tensor)
'''
'''
一旦定义好了模型架构,使用 Sequential 模型还是函数式 API 就不重要了。接下来的步骤都是相同的。
配置学习过程是在编译这一步,你需要指定模型使用的优化器和损失函数,以及训练过程中想要监控的指标。
下面是单一损失函数的例子,这也是目前最常见的。
'''
# 指定模型使用的优化器和损失函数,以及训练过程中想要监控的指标。
model.compile(optimizer=optimizers.RMSprop(lr=0.001), lose="mse", metrics=["accuracy"])
# 学习过程就是通过 fit() 方法将输入数据的 Numpy 数组(和对应的目标数据)传入模型,这一做法与 Scikit-Learn 及其他机器学习库类似。
model.fit(input_tensor, target_tensor, batch_size=128, epochs=10)
[/successbox]
。。。。。。
[/infobox]
Ps:本章内容来自对《Deep Learning with Python》学习过程的记录
Comments 1 条评论
自毕业你就以此谋生.
https://bit.ly/2ZWlliV