7 - Neural Network Library Abstractions
编程抽象
Caffe 1.0
一种很自然的想法,特点为:
- 没有计算图,直接定义各种层
- 每个层包括 前向计算和反向梯度计算两个函数

TensorFlow 声明式编程分格
有了计算图的概念,而不再是层。计算图和层的区别在于:
- 计算图只是简单的描述前向计算,当计算梯度的时候,将采用扩展计算图。TensorFlow 1.0为经典代表。
注:Theano才是计算图的发明创造者,tf只是代表 。

tf采用申明式计算图api,先完整的声明计算图,然后再喂进去数据运算,优势在于:
- 在运算的时候已经知道完整的的计算图了,因此可以进行优化,舍掉不必要的节点计算。例如在下图中,如果我只对v3节点感兴趣,在计算的时候,就不会计算v4节点。
- 拥有完整的计算图,可以有跟多的机会来优化计算图。
- 声明计算图和计算不必在同一台机器上面,因此可以进行可扩展的计算 (这也是为什么被google创造处tf的原因,因为可扩展性对google至关重要)
Pytorch 命令式编程分格
不仅在构建计算图,还在计算数据。且可以使用python的控制语句来构建计算图,因此称为动态计算图。
注:动态计算图是Chaner最先开始使用的,其引入了运行时定义的概念

优缺点分析
- 优化机会角度。命令式编程,失去了优化计算图的机会。而声明式就可以很好的优化,这也是为什么现在很多生产环境中还在使用 tf 的的原因。
- 编程友好角度。pytrch更为友好,可以更好的和python混合,比如 if, while 语句等;而tf ,需要专门使用tf.if及别的语句来执行相同的功能,就变得有些麻烦
- 调试代码角度。tf 不可能在定义计算图的时候 print 节点的信息,因为定义计算图的时候还不知道数据;而pytorch中,可以任意的插入 print 代码来打印节点
所以,主要是在灵活性(易用性)和优化能力之间权衡。当前,已经有不少工作使得命令式计算图的编程分格更加高效,比如及时编译,所以现在命令式的编程分格应该是首选了
High level modular library components
如何用 张量来构建神经网络?
当然可以使用底层的api,即手动计算每个Tensor来实现每一层?但这显然不是最佳实践。
回想机器学习的三大部分:模型、策略、算法。深度学习也是如此,可以据此设计模块化组件。此外,深度学习中,模型也是组件化的,如下图,从多个残差块的连接继续往下拆解,可以得到一个残差块的结构,然后继续拆解,可以得到Linear 块 和relu块,再往下,就是Tensor的连接了

上述这种组件化的设计,其基本数据结构为nn.Module。
- Tensor In Tensor out

损失函数也可以看作是特殊的模块:
- Tensor in, scalar out

然后是优化器:


然后是初始化:

然后是数据加载流水线

所有的模块
