Mxnet/Gluon入门实战:LeNet手写数字识别

在《Mxnet/Gluon入门实战:LeNet手写数字识别》和《Pytorch入门实战:LeNet手写数字识别》两篇博文里,我将分别使用Mxnet和Pytorch框架搭建LeNet网络,在Mnist数据集上进行手写数字识别,以对比两种框架炼丹异同。本文是Mxnet部分。

需要掌握的几个Mxnet/Gluon用法:

  1. as_in_context
    mxnet中使用as_in_contextcopyto来将数据在cpu、gpu设备之间传递。如果源变量和目标变量的context一致,as_in_context函数使目标变量和源变量共享源变量的内存;而copyto函数总是为目标变量创建新的内存。
    >>> y = x.copyto(mx.gpu())
    >>> z = x.as_in_contepredicted = output.argmax(axis=1)xt(mx.gpu())

  2. nd.ndarray.NDArray.asscalar()
    从ndarray返回一个标量。

  3. argmax()
    返回某一维度上的最大值。
    >>> predicted = output.argmax(axis=1)

  4. astype()
    类型转换。
    >>> test_acc += (predicted == y.astype(np.float32)).sum()

1
2
3
4
5
6
7
8
import mxnet as mx
from mxnet import autograd
from mxnet import init
from mxnet.gluon import nn
from mxnet import gluon
import mxnet.ndarray as nd
import time
import numpy as np
1
2
3
4
5
6
7
8
9
10
11
net = nn.Sequential()
net.add(
nn.Conv2D(channels=6, kernel_size=5, strides=1, padding=2, activation='relu'),
nn.MaxPool2D(pool_size=2, strides=2),
nn.Conv2D(channels=16, kernel_size=5, activation='relu'),
nn.MaxPool2D(pool_size=2, strides=2),
nn.Flatten(),
nn.Dense(120, activation='relu'),
nn.Dense(84, activation='relu'),
nn.Dense(10),
)
1
2
3
4
5
6
7
def try_gpu():
try:
ctx = mx.gpu()
_ = nd.zeros((1,), ctx=ctx)
except mx.base.MXNetError:
ctx = mx.cpu()
return ctx
1
2
3
epoch_nums = 10
batch_size = 16
lr = 0.01
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
def transformer(data, label):
return nd.transpose(data.astype(np.float32), (2, 0, 1)).asnumpy() / 255, label.astype(np.int32)


train_set = gluon.data.vision.MNIST(
train=True,
transform=transformer,
)

train_loader = gluon.data.DataLoader(
dataset=train_set,
batch_size=batch_size,
shuffle=True
)

test_set = gluon.data.vision.MNIST(
train=False,
transform=transformer,
)

test_loader = gluon.data.DataLoader(
dataset=test_set,
batch_size=batch_size,
shuffle=False
)
1
2
ctx = try_gpu()
ctx
gpu(0)
1
net.initialize(ctx=ctx, init=init.Xavier())
1
2
3
4
5
6
criterion = gluon.loss.SoftmaxCrossEntropyLoss()
trainer = gluon.Trainer(
params=net.collect_params(),
optimizer='sgd',
optimizer_params={'learning_rate': lr, 'momentum': 0.9},
)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
for epoch in range(epoch_nums):
loss_sum = 0
start_time = time.time()
for X, y in train_loader:
X, y = X.as_in_context(ctx), y.as_in_context(ctx)
with autograd.record():
output = net(X)
loss = criterion(output, y)
loss.backward()
trainer.step(batch_size)
loss_sum += loss.mean().asscalar()

test_acc = nd.array([0.0], ctx=ctx)
test_acc = 0
total = 0
for X, y in test_loader:
X, y = X.as_in_context(ctx), y.as_in_context(ctx)
output = net(X)
predicted = output.argmax(axis=1)
test_acc += (predicted == y.astype(np.float32)).sum()
total += y.size
print('epoch: %d, train loss: %.03f, test acc: %.03f, time %.1f sec' % (epoch + 1, loss_sum / len(train_loader), test_acc.asscalar() / total, time.time() - start_time))
epoch: 1, train loss: 0.167, test acc: 0.982, time 12.8 sec
epoch: 2, train loss: 0.056, test acc: 0.984, time 12.5 sec
epoch: 3, train loss: 0.043, test acc: 0.985, time 12.7 sec
epoch: 4, train loss: 0.034, test acc: 0.989, time 12.8 sec
epoch: 5, train loss: 0.026, test acc: 0.988, time 12.8 sec
epoch: 6, train loss: 0.024, test acc: 0.988, time 12.8 sec
epoch: 7, train loss: 0.021, test acc: 0.988, time 13.0 sec
epoch: 8, train loss: 0.021, test acc: 0.990, time 12.7 sec
epoch: 9, train loss: 0.014, test acc: 0.990, time 12.7 sec
epoch: 10, train loss: 0.018, test acc: 0.989, time 12.9 sec
1
net.save_parameters('./mxnet_mnist_parameters')
持续技术分享,您的支持将鼓励我继续创作!