MXNet:nn.Activation vs nd.relu?

时间:2017-09-18 18:12:31

标签: python-3.x mxnet

我是MXNet的新手(我在Python3中使用它)

他们的教程系列鼓励您定义自己的gluon blocks

让我们说这是你的块(一个常见的卷积结构):

class CNN1D(mx.gluon.Block):
    def __init__(self, **kwargs):
        super(CNN1D, self).__init__(**kwargs)
        with self.name_scope():
            self.cnn = mx.gluon.nn.Conv1D(10, 1)
            self.bn = mx.gluon.nn.BatchNorm()
            self.ramp = mx.gluon.nn.Activation(activation='relu')

    def forward(self, x):
        x = mx.nd.relu(self.cnn(x))
        x = mx.nd.relu(self.bn(x))
        x = mx.nd.relu(self.ramp(x))
        return x

这是他们示例的结构镜像。 mx.nd.relumx.gluon.nn.Activation有什么区别?

应该是

x = self.ramp(x)

而不是

x = mx.nd.relu(self.ramp(x))

2 个答案:

答案 0 :(得分:3)

似乎

mx.gluon.nn.Activation(activation=<act>)

是一个包装器,用于从NDArray模块调用一系列底层激活。

因此 - 原则上 - 在前向定义中使用

并不重要
x = self.ramp(x)

x = mx.nd.relu(x)

x = mx.nd.relu(self.ramp(x))

因为relu只是将最大值设置为0并且传递的值(因此除了稍微的运行时间增加之外,多个应用程序不会影响除单个调用之外的值)。

因此在这个的情况下,它并不重要。当然,对于其他激活功能,堆叠多个呼叫可能会产生影响。

在MXNets文档中,他们在定义nd.relu时在前向定义中使用gluon.Block。与使用mx.gluon.nn.Activation(activation='relu')相比,这可能会略微减少开销。

风味方面,gluon模块意味着高级抽象。因此我认为在定义块时应该使用 ramp = mx.gluon.nn.Activation(activation=<act>)代替nd.<act>(x),然后在前向定义中调用self.ramp(x)

但是,鉴于此时所有自定义Block教程/文档都坚持relu激活,无论这是否会产生持久影响还有待观察。

使用mx.gluon.nn.Activation似乎是从NDArray模块的Gluon模块调用激活函数的一种方法。

答案 1 :(得分:1)

mx.gluon.nn.Activation包裹mx.ndarray.Activation,请参阅Gluon source code

然而,当使用Gluon构建神经网络时,建议您使用Gluon API而不是分支以任意使用较低级别的MXNet API - 这可能会出现Gluon演变并可能发生变化的问题(例如停止使用mx.nd引擎盖下。)