pytorch 代码中的 ResNet 如何进行下采样?
How downsample work in ResNet in pytorch code?
在这个 pytorch ResNet 代码示例中,他们在第 44 行将下采样定义为变量。第 58 行将其用作函数。从 CNN 的角度和 python 代码的角度来看,这个下采样在这里是如何工作的。
代码示例:pytorch ResNet
我搜索了 downsample 是否是任何 pytorch 内置函数。但事实并非如此。
class BasicBlock(nn.Module):
expansion = 1
def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, norm_layer=None):
super(BasicBlock, self).__init__()
if norm_layer is None:
norm_layer = nn.BatchNorm2d
if groups != 1:
raise ValueError('BasicBlock only supports groups=1')
# Both self.conv1 and self.downsample layers downsample the input when stride != 1
self.conv1 = conv3x3(inplanes, planes, stride)
self.bn1 = norm_layer(planes)
self.relu = nn.ReLU(inplace=True)
self.conv2 = conv3x3(planes, planes)
self.bn2 = norm_layer(planes)
self.downsample = downsample
self.stride = stride
def forward(self, x):
identity = x
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out)
if self.downsample is not None:
identity = self.downsample(x)
out += identity
out = self.relu(out)
return out
我相信在这种情况下,它可以是平均池化或最大池化。它们都降低了维度并保留了输入的大部分属性。
如果您查看原始 ResNet 论文 (http://openaccess.thecvf.com/content_cvpr_2016/papers/He_Deep_Residual_Learning_CVPR_2016_paper.pdf),他们使用跨步卷积对图像进行下采样。正如在您的代码中所做的那样,使用这些跨步卷积自动对主路径进行下采样。残差路径使用 (a) 添加零条目的身份映射以不添加额外参数或 (b) 具有相同步幅参数的 1x1 卷积。
第二个选项可能如下所示:
if downsample:
self.downsample = conv1x1(inplanes, planes, strides)
在这个 ResNet 示例中,当我们定义 BasicBlock class 时,我们将下采样作为构造函数参数传递。
def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, norm_layer=None):
如果我们不向 class 传递任何内容,那么 downsample = None
,结果 identity 不会改变。
当我们将 downsample = "some convolution layer"
作为 class 构造函数参数传递时,它将通过传递的卷积层对 identity 进行下采样以成功执行加法。该层将通过代码对身份进行下采样
if self.downsample is not None:
identity = self.downsample(x)
除了 Thomas Pinetz 所说的:
在 resnet-50
架构中,这是作为下采样步骤发生的:
downsample = nn.Sequential(conv1x1(self.inplanes, planes * block.expansion, stride),norm_layer(planes * block.expansion))
注 - 1*1 卷积和批量归一化
在这个 pytorch ResNet 代码示例中,他们在第 44 行将下采样定义为变量。第 58 行将其用作函数。从 CNN 的角度和 python 代码的角度来看,这个下采样在这里是如何工作的。
代码示例:pytorch ResNet
我搜索了 downsample 是否是任何 pytorch 内置函数。但事实并非如此。
class BasicBlock(nn.Module):
expansion = 1
def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, norm_layer=None):
super(BasicBlock, self).__init__()
if norm_layer is None:
norm_layer = nn.BatchNorm2d
if groups != 1:
raise ValueError('BasicBlock only supports groups=1')
# Both self.conv1 and self.downsample layers downsample the input when stride != 1
self.conv1 = conv3x3(inplanes, planes, stride)
self.bn1 = norm_layer(planes)
self.relu = nn.ReLU(inplace=True)
self.conv2 = conv3x3(planes, planes)
self.bn2 = norm_layer(planes)
self.downsample = downsample
self.stride = stride
def forward(self, x):
identity = x
out = self.conv1(x)
out = self.bn1(out)
out = self.relu(out)
out = self.conv2(out)
out = self.bn2(out)
if self.downsample is not None:
identity = self.downsample(x)
out += identity
out = self.relu(out)
return out
我相信在这种情况下,它可以是平均池化或最大池化。它们都降低了维度并保留了输入的大部分属性。
如果您查看原始 ResNet 论文 (http://openaccess.thecvf.com/content_cvpr_2016/papers/He_Deep_Residual_Learning_CVPR_2016_paper.pdf),他们使用跨步卷积对图像进行下采样。正如在您的代码中所做的那样,使用这些跨步卷积自动对主路径进行下采样。残差路径使用 (a) 添加零条目的身份映射以不添加额外参数或 (b) 具有相同步幅参数的 1x1 卷积。
第二个选项可能如下所示:
if downsample:
self.downsample = conv1x1(inplanes, planes, strides)
在这个 ResNet 示例中,当我们定义 BasicBlock class 时,我们将下采样作为构造函数参数传递。
def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1, norm_layer=None):
如果我们不向 class 传递任何内容,那么 downsample = None
,结果 identity 不会改变。
当我们将 downsample = "some convolution layer"
作为 class 构造函数参数传递时,它将通过传递的卷积层对 identity 进行下采样以成功执行加法。该层将通过代码对身份进行下采样
if self.downsample is not None:
identity = self.downsample(x)
除了 Thomas Pinetz 所说的:
在 resnet-50
架构中,这是作为下采样步骤发生的:
downsample = nn.Sequential(conv1x1(self.inplanes, planes * block.expansion, stride),norm_layer(planes * block.expansion))
注 - 1*1 卷积和批量归一化