Deep Learning Systems Lecture 7 Neural Network Library Abstractions
这里回顾dlsys第七讲,本讲内容是神经网络库抽象。
课程主页:
大纲
- 编程抽象;
- 高级模块化库组件;
编程抽象
- 框架的编程抽象定义了实现、扩展和执行模型计算的常用方法;
- 虽然设计的选择在看到实际实现之后可能看起来很明显,但了解思考过程很有用,因为:
- 我们可以了解为什么要这样设计抽象;
- 以及学习如何设计新的抽象;
案例分析
主要从对3个框架进行分析,分别是Caffe 1.0, TensorFlow 1.0以及PyTorch:
Forward和backward层接口(Caffe 1.0)
Caffe 1.0:
定义前向计算和后向(梯度)操作,用于cuda-convenet(AlexNet框架):
class Layer:
def forward(bottom, top):
pass
def backward(top,
propagate_down,
bottom):
pass
计算图和声明式编程(Tensorflow 1.0)
首先声明计算图,然后通过输入值执行图:
import tensorflow as tf
v1 = tf.Variable()
v2 = tf.exp(v1)
v3 = v2 + 1
v4 = v2 * v3
sess = tf.Session()
value4 = sess.run(v4, feed_dict={v1: numpy.array([1]})
命令式自动微分(Pytorch, needle)
import needle as ndl
v1 = ndl.Tensor([1])
v2 = ndl.exp(v1)
v3 = v2 + 1
v4 = v2 * v3
在我们构造计算图时执行计算,允许轻松混合python控制流:
if v4.numpy() > 0.5:
v5 = v4 * 2
else:
v5 = v4
v5.backward()
高级模块化库组件
机器学习元素
机器学习的三要素为:
- 假设函数类;
- 损失函数;
- 优化方法;
问题:它们如何转化为代码中的模块化组件。
深度学习本质上是模块化的
nn.Module
:将部件组合在一起
说明:
- 输入输出都为tensor;
需要考虑的关键点:
- 对于给定的输入,如何计算输出;
- 获取(可训练的)参数列表;
- 初始化参数的方法;
损失函数作为一种特殊的模块
说明:
- 输入为标量,输出为tensor;
问题:
- 如何将多个目标函数组合在一起?
- 在训练后的推理时间内会发生什么?
优化器
优化器:
- 从模型中获取权重列表,执行优化步骤;
- 跟踪辅助状态(动量);
SGD:
正则化和优化器
合并正则化的两种方法:
- 作为损失函数的一部分实现;
- 直接合并为优化器更新的一部分;
例如带有$l_2$正则化的SGD更新方式为:
初始化
初始化策略取决于所涉及的模块和参数的类型。 大多数神经网络库都有一组通用的初始化方法:
- 权重:均匀分布,数量级取决于输入/输出;
- bias:零;
- 方差和:1;
初始化可以合并到nn.module
的构造阶段。
Data loader和预处理
- 我们经常通过随机打乱和转换输入来预处理(扩充)数据集;
- 数据增强是深度学习模型中预测准确性提升的重要部分;
- 数据加载和扩充本质上也是可组合的;
深度学习本质上是模块化的
回顾编程抽象
在Caffe 1.0的例子中,耦合了梯度计算与模块:
class Layer:
def forward(bottom, top):
pass
def backward(top,
propagate_down,
bottom):
pass
在Pytorch(needle)中至少有两层抽象:Tensors层面的计算图抽象,用来处理AD;高层次的抽象处理模块化组合:
import needle as ndl
v1 = ndl.Tensor([1])
v2 = ndl.exp(v1)
v3 = v2 + 1
v4 = v2 * v3
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Doraemonzzz!
评论
ValineLivere