4.5. 读取和存储
到目前为止,我们介绍了如何处理数据以及如何构建、训练和测试深度学习模型。然而在实际中,我们有时需要把训练好的模型部署到很多不同的设备。在这种情况下,我们可以把内存中训练好的模型参数存储在硬盘上供后续读取使用。
4.5.1. 读写NDArray
我们可以直接使用save
函数和load
函数分别存储和读取NDArray
。下面的例子创建了NDArray
变量x
,并将其存在文件名同为x
的文件里。
- In [1]:
- from mxnet import nd
- from mxnet.gluon import nn
- x = nd.ones(3)
- nd.save('x', x)
然后我们将数据从存储的文件读回内存。
- In [2]:
- x2 = nd.load('x')
- x2
- Out[2]:
- [
- [1. 1. 1.]
- <NDArray 3 @cpu(0)>]
我们还可以存储一列NDArray
并读回内存。
- In [3]:
- y = nd.zeros(4)
- nd.save('xy', [x, y])
- x2, y2 = nd.load('xy')
- (x2, y2)
- Out[3]:
- (
- [1. 1. 1.]
- <NDArray 3 @cpu(0)>,
- [0. 0. 0. 0.]
- <NDArray 4 @cpu(0)>)
我们甚至可以存储并读取一个从字符串映射到NDArray
的字典。
- In [4]:
- mydict = {'x': x, 'y': y}
- nd.save('mydict', mydict)
- mydict2 = nd.load('mydict')
- mydict2
- Out[4]:
- {'x':
- [1. 1. 1.]
- <NDArray 3 @cpu(0)>, 'y':
- [0. 0. 0. 0.]
- <NDArray 4 @cpu(0)>}
4.5.2. 读写Gluon模型的参数
除NDArray
以外,我们还可以读写Gluon模型的参数。Gluon的Block
类提供了save_parameters
函数和load_parameters
函数来读写模型参数。为了演示方便,我们先创建一个多层感知机,并将其初始化。回忆“模型参数的延后初始化”一节,由于延后初始化,我们需要先运行一次前向计算才能实际初始化模型参数。
- In [5]:
- class MLP(nn.Block):
- def __init__(self, **kwargs):
- super(MLP, self).__init__(**kwargs)
- self.hidden = nn.Dense(256, activation='relu')
- self.output = nn.Dense(10)
- def forward(self, x):
- return self.output(self.hidden(x))
- net = MLP()
- net.initialize()
- X = nd.random.uniform(shape=(2, 20))
- Y = net(X)
下面把该模型的参数存成文件,文件名为mlp.params。
- In [6]:
- filename = 'mlp.params'
- net.save_parameters(filename)
接下来,我们再实例化一次定义好的多层感知机。与随机初始化模型参数不同,我们在这里直接读取保存在文件里的参数。
- In [7]:
- net2 = MLP()
- net2.load_parameters(filename)
因为这两个实例都有同样的模型参数,那么对同一个输入X
的计算结果将会是一样的。我们来验证一下。
- In [8]:
- Y2 = net2(X)
- Y2 == Y
- Out[8]:
- [[1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]
- [1. 1. 1. 1. 1. 1. 1. 1. 1. 1.]]
- <NDArray 2x10 @cpu(0)>
4.5.3. 小结
- 通过
save
函数和load
函数可以很方便地读写NDArray
。 - 通过
load_parameters
函数和save_parameters
函数可以很方便地读写Gluon模型的参数。
4.5.4. 练习
- 即使无须把训练好的模型部署到不同的设备,存储模型参数在实际中还有哪些好处?