zoukankan      html  css  js  c++  java
  • 深度学习框架Keras与Pytorch对比

    640?wx_fmt=png

    对于许多科学家、工程师和开发人员来说,TensorFlow是他们的第一个深度学习框架。TensorFlow 1.0于2017年2月发布,可以说,它对用户不太友好。

    在过去的几年里,两个主要的深度学习库KerasPytorch获得了大量关注,主要是因为它们的使用比较简单。

    本文将介绍Keras与Pytorch的4个不同点以及为什么选择其中一个库的原因。

    Keras

    Keras本身并不是一个框架,而是一个位于其他深度学习框架之上的高级API。目前它支持TensorFlow、Theano和CNTK。

    Keras的优点在于它的易用性。这是迄今为止最容易上手并快速运行的框架。定义神经网络是非常直观的,因为使用API可以将层定义为函数。

    Pytorch

    Pytorch是一个深度学习框架(类似于TensorFlow),由Facebook的人工智能研究小组开发。与Keras一样,它也抽象出了深层网络编程的许多混乱部分。

    就高级和低级代码风格而言,Pytorch介于Keras和TensorFlow之间。比起Keras具有更大的灵活性和控制能力,但同时又不必进行任何复杂的声明式编程(declarative programming)。

    深度学习的从业人员整天都在纠结应该使用哪个框架。一般来说,这取决于个人喜好。但是在选择Keras和Pytorch时,你应该记住它们的几个方面。

    640?wx_fmt=jpeg

    (1)定义模型的类与函数

    为了定义深度学习模型,Keras提供了函数式API。使用函数式API,神经网络被定义为一系列顺序化的函数,一个接一个地被应用。例如,函数定义层1( function defining layer 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)训练模型

    640?wx_fmt=jpeg

    用Keras训练模特超级简单!只需一个简单的.fit(),你就可以直接去跑步了。

    history = model.fit_generator(
        generator=train_generator,
        epochs=10,
        validation_data=validation_generator)
    

    在Pytorch中训练模型包括以下几个步骤:

    1. 在每批训练开始时初始化梯度

    2. 前向传播

    3. 反向传播

    4. 计算损失并更新权重

    # 在数据集上循环多次
    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模式的比较

    640?wx_fmt=jpeg

    如果你已经安装了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能够快速地实现、训练和测试你的网络,并附带易于调试的额外好处!

    欢迎关注磐创博客资源汇总站:
    http://docs.panchuang.net/

    欢迎关注PyTorch官方中文教程站:
    http://pytorch.panchuang.net/

  • 相关阅读:
    神秘现象?多种情况比较
    [备忘]C++BUILDER的文件操作
    缘起
    [备忘]一个二维数组的冒泡排序
    无可救药地买入NDSL
    递归的实质
    [网游计划第九、十天]能力有限,做些小品
    大学有救
    struts2+convertion实现struts.xml的零配置
    BSD下的超级终端
  • 原文地址:https://www.cnblogs.com/panchuangai/p/12568012.html
Copyright © 2011-2022 走看看