cs231n笔记-深度学习软件(TensorFlow,Keras,PyTorch)

1.使用深度学习框架的三大理由:

  • 非常轻松地构建会使用一个庞大的计算图,且不需要去深入理解细节的东西
  • 框架会为我们处理反向传播的细节,这样,我们就只需要考虑网络的正向传播
  • 框架能够很好地在GPU上高效执行我们的训练(硬件透明)

2.TensorFlow

  • 示例:在随机数据上使用一个两层全连接ReLU网络 with L2损失

  • 代码:可以划分为两个部分:
    在这里插入图片描述

    1. 定义计算图:

    我们可以定义自己的计算图,这个计算图会运行数次。实际上,我们将数据输入到计算图中,可以实现任何我们想实现的运算。

    首先我们定义了X、Y、w1和w2,并且创建了它们的tf.placeeholder对象。这些变量会成为图中的输入结点,这些结点也就是图中的入口结点。当我们运行图时,会输入数据,将它们放入图的输入槽中。这和内存分配没有一点相似,我们只是为计算图建立了输入槽。

    然后我们用这些输入槽(符号变量)执行各种TensorFlow操作以便构建我们想要运行在这些变量上的计算。

    代码中,我们做了一个矩阵乘法,使用tf.maximum来实现ReLU的非线性特性,然后用另一个矩阵乘法来计算我们输出的预测结果,然后再用基本的张量运算来计算欧式距离,以及计算目标值Y和预测值之间的L2损失。

    在完成了损失值的计算之后,使用tf.gradients计算损失值在w1和w2方向上的梯度。

    需要指出的是,代码到此处并没有做任何实质上的运算,目前系统里还没有任何数据,我们只是建立计算图数据结构,告诉TensorFlow当输入真实数据时我们希望最终执行怎样的操作。因此,我们只是先建立了模型,并没有做任何操作。

    1. 多次运行计算图

    我们定义好计算图之后,进入一个TensorFlow会话,输入数据,实际运行计算图。

    首先我们需要输入具体数据给计算图。(values)

    然后我们调用sess.run进行计算,得到loss, grad_w1和grad_w2。

    这是一次计算的过程,如果我们想训练网络,我们需要将它们置入循环。
    在这里插入图片描述
    当我们每次进行前向传播,实际上是在对权重进行输入,我们将权重保存为NumPy的形式,直接将它输入到计算图。当计算图执行完毕,我们得到梯度值。这就存在一个CPU与GPU之间数据传输瓶颈的问题。对于这个问题,TensorFlow已经有了解决方案。我们将权重w1和w2定义为变量,而不是在每次前向传播时都将它们作为需要输入网络的占位符。
    在这里插入图片描述
    当权重成为了计算图的变量,我们就需要在计算图中更新权重的值。
    在这里插入图片描述
    还要告诉TensorFlow,每次计算都更新了权重,且下次计算使用新的权重。
    在这里插入图片描述

如果每次我们想要更新某个值,都必须调用tf.group函数,这是非常麻烦的,我们可以使用优化器。
在这里插入图片描述
我们给tf.train.GradientDescentOptimizer传入学习率,然后使用优化器来最小化损失。通过调用这个函数,w1和w2在默认情况下被标记为可训练,optimizer.minimize函数会进入计算图,在计算图中添加节点,用以计算关于w1和w2的损失梯度,然后执行更新、分组及分配操作。

3.Keras

在这里插入图片描述
Keras是一个建立在TensorFlow基础上的API。

4.Pytorch

PyTorch的内部明确定义了三个抽象:Tensor, Variable, Module。

  • Tensor:张量对象,类似于Numpy数组,是一种最基本的数组,与深度学习无关,但是可以在GPU上运行。
  • Variable:计算图中的节点,用于计算梯度等。
  • Module:一个神经网络层,我们可以将多个层组合起来,构建一个大的网络。

Tensor代码示例:
在这里插入图片描述
我们不再需要使用Numpy。

首先,建立一些随机数据,x,y,w1,w2。
在这里插入图片描述
然后进行前向传播。
在这里插入图片描述
然后是反向传播。
在这里插入图片描述
最后,更新权值。
在这里插入图片描述

Variable代码示例:
在这里插入图片描述
当我们从tensor转到variable,我们建立了计算图,可以自动完成梯度计算。如果x是一个variable,x.data就是一个tensor,x.grad是另一个variable,包含各种梯度。

同样的,我们先定义变量,每一次对变量的构造器的调用都封装了一个Tensor,并告诉构造器,这个变量在后续需不需要计算梯度。

前向传播的部分和利用tensor实现时的步骤一样,因为API是相同的。

然后,调用loss.backward可以得到我们需要的所有梯度值。

随后,更新权重。

Pytorch和TensorFlow有一个不同点是,在TensorFlow中,我们先构建显示的图,然后重复运行它,而在PyTorch中,我们在每次做前向传播时都要构建一个新的图。

我们可以自己定义tensor的前向和后向,来构造新的autograd函数,下例定义了一个ReLU,并在计算图中使用这个ReLU。
在这里插入图片描述
PyTorch同样提供了优化器,可以将参数的更新流程抽象出来,并执行Adam之类的更新法则。
在这里插入图片描述

5.nn

nn是PyTorch中对应Keras在TensorFlow中的包,提供一些高级封装。下面为应用示例。
在这里插入图片描述
我们可以定义自己的nn模块。通常,要写一个自己的类,这个类把整个模型定义成nn模块中的一个新的类,一个模块是神经网络的一种层,它可以包含其他的模块,或者可训练的权重或其他状态。
在这里插入图片描述
上例中,我们通过定义自己的nn模块重现这个两层网络。

在初始化时,我们定义linear1和linear2,建立新的模块对象存在类中。在前向传播时,使用自己的内部模块,也可以对变量使用任意autograd操作,来计算网络的输出。后续的操作就比较相似了。

6.dataloader

dataloader是PyTorch中一个好用的模块,它可以帮我们建立分批处理,也可以执行多线程。当我们需要执行自己的数据,我们编写自己的数据类型,dataloader可以用于读取我们的数据,打包并训练它们。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/AG9GgG/article/details/88699509
今日推荐