读取和存储 讨论区

http://zh.diveintodeeplearning.org/chapter_deep-learning-computation/read-write.html

1赞

在save时出现这样的错误,请问需要怎么处理?
MXNetError Traceback (most recent call last)
in ()
4 y = nd.zeros(4)
5 filename = “data/test1.params”
----> 6 nd.save(filename, [x,y])

C:\Program Files\Anaconda3\lib\site-packages\mxnet\ndarray\utils.py in save(fname, data)
246 mx_uint(len(handles)),
247 c_array(NDArrayHandle, handles),
–> 248 keys))

C:\Program Files\Anaconda3\lib\site-packages\mxnet\base.py in check_call(ret)
141 “”"
142 if ret != 0:
–> 143 raise MXNetError(py_str(_LIB.MXGetLastError()))
144
145 if sys.version_info[0] < 3:

MXNetError: [10:18:18] C:\projects\mxnet-distro-win\mxnet-build\dmlc-core\src\io\local_filesys.cc:154: Check failed: allow_null LocalFileSystem: fail to open “data/test1.params”

应该是当前目录下没有data文件夹,或者对这个文件夹没有写权限的原因

谢谢文档!请问序列化模型结构应该怎么做?

对于原先CPU跑的模型参数,是否可以用
net2 = get_net()
net2.load_params(filename, mx.gpu()) 把模型载入GPU重新跑?
我的电脑报错,---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
in ()
2 net2 = get_net()
3 net2.load_params(filename, mx.gpu()) # FIXME, gluon will support default ctx later
----> 4 print(net2(x))

~/anaconda3/lib/python3.6/site-packages/mxnet/gluon/block.py in call(self, *args)
288 def call(self, *args):
289 “”“Calls forward. Only accepts positional arguments.”""
–> 290 return self.forward(*args)
291
292 def forward(self, *args):

~/anaconda3/lib/python3.6/site-packages/mxnet/gluon/nn/basic_layers.py in forward(self, x)
48 def forward(self, x):
49 for block in self._children:
—> 50 x = block(x)
51 return x
52

~/anaconda3/lib/python3.6/site-packages/mxnet/gluon/block.py in call(self, *args)
288 def call(self, *args):
289 “”“Calls forward. Only accepts positional arguments.”""
–> 290 return self.forward(*args)
291
292 def forward(self, *args):

~/anaconda3/lib/python3.6/site-packages/mxnet/gluon/block.py in forward(self, x, *args)
466 return self._call_cached_op(x, *args)
467 try:
–> 468 params = {i: j.data(ctx) for i, j in self._reg_params.items()}
469 except DeferredInitializationError:
470 self.infer_shape(x, *args)

~/anaconda3/lib/python3.6/site-packages/mxnet/gluon/block.py in (.0)
466 return self._call_cached_op(x, *args)
467 try:
–> 468 params = {i: j.data(ctx) for i, j in self._reg_params.items()}
469 except DeferredInitializationError:
470 self.infer_shape(x, *args)

~/anaconda3/lib/python3.6/site-packages/mxnet/gluon/parameter.py in data(self, ctx)
359 NDArray on ctx
360 “”"
–> 361 return self._check_and_get(self._data, ctx)
362
363 def list_data(self):

~/anaconda3/lib/python3.6/site-packages/mxnet/gluon/parameter.py in _check_and_get(self, arr_list, ctx)
148 else:
149 ctx = context.current_context()
–> 150 idx = self._ctx_map[ctx.device_typeid][ctx.device_id]
151 if idx is not None:
152 return arr_list[idx]

IndexError: list index out of range

net2.load_params(filename, mx.cpu())不报错

各位大佬好,这里保存读取模型参数不是太明白:x = nd.random.uniform(shape=(2,10)) 通过get_net()函数转换net(x)得到shape=(2,2)的数据保存,
net.add(nn.Dense(10, activation=“relu”))
net.add(nn.Dense(2))
相当于加了2个隐藏层,

1 那这2个隐藏层系数在这个例子中是随机的吗?

读取时也需要定义x = nd.random.uniform(shape=(2,10)) 传入net(x),为什么读取模型数据也要定义x成随机数?只是读取数据最多定义下shape吧(但是我的想法不行),我定义x = nd.ones(shape=(2, 10))和定义x = nd.random.uniform(shape=(2,10)) 读取的数不一样,但是读取时x = nd.ones(shape=(2, 10)) 多次运行取得值又是一样的。

2 保存和读取时x的定义有什么关系吗?必须一样吗?

保存的是模型里面的参数,不包括输入 x

1赞

请教一下 block里的__init__()函数,在name_scope()里保存的变量和之外的有什么区别啊

name_scope主要是保证每个变量名字是unique,save/load的时候安全些

3赞

HybridBlock是怎么进行hybridize化的啊
我看到有个self._children
我们该怎么把层放进去啊

def train(train_data, test_data, net, loss, trainer, ctx, num_epochs, print_batches=None):
""“Train a network”""
print("Start training on ", ctx)
if isinstance(ctx, mx.Context):
ctx = [ctx]
for epoch in range(num_epochs):
train_loss, train_acc, n, m = 0.0, 0.0, 0.0, 0.0
if isinstance(train_data, mx.io.MXDataIter):
train_data.reset()
start = time()
for i, batch in enumerate(train_data):
data, label, batch_size = _get_batch(batch, ctx)
losses = []
with autograd.record():
outputs = [net(X) for X in data]
losses = [loss(yhat, y) for yhat, y in zip(outputs, label)]
for l in losses:
l.backward()
train_acc += sum([(yhat.argmax(axis=1)==y).sum().asscalar()
for yhat, y in zip(outputs, label)])
train_loss += sum([l.sum().asscalar() for l in losses])
trainer.step(batch_size)
n += batch_size
m += sum([y.size for y in label])
if print_batches and (i+1) % print_batches == 0:
print(“Batch %d. Loss: %f, Train acc %f” % (
n, train_loss/n, train_acc/m
))

    test_acc = evaluate_accuracy(test_data, net, ctx)
    print("Epoch %d. Loss: %.3f, Train acc %.2f, Test acc %.2f, Time %.1f sec" % (
        epoch, train_loss/n, train_acc/m, test_acc, time() - start
    ))

    net.save_params('%d-%f.params'%(epoch,test_acc))

    net.export('e2e')

使用例子:http://zh.gluon.ai/chapter_computer-vision/fine-tuning.html 进行微调,在utils文件中增加了:`net.save_params(’%d-%f.params’%(epoch,test_acc))

    net.export('e2e')`

但是报错:ValueError: Prefix densenet1_ is to be striped before saving, but Parameter densenet0_conv0_weight does not start with densenet1_.,有些方法说改成net.collect_params().save('%d-%f.params'%(epoch,test_acc))这样是可以保存成功,但是加载模型却出现错误:arg_type, name = k.split(':', 1) ValueError: need more than 1 value to unpack

测试代码:sym1 = mx.symbol.load('e2e-symbol.json') mod1 = mx.mod.Module(symbol=sym1, context=mx.cpu(),label_names=['softmax_label']) #mod1 = models.densenet201(classes=6) mod1.bind(for_training=False, data_shapes=[('data', (1, 3, 224, 224))]) mod1.load_params('e2e-0010.params')

不知道什么原因,感觉gluon对于保存模型和使用保存好的模型不是那么好用,对于上面的问题都不能很快的找到答案。
文档http://zh.gluon.ai/chapter_gluon-basics/serialization.html里面也确实是用net.save_params(filename)求解答

net.export(‘e2e’) 会生成两个文件,e2e-0000.parmas 和e2e-symbol.json
可以通过以下代码进行测试:
sym1, arg_params1, aux_params1 = mx.model.load_checkpoint('e2e', 0)
mod1 = mx.mod.Module(symbol=sym1, context=mx.cpu(), data_names=['data'], label_names=['softmax_label'])
mod1.bind(for_training=False, data_shapes=[(‘data’, (1, 3, 224, 224))])
mod1.set_params(arg_params1, aux_params1)

呃。。。沐神,我感觉好像没啥用啊。
比方说我写了下面一段代码:
net1=gluon.nn.Sequential(prefix=‘test’)
net2=gluon.nn.Sequential(prefix=‘test’)
with net1.name_scope():
net1.add(gluon.nn.Dense(10))
with net2.name_scope():
net2.add(gluon.nn.Dense(10))
print(net1[0].name)
print(net2[0].name)

最后的输出为:
testdense0
testdense0
它们的前缀名字可以是相同的,也就是说在系统里面并不是第一无二的。
不知道是不是我写的代码有问题。。或者对gluon的理解有问题

各位老师好,对于如下一个网络模型

def get_net():
net = nn.Sequential()
with net.name_scope():
net.add(nn.Dense(10))
net.add(nn.Dense(2))
return net

net = get_net()
net.initialize()
x = nd.random.uniform(shape=(3,20))
print(net(x))

输入的x 是3*20 矩阵,运行如下代码:

params = net.collect_params()
w0 = net[0].weight.data()
w1 = net[1].weight.data()
print(w0.shape)
print(w1.shape)
打印的w0 和w1分别是
(10L, 20L)
(2L, 10L)

这里 x和 W0 进行的是 dot,w0 为什么不是20*10呢?

我也报相同的Error; 求教是怎么解决的?
jupyter文件的工作目录:D:\jupyter\,我新建了data文件夹:D:\jupyter\data
修改了权限支持读写和修改。

重新跑一遍,还是报错。

报的是什么错?还有方便分享下你的环境和版本号吗?

报错信息

MXNetError Traceback (most recent call last)
in ()
5 filename = "…/data/test1.params"
6 print(filename)
----> 7 nd.save(filename,x)

c:\users\lenovo\appdata\local\programs\python\python36-32\lib\site-packages\mxnet\ndarray\utils.py in save(fname, data)
234 mx_uint(len(handles)),
235 handles,
–> 236 keys))

c:\users\lenovo\appdata\local\programs\python\python36-32\lib\site-packages\mxnet\base.py in check_call(ret)
144 “”"
145 if ret != 0:
–> 146 raise MXNetError(py_str(_LIB.MXGetLastError()))
147
148

MXNetError: [21:42:16] C:\projects\mxnet-distro-win\mxnet-build\dmlc-core\src\io\local_filesys.cc:166: Check failed: allow_null LocalFileSystem: fail to open “…/data/test1.params”

我笔记本是win8,64位;版本是2018年1月中旬安装的版本。
mxnet>=0.11.1b20171106

沫神,一个网络可能训练300个epochs,但训练过程中可能会发生各种意外中断了(如训练到epoch 260的时候),我想在训练过程中保存已经训练了260个epoch的模型,并且能恢复出来接着训练。有几个问题想请教您:
(1)我恢复出训练到第260个epoch的模型,是不是还训练40个epoch就行了?这与一次性训练完成300个epoch有差别吗?
(2)epoch的调整,对应是不是还需要调整data_loader?我的理解是一个epoch会跑一次完整的训练数据,应该跟data_loader没关系,不知可正确?
(3)我考虑的可能不完整,您能给出一个完整的思路或示例代码吗?
谢谢!预祝新年快乐!

因为你通过prefix显示的设置了namescope,所以会出现同样名字。