(七)快速搭建法
Sequential 本质是一个模块(即 Module),根据Pytorch中的约定,模块中可以继续添加模块。
这意味着我们可以在 Sequential 中添加其它的模块(自然也就可以添加其他的 Sequential)。
添加完成后,Sequential 会将这些模块组成一个流水线,输入将依次通过这些模块得到一个输出。
(八)保存提取
1.保存并恢复全网络:
这种方式很简单,不需要再构造一个网络,直接net2=torch.load(‘net.pkl’)(名字要和保存的一致)。
2.只保存并恢复参数:
这种方式则需要构建一个层数,神经元数一致的网络。
之后再net2.load_state_dict(torch.load(‘net_params.pkl’))即可。
state_dict()将layer_name : layer_param的键值信息存储为dict形式。
load_state_dict是使用反序列化的state_dict加载模型的参数字典,用来加载模型参数。(load_state_dict函数的参数是字典对象,而不是保存对象的路径)
格式:torch.nn.Module.load_state_dict(state_dict, strict=True)
对net123用完全相同的方式训练100步,并进行可视化。
运行程序并验证,发现三张图完全一致。
(九)批训练(mini-batch training)
首先介绍一下import torch.utils.data as Data,这在训练过程中基本都会用到。该接口大多用来读取数据和把数据封装成Tensor,之后的DataLoader用来做mini-batch训练。
DataLoader 是 torch 给我们用来包装数据的工具。
所以要将自己的 (numpy array 或其他) 数据形式装换成 Tensor, 然后再放进这个包装器中。使用 DataLoader 的好处是:他们帮你有效地迭代数据。
TensorDataset 基于一系列张量构建数据集。这些张量的形状可以不尽相同,但第一个维度必须具有相同大小。( TensorDataset 将张量的第一个维度视为数据集大小的维度,数据集在传入 DataLoader 后,该维度也是 batch_size 所在的维度)
实际上还有第五个参数drop_last: 当样本数不能被batchsize整除时, 是否舍弃最后一批数据。(默认不舍弃)
DataLoader构建可迭代的数据装载器,我们在训练的时候,每一个for循环,每一次iteration(迭代),就是从DataLoader中获取一个batch_size大小的数据的。
Epoch: 所有训练样本都已输入到模型中,称为一个Epoch。
Iteration(step): 一批样本输入到模型中,称为一个Iteration。
Batchsize: 一批样本的大小, 决定一个Epoch有多少个Iteration。
例:假设样本总数80, Batchsize是8, 那么1Epoch=10Iteration。 假设样本总数是87, Batchsize是8, 如果drop_last=True, 那么1Epoch=10Iteration;如果等于False, 那么1Epoch=11Iteration, 最后1个Iteration有7个样本。
enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标。
输出结果如下:
若将BATCH_SIZE改为8,则结果如下:
多次运行上述代码,发现结果均一致,而不是随机的。
这是因为我们在程序开头加入了这句:
torch.manual_seed()手动设置种子,一般可用于固定随机初始化的权重值(一旦固定种子,后面依次生成的随机数其实都是固定的)
这样就可以让每次重新训练网络时的权重的初始值虽然是随机生成的,但结果却是固定的。
(十)加速神经网络训练 (Speed Up Training)
深度学习的优化算法主要有GD,SGD,Momentum,RMSProp和Adam算法等。
深度学习中绝大多数目标函数都很复杂。因此,很多优化问题并不存在解析解,而需要使用基于数值方法的优化算法找到近似解,即数值解。以下讨论的优化算法都是这类基于数值方法的算法。
1.SGD(随机梯度下降)
如果使用梯度下降(GD),每次自变量迭代的计算开销为O(n),它随着n线性增长。因此,当训练数据样本数很大时,梯度下降每次迭代的计算开销很高。
而随机梯度下降(stochastic gradient descent,SGD)减少了每次迭代的计算开销。在随机梯度下降的每次迭代中,我们随机均匀采样的一个样本索引i∈{1,…,n},并计算梯度∇fi(x)来迭代x。于是每次迭代的计算开销从梯度下降的O(n)降到了常数O(1)。
我们还可以在每轮迭代中随机均匀采样多个样本来组成一个小批量,然后使用这个小批量来计算梯度。称为小批量随机梯度下降。通常,小批量随机梯度在每个迭代周期的耗时介于梯度下降和随机梯度下降的耗时之间。
2.Momentum(动量法)
在SGD的每次迭代中,梯度下降根据自变量当前位置,沿着当前位置的梯度更新自变量。然而,如果自变量的迭代方向仅仅取决于自变量当前位置,这可能会带来一些问题。
同一位置上,目标函数在竖直方向比在水平方向的斜率的绝对值更大。因此,给定学习率,梯度下降迭代自变量时会使自变量在竖直方向比在水平方向移动幅度更大。
动量法依赖指数加权移动平均(exponentially weighted moving average)使得自变量的更新方向更加一致,从而降低发散的可能。
其中,动量超参数γ满足0≤γ<1。当γ=0时,动量法等价于小批量随机梯度下降。
3. AdaGrad
AdaGrad算法根据自变量在每个维度的梯度值的大小来调整各个维度上的学习率,并让目标函数自变量中每个元素都分别拥有自己的学习率,从而避免统一的学习率难以适应所有维度的问题。
ϵ是为了维持数值稳定性而添加的常数,如10−6。
因为调整学习率时分母上的变量st一直在累加按元素平方的小批量随机梯度,所以目标函数自变量每个元素的学习率在迭代过程中一直在降低(或不变)。因此,当学习率在迭代早期降得较快且当前解依然不佳时,AdaGrad算法在迭代后期由于学习率过小,可能较难找到一个有用的解。
4. RMSProp
RMSProp算法对AdaGrad算法做了一点小小的修改。
不同于AdaGrad算法里状态变量st是截至时间步t所有小批量随机梯度gt按元素平方和,RMSProp算法将这些梯度按元素平方做指数加权移动平均。
RMSProp同时具备Momentum& AdaGrad两种方法的优势。
但我们还没把 Momentum合并完全, RMSProp 缺少了 Momentum 中的红框部分。
5. Adam
Adam方法的基本思路更像是融合Momentum和AdaGrad二者的优点, Adam算法在RMSProp算法的基础上对小批量随机梯度也做了指数加权移动平均。
Adam的优点主要在于经过偏置校正(使过去各时间步小批量随机梯度权值之和为1)后,每一次迭代学习率都有个确定范围,使得参数比较平稳。
大多数时候, 使用 Adam 都能又快又好的达到目标, 迅速收敛。
补充:Optimizer 优化器
zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象。