【CS231n】八、深度学习软硬件介绍

课程内容提炼:
CPU 和 GPU 硬件知识
深度学习框架:
Caffe / Caffe2
Theano / TensorFlow
Torch / PyTorch

1、CPU & GPU
总结来说就是,(众所周知)GPU适合做深度学习。
GPU,主要用NVIDIA。
GPU深度学习库,NVIDIA独占  CUDA(cuDNN)。OpenCL, 支持多种硬件,AMD给出了OpenCL转CUDA的编译器。

2、Deep Learning Framework
【CS231n】八、深度学习软硬件介绍
有趣的现象是,前沿的应用研究从高校转向工业界。

深度学习框架的意义:
(1)使搭建大型计算图更容易;
(2)使计算图的梯度(BP算法)更简单;
(3)能在GPU上更高效的运行(wrap cuDNN, cuBLAS, etc)

3、举例说明
这些框架都是python的库,通常搭配使用。

(1)Numpy
【CS231n】八、深度学习软硬件介绍

问题:没有计算梯度的函数,要自行编写。 只能run on CPU。

(2)TensorFlow
【CS231n】八、深度学习软硬件介绍

(3)PyTorch
【CS231n】八、深度学习软硬件介绍
【CS231n】八、深度学习软硬件介绍


4、TensorFlow(detial)
训练一个两层ReLU网络,随机输入,L2 Loss。
【CS231n】八、深度学习软硬件介绍

(强烈建议:可以看我的博文:最生动的TensorFlow基础概念,可以对其有快速和形象的了解)

(1)代码说明:
前半段  用来描述一张计算图; 后半段  用tf.Session()来运行这个计算图。

(2)placeholer  占位符  往往用来表示  输入输出和中间层的数据  
在搭建计算图中负责占位  在运行的阶段才进行赋值计算(输入字典型变量 如values);
(此处权重系数 也使用了  占位符; 其实实际应用中往往使用 变量Variable 类型)

(3)operation  操作符  往往用来表示  计算图中的 计算节点(Neuron)
如代码中的 tf.matmul 表示某一块输入和权重矩阵相乘。

(4)问题 与 解决方案
给 weights 赋值用的是 numpy array, 每次要复制 weight array 给 TensorFlow , 计算得到 gradients 再返回给 weight array。 也就是说要在CPU与GPU之间搬运数据(这是非常划不来的)。

所以如(2)所说,将weights通过 Variable 类型赋值,
Variable 类型 是一种 寄存在计算图中的 数据,在重复运行 同一计算图 的时候,会一直存在于计算图。(大概意思就是不会要求每次运算都需要从外界赋值(不像占位符))
同时由于是TensorFlow类型的变量,则需要通过TensorFlow来对权重进行初始化。

(而x 和 y是否也可以用variable呢?若x、y每一次调用都没有变化,是可以一直保持在TensorFlow中的,然而实际过程中,往往使用mini-batch,也就是每一次迭代中其都要输入不同的值)

【CS231n】八、深度学习软硬件介绍

原来的代码是在 计算图 外部对权重进行更新,而现在需要在计算图中,加入更新权重的operator。
【CS231n】八、深度学习软硬件介绍

【CS231n】八、深度学习软硬件介绍

这时会发现,loss函数是一条直线没有下降,原因是sess.run只调用了loss函数,而loss函数没有涉及到new_w1/2 , 而在TensorFlow中,计算图其只运行涉及到的 计算节点(node)。

方法1:返回两者的值,使其运行。然而带来的问题是,这个操作又添加了大量的CPU/GPU数据移动操作。
方法2:添加一些假的(dummy node),让 new_w1/2 和其余的计算图产生依赖关系。  
(这部分的解释不是很理解,所以这里贴上原话)其中 updates is not actually a real value. It just returns None.  技巧性在于 “tf.group returns some crazy TensorFlow value. It sort of returns some like internal TensorFlow node operation that we need to continue building the graph”当我们想要计算 updates 的 concrete value,that returns none.  产生这个效果的原因,就是tf.group() method.

【CS231n】八、深度学习软硬件介绍

这些操作仍然很繁琐,TensorFlow的强大之处就在于提供大量的函数。

使用Optimizer操作符:
【CS231n】八、深度学习软硬件介绍

使用预定义的 loss 函数:
【CS231n】八、深度学习软硬件介绍

使用Layers方法:
使用更优化的xavier初始化,程序可以(收敛)跑得更快。
这些方法,是用来帮助略过大型网络的各个细节,让设计者更专注于高层次的抽象(架构设计)
【CS231n】八、深度学习软硬件介绍


另一些代码包:
【CS231n】八、深度学习软硬件介绍


5、PyTorch
三层抽象:
(1)Tensor: just like numpy array; it can run on GPU;
(2)Variable:Node in a computational graph;store data and gradient;
(3)Module:A neural network layer; may store state or learnable weights;

(1)Tensors
import torch

dtype = torch.FloatTensor   #run on CPU
import torch

dtype = torch.cuda.FloatTensor    #run on GPU

N, D_in, H, D_out = 64, 1000, 100, 10
x = torch.randn(N, D_in).type(dtype)
y = torch.randn(N, D_out).type(dtype)
w1 = torch.randn(D_in, H).type(dtype)
w2 = torch.randn(H, D_out).type(dtype)

learning_rate = 1e-6
for t in range(500):
  h = x.mm(w1)
  h_relu = h.clamp(min = 0)
  y_pred = h_relu.mm(w2)
  loss = (y_pred - y).pow(2).sum()

  grad_y_pred = 2.0 * (y_pred - y)
  grad_w2 = h_relu.t().mm(grad_y_pred)
  grad_h_relu = grad_y_pred.mm(w2.t())
  grad_h = grad_h_relu.clone()
  grad_h[h < 0] = 0
  grad_w1 = x.t().mm(grad_h)

  w1 -= learning_rate *grad_w1
  w2 -= learning_rate *grad_w2

这段代码中,梯度部分仍然是自行编写的。
使用Autograd来求解梯度:
【CS231n】八、深度学习软硬件介绍

不同于TensorFlow,要事先搭建好计算图,pytorch每一次运行都要重新运行计算图。
也可以自己构造函数:
【CS231n】八、深度学习软硬件介绍

更高层次的抽象:
【CS231n】八、深度学习软硬件介绍

同样也提供了 optimizer:
【CS231n】八、深度学习软硬件介绍

定义高层次的模型封装:
【CS231n】八、深度学习软硬件介绍

其余太多细节,贴上来篇幅太长了。以后专门学习PyTorch的时候,再专门深入讨论。

猜你喜欢

转载自blog.csdn.net/Mys_GoldenRetriever/article/details/82113072