在使用gluon接口之前,我们首先需要下载好mxnet包pip install mxnet
生成数据集
根据公式基础去理解,并加上噪声
from mxnet import autograd, nd
num_inputs = 2
num_examples = 1000
true_w = [2, -3.4]
true_b = 4.2
features = nd.random.normal(scale=1, shape=(num_examples, num_inputs))
labels = true_w[0] * features[:, 0] + true_w[1] * features[:, 1] + true_b
labels += nd.random.normal(scale=0.01, shape=labels.shape)#生成噪声,其中噪声项ϵ服从均值为0、标准差为0.01的正态分布。噪声代表了数据集中⽆意义的⼲扰
读取数据集
from mxnet.gluon import data as gdata
batch_size = 10
# 将训练数据的特征和标签组合
dataset = gdata.ArrayDataset(features, labels)
# 随机读取⼩批量
data_iter = gdata.DataLoader(dataset, batch_size, shuffle=True)
#读取并打印第⼀个小批量数据样本
for X, y in data_iter:
print(X, y)
break
对于data_iter,实现原理如下,在gluon中进行了简单定义方便使用。
def data_iter(batch_size, features, labels):
num_examples = len(features) # 特征个数
indices = list(range(num_examples)) # 特征个数索引列表
random.shuffle(indices) # 样本的读取顺序是随机的
for i in range(0, num_examples, batch_size):
j = nd.array(indices[i: min(i + batch_size, num_examples)])
# 切片得索引(包含最后没有达到batch_size得一个切片索引)
yield features.take(j), labels.take(j) # take函数根据索引返回对应元素
定义模型
当模型结构变得更复杂时,定义模型参数将变得更烦琐。其实,Gluon提供了⼤量预定义的层,这使我们只需关注使⽤哪些层来构造模型。下⾯将介绍如何使⽤Gluon更简洁地定义线性回归。
首先,导入nn模块。该模块定义了大量神经网络的层。我们先定义⼀个模型变量net,它是⼀个Sequential实例。在Gluon中,Sequential实例可以看作是⼀个串联各个层的容器。在构造模型时,我们在该容器中依次添加层。当给定输⼊数据时,容器中的每⼀层将依次计算并将输出作为下⼀层的输入。
from mxnet.gluon import nn
net = nn.Sequential()
作为⼀个单层神经⽹络,线性回归输出层中的神经元和输入层中各个输入完全连接。因此,线性回归的输出层⼜叫全连接层。在Gluon中,全连接层是⼀个Dense实例。我们定义该层输出个数为1。
net.add(nn.Dense(1))
在Gluon中我们⽆须指定每⼀层输⼊的形状,例如线性回归的输入个数。当模型得到数据时,例如后面执行net(X)时,模型将⾃动推断出每⼀层的输入个数。
初始化模型参数
在使用net前,我们需要初始化模型参数,如线性回归模型中的权重和偏差。我们从MXNet导入init模块。该模块提供了模型参数初始化的各种方法。
from mxnet import init
net.initialize(init.Normal(sigma=0.01))
#随机采样于均值为0、标准差为0.01的正态分布
定义损失函数
from mxnet.gluon import loss as gloss
loss = gloss.L2Loss() # 平⽅损失⼜称L2范数损失
定义优化算法
from mxnet import gluon
trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate': 0.03})
#指定学习率为0.03的小批量随机梯度下降(sgd)为优化算法
该优化算法将⽤来迭代net实例所有通过add函数嵌套的层所包含的全部参数。这些参数可以通过collect_params函数获取。
训练模型
在使⽤Gluon训练模型时,我们通过调用Trainer实例的step函数来迭代模型参数。上一节中我们提到,由于变量l是长度为batch_size的一维NDArray,执行l.backward()等价于执行l.
sum().backward()。按照小批量随机梯度下降的定义,我们在step函数中指明批量大小,从
而对批量中样本梯度求平均
num_epochs = 3
for epoch in range(1, num_epochs + 1):
for X, y in data_iter:
with autograd.record():#记录梯度运算
l = loss(net(X), y)
l.backward()#求梯度
trainer.step(batch_size)#迭代模型参数
l = loss(net(features), labels)
print('epoch %d, loss: %f' % (epoch, l.mean().asnumpy()))