深度学习框架 Keras 与 PyTorch 对比
对于许多科学家、工程师和开发人员来说,TensorFlow 是他们的第一个深度学习框架。TensorFlow 1.0 于 2017 年 2 月发布,可以说,它对用户不太友好。
在过去的几年里,两个主要的深度学习库 Keras 和 PyTorch 获得了大量关注,主要是因为它们的使用比较简单。
本文将介绍 Keras 与 PyTorch 的 4 个不同点以及为什么选择其中一个库的原因。
Keras
Keras 本身并不是一个框架,而是一个位于其他深度学习框架之上的高级 API。目前它支持 TensorFlow、Theano 和 CNTK。
Keras 的优点在于它的易用性。这是迄今为止最容易上手并快速运行的框架。定义神经网络是非常直观的,因为使用 API 可以将层定义为函数。
PyTorch
PyTorch 是一个深度学习框架(类似于 TensorFlow),由 Facebook 的人工智能研究小组开发。与 Keras 一样,它也抽象出了深层网络编程的许多混乱部分。
就高级和低级代码风格而言,PyTorch 介于 Keras 和 TensorFlow 之间。比起 Keras 具有更大的灵活性和控制能力,但同时又不必进行任何复杂的声明式编程 (declarative programming)。
深度学习的从业人员整天都在纠结应该使用哪个框架。一般来说,这取决于个人喜好。但是在选择 Keras 和 PyTorch 时,你应该记住它们的几个方面。
1. 定义模型的类与函数
为了定义深度学习模型,Keras 提供了函数式 API。使用函数式 API,神经网络被定义为一系列顺序化的函数,一个接一个地被应用。例如,函数定义层 1 的输出是函数定义层 2 的输入。
img_input = layers.Input(shape=input_shape)
x = layers.Conv2D(64, (3, 3), activation='relu')(img_input)
x = layers.Conv2D(64, (3, 3), activation='relu')(x)
x = layers.MaxPooling2D((2, 2), strides=(2, 2))(x)
在 PyTorch 中,你将网络设置为一个继承自 Torch 库的 torch.nn.Module 的类。与 Keras 类似,PyTorch 提供给你将层作为构建块的能力,但是由于它们在 Python 类中,所以它们在类的 __init__() 方法中被引用,并由类的 forward() 方法执行。
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv1 = nn.Conv2d(3, 64, 3)
self.conv2 = nn.Conv2d(64, 64, 3)
self.pool = nn.MaxPool2d(2, 2)
def forward(self, x):
x = F.relu(self.conv1(x))
x = self.pool(F.relu(self.conv2(x)))
return x
model = Net()
2. 张量和计算图模型与标准数组的比较
Keras API 向普通程序员隐藏了许多混乱的细节。这使得定义网络层是直观的,并且默认的设置通常足以让你入门。
只有当你正在实现一个相当先进或'奇特'的模型时,你才真正需要深入了解底层,了解一些基本的 TensorFlow。
棘手的部分是,当你真正深入到较低级别的 TensorFlow 代码时,所有的挑战就随之而来!你需要确保所有的矩阵乘法都对齐。不要试着想打印出你自己定义的层的输出,因为你只会得到一个打印在你的终端上的没有错误的张量定义。
PyTorch 在这些方面更宽容一些。你需要知道每个层的输入和输出大小,但是这是一个比较容易的方面,你可以很快掌握它。你不需要构建一个抽象的计算图,避免了在实际调试时无法看到该抽象的计算图的细节。
PyTorch 的另一个优点是平滑性,你可以在 Torch 张量和 Numpy 数组之间来回切换。如果你需要实现一些自定义的东西,那么在 TF 张量和 Numpy 数组之间来回切换可能会很麻烦,这要求开发人员对 TensorFlow 会话有一个较好的理解。
PyTorch 的互操作实际上要简单得多。你只需要知道两种操作:一种是将 Torch 张量(一个可变对象)转换为 Numpy,另一种是反向操作。
当然,如果你从来不需要实现任何奇特的东西,那么 Keras 就会做得很好,因为你不会遇到任何 TensorFlow 的障碍。但是如果你有这个需求,那么 PyTorch 将会是一个更好的选择。
3. 训练模型
用 Keras 训练模型超级简单!只需一个简单的 .fit(),你就可以直接开始运行了。
history = model.fit_generator(
generator=train_generator,
epochs=10,
validation_data=validation_generator)
在 PyTorch 中训练模型包括以下几个步骤:
- 在每批训练开始时初始化梯度
- 前向传播
- 反向传播
- 计算损失并更新权重
# 在数据集上循环多次
for epoch in range(2):
for i, data in enumerate(trainloader, 0):
# 获取输入; data 是列表 [inputs, labels]
inputs, labels = data
# (1) 初始化梯度
optimizer.zero_grad()
# (2) 前向传播
outputs = net(inputs)
loss = criterion(outputs, labels)
# (3) 反向传播
loss.backward()
# (4) 计算损失并更新权重
optimizer.step()
光是训练就需要很多步骤!
我想这种方式你就会知道实际上发生了什么。由于这些模型训练步骤对于训练不同的模型本质上保持不变,所以这些代码实际上完全不必要的。
4. 控制 CPU 与 GPU 模式的比较
如果你已经安装了 tensorflow-gpu,那么在 Keras 中使用 GPU 是默认启用和完成的。如果希望将某些操作转移到 CPU,可以使用以下代码。
with tf.device('/cpu:0'):
y = apply_non_max_suppression(x)
对于 PyTorch,你必须显式地为每个 torch 张量和 numpy 变量启用 GPU。这将使代码变得混乱,如果你在 CPU 和 GPU 之间来回移动以执行不同的操作,则很容易出错。
例如,为了将我们之前的模型转移到 GPU 上运行,我们需要做以下工作:
# 获取 GPU 设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
# 传送网络到 GPU
net.to(device)
# 传送输入和标签到 GPU
inputs, labels = data[0].to(device), data[1].to(device)
Keras 在这方面的优势在于它的简单性和良好的默认设置。
选择框架的一般建议
我通常给出的建议是从 Keras 开始。
Keras 绝对是最容易使用、理解和快速上手并运行的框架。你不需要担心 GPU 设置,处理抽象代码,或者做任何复杂的事情。你甚至可以在不接触 TensorFlow 的任何一行的情况下实现定制层和损失函数。
如果你确实开始深入到深度网络的更细粒度方面,或者正在实现一些非标准的东西,那么 PyTorch 就是你的首选库。在 Keras 上实现反而会有一些额外的工作量,虽然不多,但这会拖慢你的进度。使用 PyTorch 能够快速地实现、训练和测试你的网络,并附带易于调试的额外好处!

