《动手学深度学习》第三课---笔记

1.Block(Sequential类继承自Block)

Block类是nn模块中的一个模型构造类。

  • __init__ 函数:创建模型参数
  • forward函数:定义前向计算,自动绑定“()” 例:MLP(X)

ps:无需定义方向传播函数,系统将自动计算出相应的backward函数。

from mxnet import nd
from mxnet.gluon import nn
class MLP(nn.Block):
    # 声明带有模型参数的层,这⾥我们声明了两个全链接层。
    def __init__(self, **kwargs):
        # 调⽤MLP ⽗类Block 的构造函数来进⾏必要的初始化。这样在构造实例时还可以指定
        # 其他函数参数,例如下下⼀节将介绍的模型参数params。
        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))

Block类是一个可以自由组件的部件。(一层,一个模型,模型的一部分)。

Sequential类(简单串联):提供add函数来逐一添加串联的Block子类的实例。

练习:

  • 如果不在MLP类的__init__函数里调用父类的__init__函数,会出现什么样的错误信息?
    AttributeError: 'MLP' object has no attribute '_children'
  • 如果去掉FancyMLP类里面的asscalar函数,会有什么问题?
#API解释。一个标量就是一个单独的数,我们在使用标量时,一般都要明确给出它是那种类型的数
#代码中如果不使用标量,可能会导致向量/矩阵与1进行比较
Returns a scalar whose value is copied from this array.

This function is equivalent to self.asnumpy()[0]. This NDArray must have shape (1,).

Examples

>>> x = mx.nd.ones((1,), dtype='int32')
>>> x.asscalar()
1
>>> type(x.asscalar())
  • 如果将NestMLP类中通过 Sequential 实例定义的self.net改为self.net = [nn.Dense(64, activation='relu'), nn.Dense(32, activation='relu')],会有什么问题?

          运行的时候变成了列表

2.模型参数

2.1 获取参数:

Sequential 类构造出来的⽹络的特定层的参数能够通过[ ]来访问。例如:参数的名称为dense0_weight,它由net[0] 的名称(dense0_)和⾃⼰的变量名(weight)组成。因此可以用以下两种方式获取:

  1. net[0].params['dense0_weight']
  2. net[0].weight

Parameter类,参数(.data())访问参数,(.grad())访问参数的梯度

collect_params 函数来获取net 实例所有嵌套(参数名称到参数实例的字典)。

2.2 不同方法初始化

#force_reinit=True,表示再次初始化(非首次赋值true,系统有保护多次初始化)
net.initialize(init=init.Normal(sigma=0.01), force_reinit=True)
  •  系统还提供了很多种方法进行初始化,详情可参见:Initial_API
  •  自定义初始化
    class MyInit(init.Initializer):
        def _init_weight(self, name, data):
            print('Init', name, data.shape)
            data[:] = nd.random.uniform(low=-10, high=10, shape=data.shape)
            data *= data.abs() >= 5
    
    net.initialize(MyInit(), force_reinit=True)

    通过Parameter类的set_data函数来直接改写模型参数

    net[0].weight.set_data(net[0].weight.data() + 1)
  • 共享模型参数

        在构造层的时候指定使用特定的参数。如果不同层使用同一份参数,那么它们在前向计算和反向传播时都会共享相同的参数 

net = nn.Sequential()
shared = nn.Dense(8, activation='relu')
net.add(nn.Dense(8, activation='relu'),
        shared,
        nn.Dense(8, activation='relu', params=shared.params),#共享参数
        nn.Dense(10))
net.initialize()

延后初始化:mxnet的一个特点,在初始化前,网络并不知道你的输入,同样也不知道中间的一些参数shape,等到你初始化,才能实际的定义好相关的shape。

  • 查阅有关init模块的 MXNet 文档,了解不同的参数初始化方法。

               Initial_API

  • 尝试在net.initialize()后、net(x)前访问模型参数,观察模型参数的形状。
  • 构造一个含共享参数层的多层感知机并训练。在训练过程中,观察每一层的模型参数和梯度

              讨论里面:前向传播会将参数乘两次,所以在反传是也应该分别求出梯度,分别更新参数,但是第二次会覆盖第一次的结果,所以我们只能看到一个值。

2.3序列化--读写模型(初级)

#mxnet
nd.save(filename, params)

params = nd.load(filename)

#mxnet.gloun
net.save_params(filename)

net2.load_params(filename,mx.cpu)

后续:跨平台读取模型。。。

3 gloun自定义层

1. 简单的层

class CenteredLayer(nn.Block):
    def __init__(self, **kwargs):
        super(CenteredLayer, self).__init__(**kwargs)

    def forward(self, x):
        return x - x.mean()

2. 带模型参数的层

  • Parameter:它包含参数和梯度的数值,可以分别通过datagrad函数来访问。
  • ParameterDict:参数名称映射到参数实例的字典
    params = gluon.ParameterDict()
    params.get('param2', shape=(2, 3))
    class MyDense(nn.Block):
        # units:该层的输出个数;in_units:该层的输入个数。
        def __init__(self, units, in_units, **kwargs):
            super(MyDense, self).__init__(**kwargs)
            self.weight = self.params.get('weight', shape=(in_units, units))
            self.bias = self.params.get('bias', shape=(units,))
    
        def forward(self, x):
            linear = nd.dot(x, self.weight.data()) + self.bias.data()
            return nd.relu(linear)

     

4 丢弃法(以一定概率丢弃某些神经元)

  • 降低模型的复杂性
  • 防止过拟合

5 AlexNet

6 VGG

通过重复的小网络实现深度网络

空间信息->语义信息    64->128->256->512   input-channls。input 变小1倍,channl变大1倍。 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值