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语句,该语句用于处理由用户发起的键盘中断(例如用户按下了 Ctrl+C\mathrm{Ctrl} + \mathrm{C} 键)。在这种情况(在保存过程中收到了中断信号的情况)下,正在保存的文件会被删除,由此可以防止创建(和加载)不完整状态的文件。

下面以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和测试模式

过拟合是神经网络中常见的问题。过拟合发生的主要原因有以下几点。

  1. 训练数据少

  2. 模型的表现力太强

针对第一个原因,我们可以采取的措施有增加数据或使用数据增强(data augmentation)。

针对第二个原因,可以采取的措施有权重衰减(weight decay)、Dropout(参考文献[34])和批量正则化(batch normalization)(参考文献[35])。尤其是Dropout这种方法简单又有效,在实践中经常被使用。因此,本步骤会将Dropout添加到DeZero中。此外,在训练和测试时需要改变Dropout的处理,所以本步骤还会创建区分训练阶段和测试阶段的机制。

53.3_Layer 类的 save 函数和 load 函数 - 深度学习自制框架 | OpenTech