如何手写一个深度学习框架、对比tensorflow分析
本文仅对一个开源手写框架做介绍,并简要分析。
最近为了更深入得了解深度学习框架,发现网上已经有人实现了手写框架,参照其文章,尝试进行了实现。
这里记录一下实现过程和心得。并通过对比一些tensorflow框架下的特性,阐述一些自己理解。
原文的连接在此: https://borgwang.github.io/dl/2019/08/18/tinynn.html
(国内网可能无法访问)
知乎连接在此: https://zhuanlan.zhihu.com/p/78713744?utm_source=wechat_timeline
原文介绍
原文里的笔者将设计和实现一个、轻量级的(约 200 行)、易于扩展的深度学习框架 tinynn,这个框架是基于 Python 和 Numpy 实现的。
原文首先从深度学习的流程开始分析,对神经网络中的关键组件抽象,确定基本框架;然后再对框架里各个组件进行代码实现。
原文最后基于这个框架实现了一个 MNIST 分类的示例,并与 Tensorflow 做了简单的对比验证。
但该步骤,因为本人网络问题,导致MNIST数据集未下载出来,未进行验证。
设计步骤
步骤如下:
分析深度学习流程 --》 关键组件抽象 --》进行代码实现
深度学习流程分析
模型从被设计,到训练的整个周期,可以被简单理解为:网络的构建 + 损失函数的选取 + 训练。
其中的,网络的构建必定会涉及网络层(layer)的选取、前向传播、反向传播、优化器等的选取。
设置好特定的损失函数后,通过计算出每次传递的误差,传递给优化器,通过反向传播,对每层的参数进调整。
训练的时候,执行训练过程往复,达到特定的训练结要求后,就停止训练。
详细介绍见原文。
整体框架如下图所示:
对于整个框架具体的实现细节,原文阐述的很详细,我这里就不赘述了。
想要自行实现的话,可以参照原作者的github连接: https://github.com/borgwang/tinynn-autograd
但有时候,github访问不了的话,也可以参见gitee连接获取源码:https://gitee.com/aismarter/tinynn-autograd
依照相关操作,即可实现全过程。下面说一些,对标tensorflow,对这个简单小框架的体会。
对比tensorflow框架
下图,按照系统的层次结构展示了 TensorFlow 的不同层的功能和组件,也是这些构成了TensorFlow 框架下整个生态系统的核心。
当然,tensorfow开发维护者众多,原文里手写的框架,仅只相对于tensorflow的计算图层和数值计算层的实现。
之后,原文就分别实现,手写框架种的layer、loss、optimizer等模块。
实际上,就tinnyNN这个而言就只是实现了数值计算和构建网络的功能。连优化器,损失函数等都很少。当然,后边,原作者也再不断添加。
对标tensorflow,其也仅仅只是实现了数值计算层和计算图层。
在构建数值计算层上,手写框架,使用nump作为数值计算层的组件,也直接使用 numpy.ndarray 类作为 tensor 类的实现tensor 张量。而tensorflow下,我们一般较常见则使用cuDNN相关来实现计算。
在构建计算图层上,手写框架,通过自己编写的Dense类,Optimizer类等构成core组件,来实现计算图的构造、优化、执行以及前向传播和后向传播等功能。而tensorflow也是有相应的core组件,Core组件下的代码结构详情,可以上github查看。
以下是手写框架下,core组件下目录结构以及layer的相关代码。
tinynn
├── core
│ ├── __init__.py
│ ├── evaluator.py
│ ├── initializer.py
│ ├── layers.py
│ ├── losses.py
│ ├── model.py
│ ├── nn.py
│ └── optimizer.py
# layers.py
class Dense(Layer):
def __init__(self, num_in, num_out,
w_init=XavierUniformInit(),
b_init=ZerosInit()):
super().__init__("Linear")
self.params = {
"w": w_init([num_in, num_out]),
"b": b_init([1, num_out])}
self.inputs = None
def forward(self, inputs):
self.inputs = inputs
return inputs @ self.params["w"] + self.params["b"]
def backward(self, grad):
self.grads["w"] = self.inputs.T @ grad
self.grads["b"] = np.sum(grad, axis=0)
return grad @ self.params["w"].T
以下是tensorflow的core组件的目录结构。。(源码可登上github自行查阅)
可见,tensorflow对框架的计算图进行了多次封装,用以实现图构造、优化、执行等功能。但手写的框架就比较直接。
毕竟tensorflow的core是由c++实现,并大约有26万行代码。
其它说明
再次附上原文的知乎连接:https://zhuanlan.zhihu.com/p/78713744?utm_source=wechat_timeline
可以从其中了解一个框架实现的最开始的细节。
推荐阅读
-
如何手写一个深度学习框架、对比tensorflow分析
-
Tensorflow 实战Google深度学习框架——学习笔记(六)LeNet-5网络实现MNIST手写数字集识别
-
利用tensorflow深度学习框架手写数字识别
-
TensorFlow与主流深度学习框架对比 TensorFlowTensorFlow实战
-
TensorFlow与主流深度学习框架对比 TensorFlowTensorFlow实战
-
TensorFlow和Caffe、MXNet、Keras等深度学习框架的对比
-
【Tensorflow与深度学习笔记day07】5.2. ANN网络分析+Mnist手写数字识别+one-hot编码+SoftMax回归+损失计算-交叉熵损失+实现神经网络模型+模型正确率评估
-
TensorFlow和Caffe、MXNet、Keras等深度学习框架的对比