第三章第三节 模型参数的延后初始化

如果做了上一节练习,你会发现模型net在调用初始化函数initialize之后、在做前向计算net(X)之前时,权重参数的形状中出现了0.虽然直觉上initialize完成了所有参数初始化过程,然而这在Gluon中却是不一定的。我们在本节中详细讨论这个话题。

3.3.1 延后初始化

也许读者早就注意到了,在之前使用Gluon创建的全连接层都没有指定输入个数。例如,在上一节使用的多层感知机net里,我们创建的隐藏层仅仅指定了输出大小为256。当调用initialize函数时,由于隐藏层输入个数依然未知,系统也无法得知 该权重参数的形状。只有在当我们将形状是(2,20)的输入X传进网络做前向计算net(X)时,系统才推断出该层的权重参数形状为(256,20)。因此,这时候我们才能真正开始初始化参数。

让我们使用上一节中定义的MyInit类来演示这一过程。我们创建多层感知机,并使用MyInit实例来初始化模型参数。

注意,虽然MyInit被调用时会打印模型参数的相关信息,但上面的initialize函数执行完并未打印任何信息。由此可见,调用initialize函数时并没有真正初始化参数。下面我们定义输入并执行一次前向计算。

这时候,有关模型参数的信息被打印出来。在根据输入X做前向计算时,系统能够根据输入的形状自动推断出所有层的权重参数的形状。系统在创建这些参数之后,调用MyInit实例对它们进行初始化,然后才进行前向计算。

当然,这个初始化只会在第一次前向计算时被调用。之后我们再运行前向计算net(X)时则不会重新初始化,因此不会再次产生MyInit实例的输出。

系统将真正的参数初始化延后到获得足够信息时才执行的行为叫做延后初始化(deferred initialization)。它可以让模型的创建更加简单:只需要定义每个层的输出大小,而不用人工推测它们的输入个数。这对于之后将介绍的定义多达数十甚至数百层的网络来说尤其方便。

然而,任何事物都有两面性。正如本节开头提到的那样,延后初始化也可能带来一定的困惑。在第一次前向计算之前,我们无法直接操作模型参数,例如无法使用data函数和set_data函数来获取和修改参数。因此,我们经常会额外做一次前向计算来迫使参数被真正地初始化。

3.3.2 避免延后初始化

如果系统在调用initialize函数时能够知道所有参数的形状,那么延后初始化就不会发生。我们在这里分别介绍两种这样的情况。

第一种情况是我们要对已初始化的模型重新初始化时。因为参数形状不会发生变化,所以系统能够立即进行重新初始化。

第二种情况是我们在创建层的时候指定了它的输入个数,使系统不需要额外的信息来推测参数形状。下例中我们通过in_units来指定每个全连接层的输入个数,使初始化能够在initialize函数被调用时立即发生。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值