gpt4 book ai didi

python - 仅使用 ‘Sequential()’ 或 ‘HybridSequential()’ 作为容器是否有任何副作用?

转载 作者:行者123 更新时间:2023-12-01 09:25:19 36 4
gpt4 key购买 nike

我正在阅读有关 MxNet 的教程。作者使用‘mxnet.gluon.nn.Sequential()’作为容器来存储一些 block (参见代码1);然后,他们重写‘defforward(self,x)’中 block 的连接(参见代码2和3)。这样做有副作用吗?顺便问一下,‘Sequential()’和‘HybridSequential()’有什么区别。我尝试用一​​个列表来替换“顺序”,在初始化过程中我收到以下警告。

“ToySSD.downsamplers” is a container with Blocks. Note that Blocks inside the list, tuple or dict will not be registered automatically. Make sure to register them using register_child() or switching to nn.Sequential/nn.HybridSequential instead.’

据我所知,如果您将一些 block 放入“​​mxnet.gluon.nn.Sequential()”或“mxnet.gluon.nn.HybridSequential()”中,此操作会告诉计算机这些 block 已连接。然而,如果你在“转发”功能中设计 block 的关系,你就是在告诉计算机以另一种方式连接这些 block 。会导致困惑吗?如果我只在“forward”中设计一些 block 连接,那么“Sequential()”中未在“forward”函数中设计的其他 block 之间的关系是什么?

整个教程可以在here中找到.

代码1:

def toy_ssd_model(num_anchors, num_classes):
downsamplers = nn.Sequential()
for _ in range(3):
downsamplers.add(down_sample(128))

class_predictors = nn.Sequential()
box_predictors = nn.Sequential()
for _ in range(5):
class_predictors.add(class_predictor(num_anchors, num_classes))
box_predictors.add(box_predictor(num_anchors))

model = nn.Sequential()
model.add(body(), downsamplers, class_predictors, box_predictors)
return model

代码2:

def toy_ssd_forward(x, model, sizes, ratios, verbose=False):    
body, downsamplers, class_predictors, box_predictors = model
anchors, class_preds, box_preds = [], [], []
# feature extraction
x = body(x)
for i in range(5):
# predict
anchors.append(MultiBoxPrior(
x, sizes=sizes[i], ratios=ratios[i]))
class_preds.append(
flatten_prediction(class_predictors[i](x)))
box_preds.append(
flatten_prediction(box_predictors[i](x)))
if verbose:
print('Predict scale', i, x.shape, 'with',
anchors[-1].shape[1], 'anchors')
# down sample
if i < 3:
x = downsamplers[i](x)
elif i == 3:
x = nd.Pooling(
x, global_pool=True, pool_type='max',
kernel=(x.shape[2], x.shape[3]))
# concat data
return (concat_predictions(anchors),
concat_predictions(class_preds),
concat_predictions(box_preds))

代码3:

from mxnet import gluon
class ToySSD(gluon.Block):
def __init__(self, num_classes, verbose=False, **kwargs):
super(ToySSD, self).__init__(**kwargs)
# anchor box sizes and ratios for 5 feature scales
self.sizes = [[.2,.272], [.37,.447], [.54,.619],
[.71,.79], [.88,.961]]
self.ratios = [[1,2,.5]]*5
self.num_classes = num_classes
self.verbose = verbose
num_anchors = len(self.sizes[0]) + len(self.ratios[0]) - 1
# use name_scope to guard the names
with self.name_scope():
self.model = toy_ssd_model(num_anchors, num_classes)

def forward(self, x):
anchors, class_preds, box_preds = toy_ssd_forward(
x, self.model, self.sizes, self.ratios,
verbose=self.verbose)
# it is better to have class predictions reshaped for softmax computation
class_preds = class_preds.reshape(shape=(0, -1, self.num_classes+1))
return anchors, class_preds, box_preds

最佳答案

在 Gluon 中,网络是使用 Block 构建的。如果某物不是Block,它就不能成为 Gluon 网络的一部分。密集层是一个Block,卷积是一个Block,池化层是一个Block,等等

有时您可能需要一个不是 Gluon 中预定义 block 的 block ,而是预定义 Gluon block 的序列。例如,

Conv2D -> MaxPool2D -> Conv2D -> MaxPool2D -> 展平 -> 密集 -> 密集

Gluon 没有执行上述操作序列的预定义 block 。但 Gluon 确实有执行每个单独操作的 block 。因此,您可以通过将预定义的 Gluon block 串在一起来创建自己的 block 来执行上述操作序列。示例:

net = gluon.nn.HybridSequential()

with net.name_scope():

# First convolution
net.add(gluon.nn.Conv2D(channels=20, kernel_size=5, activation='relu'))
net.add(gluon.nn.MaxPool2D(pool_size=2, strides=2))

# Second convolution
net.add(gluon.nn.Conv2D(channels=50, kernel_size=5, activation='relu'))
net.add(gluon.nn.MaxPool2D(pool_size=2, strides=2))

# Flatten the output before the fully connected layers
net.add(gluon.nn.Flatten())

# First fully connected layers with 512 neurons
net.add(gluon.nn.Dense(512, activation="relu"))

# Second fully connected layer with as many neurons as the number of classes
net.add(gluon.nn.Dense(num_outputs))

当您创建这样的序列时,您可以使用 HybridSequentialSequential。要了解差异,您需要了解 difference between symbolic and imperative programming .

  • HybridBlock 是一个可以转换为符号图以加快执行速度的 block 。 HybridSequential 是一系列 Hybrid block 。
  • Blocks(不是混合的)是无法转换为符号图的Block。 Sequential 是非混合 block 的序列。

一个 block 是否是混合 block 取决于它的实现方式。几乎所有预定义的 Gluon block 也是 HybridBlock。有时某些 block 不能混合是有原因的。 Tree LSTM就是一个例子。更常见的是,某些东西不是混合的,只是因为编写它的人由于多种原因没有付出努力使其成为混合(例如:也许使其混合不会带来很大的性能提升,或者可能很难使其成为混合) )。

请注意,SequentialHybridSequential 不仅仅是像 Python list 这样的容器。当您使用其中之一时,您实际上是在使用预先存在的 block 创建一个新的 block 。这就是为什么您不能使用 Python list 替换 Sequential

好的,现在您知道如何通过将预先存在的 block 串在一起来创建自己的 block 了。好的。如果您不想只通过一系列 block 传递数据怎么办?如果您想有条件地通过这些 block 之一传递数据该怎么办?以下是 ResNet 的示例:

class BasicBlockV1(HybridBlock):
def __init__(self, channels, stride, downsample=False, in_channels=0, **kwargs):
super(BasicBlockV1, self).__init__(**kwargs)
self.body = nn.HybridSequential(prefix='')
self.body.add(_conv3x3(channels, stride, in_channels))
self.body.add(nn.BatchNorm())
self.body.add(nn.Activation('relu'))
self.body.add(_conv3x3(channels, 1, channels))
self.body.add(nn.BatchNorm())
if downsample:
self.downsample = nn.HybridSequential(prefix='')
self.downsample.add(nn.Conv2D(channels, kernel_size=1, strides=stride,
use_bias=False, in_channels=in_channels))
self.downsample.add(nn.BatchNorm())
else:
self.downsample = None

def hybrid_forward(self, F, x):
residual = x

x = self.body(x)

if self.downsample:
residual = self.downsample(residual)

x = F.Activation(residual+x, act_type='relu')

return x

此代码使用预先存在的 Gluon block 创建一个新 block 。但它不仅仅是通过一些预先存在的 block 运行数据。给定一些数据,该 block 会通过主体 block 运行数据。但是,仅当此 block 是在 downsample 设置为 true 的情况下创建的时,才通过 downsample 运行数据。然后,它将 bodydownsample 的输出连接起来以创建输出。正如您所看到的,发生的事情不仅仅是通过一系列 block 传递数据。这是当您通过子类化 HybridBlockBlock 创建自己的 block 时。

请注意,__init__ 函数创建了必要的 block ,forward 函数获取输入并通过在 __init__ 中创建的 block 运行输入。 forward 不会修改在 __init__ 中创建的 block 。它仅通过 __init__ 中创建的 block 运行数据。

在您引用的示例中,第一个代码块创建诸如 downsamplersclass_predictorsbox_predictors 之类的 block 。代码块 2 和 3 中的前向函数不会修改这些 block 。他们只是通过这些 block 传递输入数据。

关于python - 仅使用 ‘Sequential()’ 或 ‘HybridSequential()’ 作为容器是否有任何副作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50458412/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com