我是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.relu
与mx.gluon.nn.Activation
有什么区别?
应该是
x = self.ramp(x)
而不是
x = mx.nd.relu(self.ramp(x))
答案 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引擎盖下。)