深度学习计算
深入探索深度学习计算的关键组件, 即模型构建、参数访问与初始化、设计自定义层和块、将模型读写到磁盘, 以及利用GPU实现显著的加速。 这些知识将使你从深度学习“基础用户”变为“高级用户”。 虽然本章不介绍任何新的模型或数据集, 但后面的高级模型章节在很大程度上依赖于本章的知识。
5.1层和块
从编程的角度来看,块由类(class)表示。 它的任何子类都必须定义一个将其输入转换为输出的前向传播函数, 并且必须存储任何必需的参数。 注意,有些块不需要任何参数。 最后,为了计算梯度,块必须具有反向传播函数。 在定义我们自己的块时,由于自动微分(在 2.5节 中引入) 提供了一些后端实现,我们只需要考虑前向传播函数和必需的参数。
每个块包含的功能:
-
将输入数据作为其前向传播函数的参数。
-
通过前向传播函数来生成输出。
-
计算其输出关于输入的梯度,可通过其反向传播函数进行访问。
-
存储和访问前向传播计算所需的参数。
-
根据需要初始化模型参数。
反向传播函数或参数初始化(super().__init__()继承父类__init__), 系统将自动生成
自定义class,使用Sequential
类进行组合。如:
nn.Sequential(NestMLP()#自定义的类, nn.Linear(16, 20), FixedHiddenMLP()#自定义的类)
编程经验:控制流主要是if for while,super继承父类的初始化
5.2参数管理
-
访问参数,用于调试、诊断和可视化。
-
参数初始化。
-
在不同模型组件间共享参数。
详细介绍如何操作参数,以便模型进行复用,或者进行模型的检查(使用
Sequential类可以查看某个或者所有的参数,参数的初始化,以及实现参数绑定share层)
编程感悟:1.->的使用:表示函数return类型。如:->int,代表返回为int类型
2.var:type=value和->一样都是用来提示类型
3.参数的查看类似调用数组的数据
5.4自定义层可能
可能以后需要得层没有被定义过,需要自己定义如要实现x-x.mean的层
5.4.1不带参数的层
我们只需让层继承基础层类并实现前向传播功能。
class CenteredLayer(nn.Module): def __init__(self): super().__init__() def forward(self, X): return X - X.mean()
5.4.2带参数的层
层里的参数可以通过训练进行调整。 我们可以使用内置函数来创建参数,这些函数提供一些基本的管理功能。 比如管理访问、初始化、共享、保存和加载模型参数。 这样做的好处之一是:我们不需要为每个自定义层编写自定义的序列化程序。
class MyDense(nn.Block): def __init__(self, units, in_units, **kwargs): super().__init__(**kwargs) self.weight = self.params.get('weight', shape=(in_units, units)) self.bias = self.params.get('bias', shape=(units,)) def forward(self, x): linear = np.dot(x, self.weight.data(ctx=x.ctx)) + self.bias.data( ctx=x.ctx) return npx.relu(linear)
这个层中weight,bias为可以根据输入输出进行动态调整的参数,也可以用一个share层来实现和其他层的参数共享。
5.5读写文件
希望保存训练的模型, 以备将来在各种环境中使用。此外,当运行一个耗时较长的训练过程时, 最佳的做法是定期保存中间结果, 以确保在服务器电源被不小心断掉时,我们不会损失几天的计算结果。 因此,现在是时候学习如何加载和存储权重向量和整个模型了。
5.5.1加载和保存张量
(1)可存储单个向量
torch.save(x, 'x-file')、
(2)可存储向量列表
y = torch.zeros(4) torch.save([x, y],'x-files')
(3)可存储从字符串映射到张量的字典
mydict = {'x': x, 'y': y} torch.save(mydict, 'mydict')
5.5.2加载和保存模型参数
深度学习框架提供了内置函数来保存和加载整个网络(保存单个参数没啥用,保存全部参数太麻烦)。模型可能复杂多样,难以将模型本身序列化,但模型参数可以保存下来。为了恢复模型,我们实例化了原始多层感知机模型的一个备份。 这里我们不需要随机初始化模型参数,而是直接读取文件中存储的参数。
clone = MLP() clone.load_state_dict(torch.load('mlp.params'))
clone和初始net计算结果是一样的
5.6GPU
深度学习框架要求计算的所有输入数据都在同一设备上,无论是CPU还是GPU。
编程经验:张量可以选定在cpu或者gpu上创建(计算时cpu上的张量复制到gpu会花多余时间和内存)