算法工程师修仙之路:Mxnet(四)

深度学习基础

线性回归的简洁实现


  • 实践中,我们通常可以用更简洁的代码来实现同样的模型,我们将介绍如何使用 MXNet 提供的Gluon 接口更方便地实现线性回归的训练。

生成数据集

  • 我们生成与之前相同的数据集,其中 features 是训练数据特征,labels 是标签。

    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)
    

读取数据

  • Gluon 提供了 data 包来读取数据。

  • 由于 data 常用作变量名,我们将导入的 data 模块用添加了 Gluon 首字母的假名 gdata 代替。

  • 在每一次迭代中,我们将随机读取包含10个数据样本的小批量。

    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
    """
    Output:
    [[ 0.10669409 -1.615797  ]
     [-0.24337251 -0.55600816]
     [ 0.18799396 -0.45784158]
     [-1.599301    0.06591962]
     [ 1.5509241   0.63531184]
     [ 0.1757906   0.74375474]
     [ 0.3500547   0.5360521 ]
     [ 0.6038035   1.1042424 ]
     [ 1.0598046   0.943863  ]
     [-0.5385921  -0.8611333 ]]
    <NDArray 10x2 @cpu(0)>
    [9.915791  5.609725  6.1265273 0.779277  5.141447  2.036555  3.0958035
     1.6462706 3.1178625 6.0557494]
    <NDArray 10 @cpu(0)>
    """
    

定义模型

  • 在从零开始的实现中,我们需要定义模型参数,并使用它们一步步描述模型是怎样计算的。当模型结构变得更复杂时,这些步骤将变得更繁琐。

  • 其实,Gluon 提供了大量预定义的层,这使我们只需关注使用哪些层来构造模型。

  • 下面将介绍如何使用 Gluon 更简洁地定义线性回归:

    • 首先,导入 nn 模块

      • 实际上,“nn” 是 neural networks(神经网络)的缩写。
      • 顾名思义,该模块定义了大量神经网络的层
    • 我们先定义一个模型变量 net,它是一个 Sequential 实例

      • 在 Gluon 中,Sequential 实例可以看作是一个串联各个层的容器。
    • 在构造模型时,我们在该容器中依次添加层。

      • 当给定输入数据时,容器中的每一层将依次计算并将输出作为下一层的输入。
      from mxnet.gluon import nn
      
      net = nn.Sequential()
      
    • 线性回归的输出层又叫全连接层。

      • 作为一个单层神经网络,线性回归输出层中的神经元和输入层中各个输入完全连接。
      • 在 Gluon 中,全连接层是一个 Dense 实例。我们定义该层输出个数为1。
  • 在 Gluon 中我们无须指定每一层输入的形状,例如线性回归的输入个数。当模型得到数据时,例如后面执行 net(X) 时,模型将自动推断出每一层的输入个数。

初始化模型参数

  • 在使用 net 前,我们需要初始化模型参数,如线性回归模型中的权重和偏差。
    • 我们从 MXNet 导入 init 模块

      • 该模块提供了模型参数初始化的各种方法
      • 这里的 init 是 initializer 的缩写形式。
    • 我们通过 init.Normal(sigma=0.01) 指定权重参数每个元素将在初始化时随机采样于均值为0、标准差为0.01的正态分布,偏差参数默认会初始化为零。

      from mxnet import init
      
      net.initialize(init.Normal(sigma=0.01))
      

定义损失函数

  • 在 Gluon 中,loss 模块定义了各种损失函数

  • 我们用假名 gloss 代替导入的 loss 模块,并直接使用它提供的平方损失作为模型的损失函数。

    from mxnet.gluon import loss as gloss
    
    loss = gloss.L2Loss()  # 平方损失又称 L2 范数损失
    

定义优化算法

  • 在导入 Gluon 后,我们创建一个 Trainer 实例,并指定学习率为0.03的小批量随机梯度下降(sgd)为优化算法。
    • 该优化算法将用来迭代 net 实例所有通过 add 函数嵌套的层所包含的全部参数。

    • 这些参数可以通过 collect_params 函数获取

      from mxnet import gluon
      
      trainer = gluon.Trainer(net.collect_params(), 'sgd', {'learning_rate': 0.03})
      

训练模型

  • 在使用 Gluon 训练模型时,我们通过调用 Trainer 实例的 step 函数迭代模型参数

  • 由于变量 l l l 是长度为 batch_size 的一维 NDArray,执行 l . b a c k w a r d ( ) l.backward() l.backward() 等价于执行 l . s u m ( ) . b a c k w a r d ( ) l.sum().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()))
    """
    Output:
    epoch 1, loss: 0.035042
    epoch 2, loss: 0.000129
    epoch 3, loss: 0.000049  
    """
    
    # 分别比较学到的模型参数和真实的模型参数
    # 我们从 net 获得需要的层,并访问其权重(weight)和偏差(bias)
    dense = net[0]
    print(true_w, dense.weight.data())
    print(true_b, dense.bias.data())
    """
    Output:
    [2, -3.4]
    [[ 1.999579 -3.399454]]
    <NDArray 1x2 @cpu(0)>
    4.2
    [4.199904]
    <NDArray 1 @cpu(0)>
    """
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值