Update programming model (#425)

This commit is contained in:
Cheng Lai
2023-03-09 16:21:00 +08:00
committed by GitHub
parent f80e6559b0
commit 3d7c502c68
6 changed files with 81 additions and 41 deletions

View File

@@ -1,6 +1,6 @@
## C/C++编程接口
上述小节中,我们讨论了开发者如何利用Python来定义机器学习的整个工作流以及如何定义复杂的深度神经网络。然而在很多时候用户也需要添加自定义的算子来帮助实现新的模型优化器数据处理函数等。这些自定义算子需要通过C和C++实现,从而获得最优性能。但是为了帮助这些算子被用户使用他们也需要暴露为Python函数从而方便用户整合入已有的Python为核心编写的工作流和模型。在这一小节中我们讨论这一过程是如何实现的。
2.2和2.3节中,分别讨论了开发者如何利用Python来定义机器学习的整个工作流以及如何定义复杂的深度神经网络。然而在很多时候开发者也需要添加自定义的算子来帮助实现新的模型优化器数据处理函数等。这些自定义算子需要通过C和C++实现,从而获得最优性能。但是为了帮助这些算子被开发者使用他们也需要暴露为Python函数从而方便开发者整合入已有的Python为核心编写的工作流和模型。在这一小节中我们讨论这一过程是如何实现的。
### 在Python中调用C/C++函数的原理

View File

@@ -4,23 +4,18 @@
:width:`800px`
:label:`img_framedh`
随着机器学习系统的诞生,如何设计易用且高性能的编程接口就一直成为了框架设计者首要解决的问题。在早期的机器学习框架中(如 :numref:`img_framedh`所示人们选择用LuaTorch和PythonTheano等高层次编程语言来编写机器学习程序。这些早期的机器学习框架提供了机器学习必须的模型定义自动微分等功能其适用于编写小型和科研为导向的机器学习应用。
随着机器学习系统的诞生,如何设计易用且高性能的API接口就一直成为了系统设计者首要解决的问题。在早期的机器学习框架中(如 :numref:`img_framedh`所示人们选择用LuaTorch和PythonTheano等高层次编程语言来编写机器学习程序。这些早期的机器学习框架提供了机器学习必须的模型定义自动微分等功能其适用于编写小型和科研为导向的机器学习应用。
在2011年深度神经网络快速崛起,很快在各个AI应用领域计算机视觉语音识别自然语言处理等)取得了最先进的性能。训练深度神经网络需要消耗大量的算力,而这些算力无法被以Lua和Python主导开发的Torch和Theano所满足。与此同时计算加速卡如英伟达GPU的通用编程接口例如CUDA
C日趋成熟而构建于CPU多核技术之上的多线程库POSIX
Threads也被广大开发者所接受。因此许多的机器学习用户希望基于C和C++来开发高性能的深度学习应用。这一类需求被Caffe等一系列以C和C++作为核心编程接口的框架所满足。
深度神经网络在2011年来快速崛起很快在各个AI应用领域计算机视觉语音识别自然语言处理等)取得了突破性的成绩。训练深度神经网络需要消耗大量的算力而以Lua和Python主导开发的Torch和Theano无法发挥这些算力的最大性能。与此同时计算加速卡如英伟达GPU的通用API接口例如CUDA C日趋成熟且构建于CPU多核技术之上的多线程库POSIX Threads也被广大开发者所接受。因此许多的机器学习用户希望基于C和C++来开发高性能的深度学习应用。这一类需求被Caffe等一系列以C和C++作为核心API的框架所满足。
然而,机器学习模型往往需要针对部署场景数据类型识别任务等需求进行深度定制而这类定制任务需要被广大的AI应用领域开发者所实现。这类开发者的背景多样,往往不具有熟练使用C和C++的背景,因此Caffe这一类与C和C++深度绑定的编程模型快速成为了制约这一类框架快速推广的巨大瓶颈。
然而,机器学习模型往往需要针对部署场景数据类型识别任务等需求进行深度定制而这类定制任务需要被广大的AI应用领域开发者所实现。这类开发者的背景多样往往不熟练使用C和C++因此Caffe这一类与C和C++深度绑定的编程框架,成为了制约框架快速推广的巨大瓶颈。
在2016年谷歌率先推出了TensorFlow。相比于传统的CaffeTorch和TheanoTensorFlow提出利用高层次编程语言Python作为面向用户的主要前端语言而利用C和C++实现高性能后端。大量基于Python的前端API确保了TensorFlow可以被大量的数据科学家和机器学习科学家接受同时帮助TensorFlow能够快速融入Python为主导的大数据生态大量的大数据开发库如NumpyPandasSciPy
Matplotlib和PySpark。同时Python具有出色的和C语言的互操作性这种互操作性已经在多个Python库中得到验证。因此TensorFlow兼有Python的灵活性和生态同时也通过C/C++后端得以实现高性能。这种设计在日后崛起的PyTorchMXNet和CNTK的机器学习框架得到传承。
在2015年底谷歌率先推出了TensorFlow。相比于传统的TorchTensorFlow提出前后端分离相对独立的设计利用高层次编程语言Python作为面向用户的主要前端语言而利用C和C++实现高性能后端。大量基于Python的前端API确保了TensorFlow可以被大量的数据科学家和机器学习科学家接受同时帮助TensorFlow能够快速融入Python为主导的大数据生态大量的大数据开发库如NumpyPandasSciPy、Matplotlib和PySpark。同时Python具有出色的和C/C++语言的互操作性这种互操作性已经在多个Python库中得到验证。因此TensorFlow兼有Python的灵活性和生态同时也通过C/C++后端得以实现高性能。这种设计在日后崛起的PyTorch、MindSpore和PaddlePaddle等机器学习框架得到传承。
随着多个机器学习框架的出现,Keras和TensorLayer等高层次机器学习开发库提供了更高层次的Python
API从而可以快速导入已有的模型
这些高层次API进一步屏蔽了底层框架的实现细节因此Keras和TensorLayer可以运行在不同的机器学习框架之上。
随着各国大型企业开源机器学习框架的出现,为了更高效地开发机器学习应用基于开源机器学习框架为后端的高层次库Keras和TensorLayerX应运而生它们提供Python API 可以快速导入已有的模型这些高层次API进一步屏蔽了机器学习框架的实现细节因此Keras和TensorLayerX可以运行在不同的机器学习框架之上。
随着深度神经网络的进一步发展对于机器学习框架编程接口的挑战也日益增长。因此在2020年前后新型的机器学习框架如MindSpore和JAX进一步出现。其中MindSpore在继承了TensorFlowPyTorch的Python和C/C++的混合接口的基础上进一步拓展了机器学习编程模型从而可以高效支持多种AI后端芯片如华为Ascend英伟达GPU和ARM芯片实现了机器学习应用在海量异构设备上的快速部署。
随着深度神经网络的进一步发展对于机器学习框架编程接口的挑战也日益增长。因此在2020年前后新型的机器学习框架如MindSpore和JAX进一步出现。其中MindSpore在继承了TensorFlowPyTorch的Python和C/C++的混合接口的基础上进一步拓展了机器学习编程模型从而可以高效支持多种AI后端芯片如华为Ascend英伟达GPU和ARM芯片实现了机器学习应用在海量异构设备上的快速部署。
同时,超大型数据集和超大型深度神经网络崛起让分布式执行成为了机器学习框架编程模型的核心设计需求。为了实现分布式执行TensorFlow和PyTorch的使用者需要进行大量编程来将数据集和神经网络分配到分布式节点上而大量的AI开发人员并不具有分布式编程的能力。因此MindSpore进一步完善了机器学习框架的分布式编程模型的能力从而让单节点的MindSpore程序可以无缝地运行在海量节点上。
同时,超大型数据集和超大型深度神经网络崛起让分布式执行成为了机器学习编程框架的核心设计需求。为了实现分布式执行TensorFlow和PyTorch的使用者需要花费大量代码来将数据集和神经网络分配到分布式节点上而大量的AI开发人员并不具有分布式编程的能力。因此MindSpore进一步完善了机器学习框架的分布式编程模型的能力从而让单节点的MindSpore程序可以无缝地运行在海量节点上。
在本小节中我们将以MindSpore作为例子讲解一个现代机器学习框架的Python前端API和C/C++后端API的设计原则。这些设计原则和PyTorchTensorFlow相似。

View File

@@ -1,8 +1,8 @@
# 编程接口
现代机器学习框架包含大量的组件。这些组件使得用户得以高效开发机器学习算法处理数据部署模型性能调优和使用硬件加速器。在设计这些组件的编程接口时一个核心的诉求是如何平衡框架性能和易用性为了达到最优的性能开发者需要利用硬件亲和的编程语言如C和C++来进行开发。这是因为C和C++的使用使得机器学习框架可以高效调用硬件底层API从而最大限度发挥硬件性能。同时现代操作系统如Linux和Windows提供丰富的基于C和C++的编程接口(如文件系统网络编程多线程管理等通过直接调用操作系统API可以降低框架运行的开销。
现代机器学习框架包含大量的组件,辅助用户高效开发机器学习算法处理数据部署模型性能调优和用硬件加速器。在设计这些组件的应用编程接口Application Programming InterfaceAPI一个核心的诉求是如何平衡框架性能和易用性为了达到最优的性能开发者需要利用硬件亲和的编程语言如C和C++来进行开发。这是因为C和C++可以帮助机器学习框架高效调用硬件底层API从而最大限度发挥硬件性能。同时现代操作系统如Linux和Windows提供丰富的基于C和C++的API接口(如文件系统网络编程多线程管理等通过直接调用操作系统API可以降低框架运行的开销。
从易用性的角度分析,机器学习框架的使用者往往具有丰富的行业背景(如数据科学家生物学家化学家物理学家等。他们常用的编程语言是高层次脚本语言PythonMatlabR和Julia。相比于C和C++,这些语言在提供编程易用性的同时丧失了C和C++对底层硬件和操作系统进行深度优化的能力。因此,机器学习框架的核心设计目标是:其要具有易用编程接口来支持用户用高层次语言如Python实现机器学习算法同时也要具备以C和C++为核心的低层次编程接口,使得框架开发者可以用C和C++实现大量高性能组件,从而在硬件上高效执行。在本章中,我们将会讲述如何达到这个设计目标。
从易用性的角度分析,机器学习框架的使用者往往具有丰富的行业背景(如数据科学家生物学家化学家物理学家等。他们常用的编程语言是高层次脚本语言PythonMatlabR和Julia。相比于C和C++这些语言在提供编程易用性的同时丧失了C和C++对底层硬件和操作系统进行深度优化的能力。因此,机器学习框架的核心设计目标是:具有易用编程接口来支持用户使用高层次语言如Python实现机器学习算法同时也要具备以C和C++为核心的低层次编程接口来帮助框架开发者用C和C++实现大量高性能组件,从而在硬件上高效执行。在本章中,讲述如何达到这个设计目标。
本章的学习目标包括:
@@ -21,5 +21,6 @@ development_history
ml_workflow
neural_network_layer
c_python_interaction
ml_programming_paradigm
summary
```

View File

@@ -0,0 +1,55 @@
## 机器学习框架的编程范式
### 机器学习框架编程需求
机器学习的训练是其任务中最为关键的一步训练依赖于优化器算法来描述。目前大部分机器学习任务都使用一阶优化器因为一阶方法简单易用。随着机器学习的高速发展软硬件也随之升级越来越多的研究者开始探索收敛性能更好的高阶优化器。常见的二阶优化器如牛顿法、拟牛顿法、AdaHessians均需要计算含有二阶导数信息的Hessian矩阵Hessian矩阵的计算带来两方面的问题一方面是计算量巨大如何才能高效计算另一方面是高阶导数的编程表达。
同时近年来工业界发布了非常多的大模型从2020年OpenAI GTP-3 175B参数开始到2021年盘古大模型100B、鹏程盘古-$\alpha$ 200B、谷歌switch transformer 1.6T、智源悟道 1.75T参数再到2022年百度ERNIE3.0 280M、Facebook NLLB-200 54B越来越多的超大规模模型训练需求使得单纯的数据并行难以满足而模型并行需要靠人工来模型切分耗时耗力如何自动并行成为未来机器学习框架所面临的挑战。最后构建机器学习模型本质上是数学模型的表示如何简洁表示机器学习模型也成为机器学习框架编程范式的设计的重点。
为了解决机器学习框架在实际应用中的一些困难,研究人员发现函数式编程能很好地提供解决方案。在计算机科学中,函数式编程是一种编程范式,它将计算视为数学函数的求值,并避免状态变化和数据可变,这是一种更接近于数学思维的编程模式。神经网络由连接的节点组成,每个节点执行简单的数学运算。通过使用函数式编程语言,开发人员能够用一种更接近运算本身的语言来描述这些数学运算,使得程序的读取和维护更加容易。同时,函数式语言的函数都是相互隔离的,使得并发性和并行性更容易管理。
因此,机器学习框架使用函数式编程设计具有以下优势:
- 支持高效的科学计算和机器学习场景。
- 易于开发并行。
- 简洁的代码表示能力。
### 机器学习框架编程范式现状
本小节将从目前主流机器学习框架发展历程来看机器学习框架对函数式编程的支持现状。谷歌在2015年发布了TensorFlow1.0其代表的编程特点包括计算图(Computational Graphs)、会话Session、张量(Tensor)它是一种声明式编程风格。2017年Facebook发布了PyTorch其编程特点为即时执行它是一种命令式编程风格。2018年谷歌发布了JAX它不是存粹为了机器学习而编写的框架而是针对GPU和TPU做高性能数据并行计算的框架与传统的机器学习框架相比其核心能力是神经网络计算和数值计算的融合在接口上兼容了NumPy、Scipy等Python原生的数据科学接口而且在此基础上扩展分布式、向量化、高阶求导、硬件加速其编程风格是函数式主要体现在无副作用、Lambda闭包等。2020年华为发布了MindSpore其函数式可微分编程架构可以让用户聚焦机器学习模型数学的原生表达。2022年PyTorch推出functorch受到谷歌JAX的极大启发functorch是一个向PyTorch添加可组合函数转换的库包括可组合的vmap向量化和autodiff转换可与PyTorch模块和PyTorch autograd一起使用并具有良好的渴望模式Eager-Mode性能functorch可以说是弥补了PyTorch静态图的分布式并行需求。
从主流的机器学习框架发展历程来看,未来机器学习框架函数式编程风格将会日益得到应用,因为函数式编程能更直观地表达机器学习模型,同时对于自动微分、高阶求导、分布式实现也更加方便。另一方面,未来的机器学习框架在前端接口层次也趋向于分层解耦,其设计不直接为了机器学习场景,而是只提供高性能的科学计算和自动微分算子,更高层次的应用如机器学习模型开发则是通过封装这些高性能算子实现。
### 函数式编程案例
在上一小节介绍了机器学习框架编程范式的现状不管是JAX、MindSpore还是functorch都提到了函数式编程,其在科学计算、分布式方面有着独特的优势。然而在实际应用中纯函数式编程几乎没有能够成为主流开发范式而现代编程语言几乎不约而同的选择了接纳函数式编程特性。以MindSpore为例MindSpore选择将函数式和面向对象编程融合兼顾用户习惯提供易用性最好编程体验最佳的混合编程范式。MindSpore采用混合编程范式道理也很简单纯函数式会让学习曲线陡增易用性变差面向对象构造神经网络的编程范式深入人心。
下面中提供了使用MindSpore编写机器学习模型训练的全流程。其网络构造满足面向对象编程习惯函数式编程主要体现在模型训练的反向传播部分MindSpore使用函数式将前向计算构造成function然后通过函数变换获得grad function最后通过执行grad function获得权重对应的梯度。
```python
# Class definition
class Net(nn.Cell):
def __init__(self):
......
def construct(self, inputs):
......
# Object instantiation
net = Net() # network
loss_fn = nn.CrossEntropyLoss() # loss function
optimizer = nn.Adam(net.trainable_params(), lr) # optimizer
# define forward function
def forword_fn(inputs, targets):
logits = net(inputs)
loss = loss_fn(logits, targets)
return loss, logits
# get grad function
grad_fn = value_and_grad(forward_fn, None, optim.parameters, has_aux=True)
# define train step function
def train_step(inputs, targets):
(loss, logits), grads = grad_fn(inputs, targets) # get values and gradients
optimizer(grads) # update gradient
return loss, logits
for i in range(epochs):
for inputs, targets in dataset():
loss = train_step(inputs, targets)
```

View File

@@ -1,19 +1,19 @@
## 机器学习工作流
机器学习系统编程模型的首要设计目标是:对开发者的整个工作流进行完整的编程支持。一个常见的机器学习任务一般包含如 :numref:`img_workflow`所示的流。这个工作流完成了训练数据集的读取模型的训练测试和调试。通过归纳我们可以将这一工作流中用户所需要自定义的部分通过定义以下API来支持我们这里假设用户的高层次API以Python函数的形式提供
机器学习系统编程模型的首要设计目标是:对开发者的整个工作流进行完整的编程支持。一个常见的机器学习任务一般包含如 :numref:`img_workflow`所示的工作流。这个工作流完成了训练数据集的读取模型的训练测试和调试。通过归纳我们可以将这一工作流中用户所需要自定义的部分通过定义以下API来支持我们这里假设用户的高层次API以Python函数的形式提供
- **数据处理:**
首先用户需要数据处理API来支持将数据集从磁盘读入。进一步用户需要对读取的数据进行预处理从而可以将数据输入后续的机器学习模型中。
- **模型结构**
完成数据的读取用户需要模型定义API来定义机器学习模型。这些模型带有模型参数可以对给定的数据进行推理。
- **模型定义**
完成数据的预处理用户需要模型定义API来定义机器学习模型。这些模型带有模型参数可以对给定的数据进行推理。
- **损失函数和优化算法**
- **优化器定义**
模型的输出需要和用户的标记进行对比这个对比差异一般通过损失函数Loss
function来进行评估。因此优化器定义API允许用户定义自己的损失函数并且根据损失来引入Import和定义各种优化算法Optimisation
algorithms来计算梯度Gradient完成对模型参数的更新。
- **训练过程**
- **训练:**
给定一个数据集模型损失函数和优化器用户需要训练API来定义一个循环Loop从而将数据集中的数据按照小批量mini-batch的方式读取出来反复计算梯度来更新模型。这个反复的过程称为训练。
- **测试和调试:**
@@ -175,7 +175,7 @@ train_net(args, model, train_epoch, mnist_path, dataset_size, ckpoint, False)
### 测试和验证
测试是模型运行测试数据集得到的结果,通常在训练过程中每训练一定的数据量后就会测试一次以验证模型的泛化能力。MindSpore使用model.eval接口读入测试数据集。
测试是测试数据集输入到模型,运行得到输出的过程。通常在训练过程中每训练一定的数据量后就会测试一次以验证模型的泛化能力。MindSpore使用model.eval接口读入测试数据集。
```python
def test_net(model, data_path):
"""定义验证的方法"""

View File

@@ -1,13 +1,13 @@
## 定义深度神经网络
在上一节我们使用MindSpore构建了一个多层感知机的网络结构随着深度神经网络的飞速发展各种深度神经网络结构层出不穷但是不管结构如何复杂神经网络层数量如何增加构建深度神经网络结构始终遵循最基本的规则1.承载计算的节点2.可变化的节点权重节点权重可训练3.允许数据流动的节点连接。因此在机器学习编程库中神经网络是以层为核心,它提供了各类神经网络层基本组件;将神经网络层组件按照网络结构进行堆叠、连接就能构造出神经网络模型。
在上一节我们使用MindSpore构建了一个多层感知机的网络结构随着深度神经网络的飞速发展各种深度神经网络结构层出不穷但是不管结构如何复杂神经网络层数量如何增加构建深度神经网络结构始终遵循最基本的元素1.承载计算的节点2.可变化的节点权重节点权重可训练3.允许数据流动的节点连接。因此在机器学习编程库中深度神经网络是以层为核心,它提供了各类深度神经网络层基本组件;将神经网络层组件按照网络结构进行堆叠、连接就能构造出神经网络模型。
### 以层为核心定义神经网络
神经网络层包含构建机器学习网络结构的基本组件,如计算机视觉领域常用到卷积(Convolution)、池化(Pooling)、全连接(Fully Connected);自然语言处理常用到循环神经网络(Recurrent Neural NetworkRNN)为了加速训练防止过拟合通常用到批标准化BatchNorm、Dropout等。
**全连接**是将当前层每个节点都和上一层节点一一连接,本质上是特征空间的线性变换;可以将数据从高维映射到低维,也能从低维映射到高维度。
:numref:`fc_layer`展示了全连接的过程对输入的n个数据变换到另一个大小为m的特征空间再从大小为m的特征空间变换到大小为p的特征空间可见全连接层的参数量巨大两次变换所需的参数大小为$n \times m$和$m \times p$。
:numref:`fc_layer`展示了全连接的过程对输入的n个数据变换到大小为m的特征空间再从大小为m的特征空间变换到大小为p的特征空间可见全连接层的参数量巨大两次变换所需的参数大小为$n \times m$和$m \times p$。
![全连接层](../img/ch02/fc_layer_1.svg)
:width:`800px`
@@ -56,7 +56,7 @@
:width:`800px`
:label:`nn_network`
有了上述基础知识,我们对卷积神经网络所需组件接口和模型构建使用伪代码描述如下:
有了上述基础知识,对卷积神经网络模型构建过程使用伪代码描述如下:
```python
# 构建卷积神经网络的组件接口定义:
全连接层接口fully_connected(input, weights)
@@ -94,26 +94,15 @@ Transformer又是BERT模型架构的重要组成。随着深度神经网络的
### 神经网络层的实现原理
3.3.1中使用伪代码定义了一些卷积神经网络接口和模型构建过程,整个构建过程需要创建训练变量和构建连接过程
随着网络层数的增加手动管理训练变量是一个繁琐的过程因此2.3.1中描述的接口在机器学习库中属于低级API。
机器学习编程库大都提供了更高级用户友好的API它将神经网络层抽象成一个基类所有的神经网络层实现都继承基类调用低级API。
如MindSpore提供的mindspore.nn.Cell、mindspore.nn.Conv2d、mindspore.dataset
PyTorch提供的torch.nn.Module、torch.nn.Conv2d、torch.utils.data.Dataset。
2.3.1中使用伪代码定义了一些卷积神经网络接口和模型构建过程,整个构建过程需要创建训练变量和构建连接过程。随着网络层数的增加手动管理训练变量是一个繁琐的过程因此2.3.1中描述的接口在机器学习库中属于低级API。机器学习编程库大都提供了更高级用户友好的API它将神经网络层抽象出一个基类所有的神经网络层都继承基类来实现如MindSpore提供的mindspore.nn.CellPyTorch提供的torch.nn.Module。基于基类他们都提供了高阶API如MindSpore 提供的mindspore.nn.Conv2d、mindspore.nn.MaxPool2d、mindspore.datasetPyTorch提供的torch.nn.Conv2d、torch.nn.MaxPool2d、torch.utils.data.Dataset。
:numref:`model_build`描述了神经网络构建过程中的基本细节。
神经网络层需要的功能有该层的训练参数(变量,包括初始化方法和训练状态)以及计算过程;
神经网络模型需要的功能是对神经网络层管理和神经网络层参数的管理。
在机器学习编程库中承担此功能有MindSpore的Cell、PyTorch的Module。
Cell和Module是模型抽象方法也是所有网络的基类。
现有模型抽象方案有两种。
一种是抽象出两个方法分别为Layer负责单个神经网络层的参数构建和前向计算Model负责对神经网络层进行连接组合和神经网络层参数管理
另一种是将Layer和Model抽象成一个方法该方法既能表示单层神经网络层也能表示包含多个神经网络层堆叠的模型Cell和Module就是这样实现的。
:numref:`model_build`描述了神经网络构建过程中的基本细节。基类需要初始化训练参数、管理参数状态以及定义计算过程神经网络模型需要实现对神经网络层和神经网络层参数管理的功能。在机器学习编程库中承担此功能有MindSpore的Cell、PyTorch的Module。Cell和Module是模型抽象方法也是所有网络的基类。现有模型抽象方案有两种一种是抽象出两个方法分别为Layer负责单个神经网络层的参数构建和前向计算Model负责对神经网络层进行连接组合和神经网络层参数管理另一种是将Layer和Model抽象成一个方法该方法既能表示单层神经网络层也能表示包含多个神经网络层堆叠的模型Cell和Module就是这样实现的。
![神经网络模型构建细节](../img/ch02/model_build.svg)
:width:`800px`
:label:`model_build`
:numref:`cell_abs`展示了设计神经网络层抽象方法的通用表示。通常在构造器会选择使用Python中collections模块的OrderedDict来初始化神经网络层和神经网络层参数的存储它的输出是一个有序的相比与Dict更适合深度学习这种模型堆叠的模式。参数和神经网络层的管理是在\_\_setattr\_\_中实现的当检测到属性是属于神经网络层及神经网络层参数时就记录起来。神经网络模型比较重要的是计算连接过程可以在\_\_call\_\_里重载实现神经网络层时在这里定义计算过程。训练参数的返回接口是为了给优化器传所有训练参数。神经网络层返回为了遍历各层神经网络得到各个神经网络层的参数。这里只列出了一些重要的方法,在自定义方法中,通常需要实现参数插入删除方法、神经网络层插入删除、神经网络模型信息
:numref:`cell_abs`展示了设计神经网络层抽象方法的通用表示。通常在构造器会选择使用Python中collections模块的OrderedDict来初始化神经网络层和神经网络层参数的存储它的输出是一个有序的相比与Dict更适合深度学习这种模型堆叠的模式。参数和神经网络层的管理是在\_\_setattr\_\_中实现的当检测到属性是属于神经网络层及神经网络层参数时就记录起来。神经网络模型比较重要的是计算连接过程可以在\_\_call\_\_里重载实现神经网络层时在这里定义计算过程。训练参数的返回接口给优化器传所有训练参数,这些参数是基类遍历了所有网络层后得到的。这里只列出了一些重要的方法,在自定义方法中,通常需要实现参数插入删除、神经网络层插入删除、神经网络模型信息返回等方法
![神经网络基类抽象方法](../img/ch02/cell_abstract.svg)
:width:`800px`
@@ -123,7 +112,7 @@ Cell和Module是模型抽象方法也是所有网络的基类。
### 自定义神经网络层
2.3.1中使用伪代码定义机器学习库中低级API有了实现的神经网络基类抽象方法那么就可以设计更高层次的接口解决手动管理参数的繁琐。假设已经有了神经网络模型抽象方法Cell构建Conv2D将继承Cell并重构\_\_init\_\_和\_\_call\_\_方法在\_\_init\_\_里初始化训练参数和输入参数在\_\_call\_\_里调用低级API实现计算逻辑。同样使用伪代码接口描述自定义卷积层的过程。
2.3.1中使用伪代码定义机器学习库中低级API有了实现的神经网络基类抽象方法那么就可以设计更高层次的接口解决手动管理参数的繁琐。假设已经有了神经网络模型抽象方法Cell构建Conv2D将继承Cell并重构\_\_init\_\_和\_\_call\_\_方法在\_\_init\_\_里初始化训练参数和输入参数在\_\_call\_\_里调用低级API实现计算逻辑。同样使用伪代码描述自定义卷积层的过程。
```python
# 接口定义:
@@ -153,7 +142,7 @@ conv = Conv2D(in_channel=10, out_channel=20, filter_size=3, stride=2, padding=0)
output = conv(input)
```
执行过程为,在初始化Conv2D时\_\_setattr\_\_会判断属性属于Cell把神经网络层Conv2D记录到self.\_cellsfilters属于parameter把参数记录到self.\_params。查看神经网络层参数使用conv.parameters_and_names查看神经网络层列表使用conv.cells_and_names执行操作使用conv(input)。
执行过程中,初始化Conv2D时\_\_setattr\_\_会判断属性属于Cell把神经网络层Conv2D记录到self.\_cells属于parameter的filters记录到self.\_params。查看神经网络层参数使用conv.parameters_and_names查看神经网络层列表使用conv.cells_and_names执行操作使用conv(input)。
### 自定义神经网络模型
@@ -191,4 +180,4 @@ class CNN(Cell):
net = CNN()
```
上述卷积模型进行实例化,其执行将从\_\_init\_\_开始第一个是Conv2DConv2D也是Cell的子类会进入到Conv2D的\_\_init\_\_此时会将第一个Conv2D的卷积参数收集到self.\_params之后回到Conv2D将第一个Conv2D收集到self.\_cells第二个的组件是MaxPool2D因为其没有训练参数因此将MaxPool2D收集到self.\_cells依次类推分别收集第二个卷积参数和卷积层,三个全连接层的参数和全连接层。实例化之后可以调用net.parameters_and_names来返回训练参数调用net.cells_and_names查看神经网络层列表。
上述卷积模型进行实例化,其执行将从\_\_init\_\_开始第一个是Conv2DConv2D也是Cell的子类会进入到Conv2D的\_\_init\_\_此时会将第一个Conv2D的卷积参数收集到self.\_params之后回到Conv2D将第一个Conv2D收集到self.\_cells第二个的组件是MaxPool2D因为其没有训练参数因此将MaxPool2D收集到self.\_cells依次类推分别收集第二个卷积层的参数和层信息以及三个全连接层的参数和层信息。实例化之后可以调用net.parameters_and_names来返回训练参数调用net.cells_and_names查看神经网络层列表。