53.3_Layer 类的 save 函数和 load 函数
53.3 Layer类的save函数和load函数
到这里,我们就完成了将Layer类的参数保存到外部文件的准备。下面添加新方法save_weights和load_weights。
dezero/layers.py
import os
class Layer: def saveweights(self, path): self.to_cpu() params_dict $=$ {} self._ flatten.paramsparams_dict) array_dict $=$ {key: param.data for key, param in params_dict/items() if param is not None} try: np.savez_compressed(path, \*\*array_dict) except (Exception, KeyboardInterrupt) as e: if os.path.exists(path): os.remove(path) raise def loadweights(self, path): npz $=$ np.load(path) params_dict $=$ {} self._ flatten.paramsparams_dict) for key, param in params_dict.items(): param.data $=$ npz[key]save_weights方法首先通过self.to_cpu()确保数据在主内存中(数据是NumPy的ndarray),然后创建保存ndarray实例的值的字典(array_dict),之后使用np.savez_compressed函数将数据保存为外部文件。loadweights方法使用np.load函数来加载数据,并将相应键的数据设置为参数。

上面的代码在保存文件时使用了try语句,该语句用于处理由用户发起的键盘中断(例如用户按下了 键)。在这种情况(在保存过程中收到了中断信号的情况)下,正在保存的文件会被删除,由此可以防止创建(和加载)不完整状态的文件。
下面以MNIST的训练为例保存和加载参数。代码如下所示
steps/step53.py
import os
importdezero
importdezero-functions as F
fromdezero import optimizers
fromdezero import DataLoader
fromdezero.models import MLP
max_epoch $= 3$
batch_size $= 100$
train_set $\equiv$ dezero.datasets.MNIST(train=True)
trainloader $\equiv$ DataLoader(train_set,batch_size)
model $=$ MLP((1000,10))
optimizer $=$ optimizers.SGD().setup(model)加载参数
if os.path.exists('my_mlp.npz'): model.loadweights('my_mlp.npz')
for epoch in range(max_epoch): sum_loss $= 0$ for $\mathbf{X}$ ,t in trainloader: y $=$ model(x) loss $=$ Fsoftmaxcross_entropy(y,t) model.cleargrads() loss/backward() optimizer.update() sum_loss $+ =$ float(loss.data)\*len(t) print('epoch:{},loss:{:.4f}'.format( epoch $^+$ 1,sum_loss / len(train_set)))
model.save_weights('my_mlp.npz')首次运行上面的代码时,my_mlp.npz文件并不存在,所以和往常一样,我们让模型的参数在随机初始化的状态下开始训练,最后通过model.saveweights('my_mlp.npz')保存模型的参数。
再次运行上面的代码时,my_mlp.npz文件已经存在,该文件会被加载。由此,之前训练得到的参数会赋给模型。到这里,我们就实现了保存和加载模型参数的功能。
步骤54
Dropout和测试模式
过拟合是神经网络中常见的问题。过拟合发生的主要原因有以下几点。
训练数据少
模型的表现力太强
针对第一个原因,我们可以采取的措施有增加数据或使用数据增强(data augmentation)。
针对第二个原因,可以采取的措施有权重衰减(weight decay)、Dropout(参考文献[34])和批量正则化(batch normalization)(参考文献[35])。尤其是Dropout这种方法简单又有效,在实践中经常被使用。因此,本步骤会将Dropout添加到DeZero中。此外,在训练和测试时需要改变Dropout的处理,所以本步骤还会创建区分训练阶段和测试阶段的机制。