torchvision.models.resnet18(pretrained=True)

ResNet(
  (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
  (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (relu): ReLU(inplace=True)
  (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
  (layer1): Sequential((0): BasicBlock(...) (1): BasicBlock(...))
  (layer2): Sequential((0): BasicBlock(...) (1): BasicBlock(...))
  (layer3): Sequential((0): BasicBlock(...) (1): BasicBlock(...))
  (layer4): Sequential((0): BasicBlock(...) (1): BasicBlock(...))
  (avgpool): AdaptiveAvgPool2d(output_size=(1, 1))
  (fc): Linear(in_features=512, out_features=1000, bias=True)
)

ResNet随着网络层不断的加深,模型的准确率先是不断的提高,达到最大值(准确率饱和),然后随着网络深度的继续增加,模型准确率毫无征兆的出现大幅度的降低。这个现象与“越深的网络准确率越高”的信念显然是矛盾的、冲突的。ResNet团队把这一现象称为“退化(Degradation)”。ResNet团队把退化现象归因为深层神经网络难以实现“恒等变换(y=x)”。

深度学习的关键特征在于网络层数更深、非线性转换(激活)、自动的特征提取和特征转换,其中,非线性转换是关键目标,它将数据映射到高纬空间以便于更好的完成“数据分类”。随着网络深度的不断增大,所引入的激活函数也越来越多,数据被映射到更加离散的空间,此时已经难以让数据回到原点(恒等变换)。
 

torch.nn.Conv2d(in_channelsout_channelskernel_sizestride=1padding=0dilation=1groups=1bias=Truepadding_mode='zeros'device=Nonedtype=None)

in_channels:输入通道数,out_channels:输出通道数。

kernel_size:卷积核的大小

H=W=5(5行5列):kernel_size is a singe number

H=3,W=5(3行5列):kernel_size is a turple(3,5)

stride:卷积核在图像窗口上每次平移的间隔,即所谓的步长。

padding:填充包括图像的上下左右。Pytorch不同于Tensorflow的地方在于,Tensorflow提供的是padding的模式,比如same、valid,且不同模式对应了不同的输出图像尺寸计算公式。而Pytorch则需要手动输入。

(1)valid padding:不进行任何处理,只使用原始图像,不允许卷积核超出原始图像边界

(2)same padding:进行填充,允许卷积核超出原始图像边界,并使得卷积后结果的大小与原来的一致

dilation,扩张操作:控制kernel点(卷积核点)的间距。空洞卷积的rate,代表传统卷积核的相邻之间插入rate-1个空洞数。当rate=1时,相当于传统的卷积核。

​​​​​​https://i-blog.csdnimg.cn/blog_migrate/07e5688b578c28b33ee11f781456c503.png

group:控制输入和输出之间的连接。in-channels和out-channels都必须能被group整除。

默认值为1, 也就是说默认输出输入的所有通道各为一组。 比如输入数据大小为90x100x100x32,通道数32,要经过一个3x3x48的卷积,group默认是1,就是全连接的卷积层。

如果group是2,那么对应要将输入的32个通道分成2个16的通道,将输出的48个通道分成2个24的通道。对输出的2个24的通道,第一个24通道与输入的第一个16通道进行全卷积,第二个24通道与输入的第二个16通道进行全卷积。

极端情况下,输入输出通道数相同,比如为24,group大小也为24,那么每个输出卷积核,只与输入的对应的通道进行卷积。

conv = nn.Conv2d(in_channels=6, out_channels=6, kernel_size=1, groups=1)
conv.weight.data.size()

第一个值为out_channels的大小,第二个值为in_channels的大小,后面两个值为kernel_size

torch.Size([6, 6, 1, 1]),该卷积层需要6*6*1*1=36个参数,即需要6个6*1*1的卷积核。

6*H_in*W_in的输入整个乘以一个6*1*1的卷积核,得到输出的一个channel的值,即1*H_out*W_out。

conv = nn.Conv2d(in_channels=6, out_channels=6, kernel_size=1, groups=2)
conv.weight.data.size()

torch.Size([6, 3, 1, 1]),第一个输出的3通道与输入的3通道进行全卷积,一个卷积核大小为3*1*1,有3个卷积核。

conv = nn.Conv2d(in_channels=6, out_channels=6, kernel_size=1, groups=3)
conv.weight.data.size()

torch.Size([6, 2, 1, 1])

conv = nn.Conv2d(in_channels=6, out_channels=6, kernel_size=1, groups=6)
conv.weight.data.size()

torch.Size([6, 1, 1, 1])

bias:即是否要添加偏置参数作为可学习参数的一个,默认为True。(一个channel中一个bias)

padding_mode:填充模式

'zeros'就是最常见的零填充,即在矩阵的高、宽两个维度上用0进行填充,填充时将在一个维度的两边都进行填充。

'reflect'是以矩阵边缘为对称轴,将矩阵中的元素对称的填充到最外围。

# 定义一个1*1卷积,设置填充模式为'reflect',在高和宽维度上两边各填充1个单位
In [58]: conv_reflect = torch.nn.Conv2d(1,1,1,1,padding=1,padding_mode='reflect',bias=False)

# 将卷积核的权重设置为1,这样可使卷积后的输出即为填充后的输入矩阵
In [59]: conv_reflect.weight = torch.nn.Parameter(torch.ones(1,1,1,1))

# 进行卷积计算,并输出结果
In [60]: conv_reflect(x)
Out[60]:
tensor([[[[ 6.,  5.,  6.,  7.,  8.,  7.],
          [ 2.,  1.,  2.,  3.,  4.,  3.],
          [ 6.,  5.,  6.,  7.,  8.,  7.],
          [10.,  9., 10., 11., 12., 11.],
          [14., 13., 14., 15., 16., 15.],
          [10.,  9., 10., 11., 12., 11.]]]], grad_fn=<ThnnConv2DBackward>)

'replicate'将矩阵的边缘复制并填充到矩阵的外围.

# 定义一个1*1卷积,设置填充模式为'replicate',在高和宽维度上两边各填充1个单位
In [61]: conv_reflect = torch.nn.Conv2d(1,1,1,1,padding=1,padding_mode='replicate',bias=False)

# 将卷积核的权重设置为1,这样可使卷积后的输出即为填充后的输入矩阵
In [62]: conv_reflect.weight = torch.nn.Parameter(torch.ones(1,1,1,1))

# 进行卷积计算,并输出结果
In [63]: conv_replicate(x)
Out[63]:
tensor([[[[ 1.,  1.,  2.,  3.,  4.,  4.],
          [ 1.,  1.,  2.,  3.,  4.,  4.],
          [ 5.,  5.,  6.,  7.,  8.,  8.],
          [ 9.,  9., 10., 11., 12., 12.],
          [13., 13., 14., 15., 16., 16.],
          [13., 13., 14., 15., 16., 16.]]]], grad_fn=<ThnnConv2DBackward>)

'circular'就是循环的进行填充

# 定义一个1*1卷积,设置填充模式为'circular',在高和宽维度上两边各填充1个单位
In [64]: conv_reflect = torch.nn.Conv2d(1,1,1,1,padding=1,padding_mode='circular',bias=False)

# 将卷积核的权重设置为1,这样可使卷积后的输出即为填充后的输入矩阵
In [65]: conv_reflect.weight = torch.nn.Parameter(torch.ones(1,1,1,1))

# 进行卷积计算,并输出结果
In [66]: conv_circular(x)
Out[66]:
tensor([[[[16., 13., 14., 15., 16., 13.],
          [ 4.,  1.,  2.,  3.,  4.,  1.],
          [ 8.,  5.,  6.,  7.,  8.,  5.],
          [12.,  9., 10., 11., 12.,  9.],
          [16., 13., 14., 15., 16., 13.],
          [ 4.,  1.,  2.,  3.,  4.,  1.]]]], grad_fn=<ThnnConv2DBackward>)

The parameters kernel_sizestridepaddingdilation can either be:

元组的第一个参数指向高维度(行)。

  • a single int – in which case the same value is used for the height and width dimension

  • tuple of two ints – in which case, the first int is used for the height dimension, and the second int for the width dimension

计算输出大小

变量

torch.nn.BatchNorm2d(num_featureseps=1e-05momentum=0.1affine=Truetrack_running_stats=Truedevice=Nonedtype=None)

以一个batch为统计单位,在C(channel)维度上进行归一化。具体来说,对于每个batch的数据,BatchNorm2d会计算其均值和方差,并使用这两个参数对数据进行归一化。然后,再通过可学习的参数γ和β进行缩放和平移。这个过程可以保证每一层的输入数据都具有相同的分布特征,从而使得神经网络训练更加稳定。

  1. 抑制梯度消失:在深度神经网络中,梯度消失是一个常见的问题。BatchNorm2d通过对激活函数前添加归一化层,抑制了梯度消失的问题,从而加速了优化过程。
  2. 加速优化过程:使用BatchNorm2d后,可以应用更大的学习率,使得训练过程更加稳定,大大提高了训练速度。
  3. 减小参数初始化带来的影响:BatchNorm2d通过对数据的归一化处理,使得权重初始化的影响减小,无论权重的初始值如何,都可以通过归一化和仿射变换得到较好的效果。
  4. 正则化作用:BatchNorm2d可以视为一种有效的正则化技术,它通过引入额外的参数γ和β,增加了模型的复杂度,从而在一定程度上避免了过拟合。此外,BatchNorm2d还具有数据增强的效果,通过对mini-batch的数据进行归一化处理,可以看作是对数据进行了一定的变换,类似于数据增强的效果。

从公式看: 归一化输出范围在0-1之间,实现对原始数据的等比例缩放。在对变量无量纲化过程中仅仅与该变量的最大值和最小值这两个极端值有关。

从公式看:标准化输出范围是负无穷到正无穷,将数据变换为均值为0,标准差为1的分布,切记:并非一定是正态的。在无量纲化过程中利用了所有的数据信息,但是该方法在无量纲化后不仅使得转换后的各变量均值相同,且标准差也相同。

num_features:图像的通道数,也即(N, C, H, W)中的C的值。

eps:为数值稳定性而添加到分母上的值。默认值:1e-5。

momentum:一个用于运行过程中均值和方差的一个估计参数。表示动量参数,用于指定运算中移动均值和方差的计算方式。默认值为0.1。在训练过程中,会使用移动平均的方式来计算均值和方差,这个参数决定了移动平均的衰减率。

affine:一个布尔值,当设置为True时,此模块具有可学习的仿射参数。仿射变换是指对归一化后的数据进行缩放和平移操作,即乘以可学习的参数γ和加上可学习的偏置β。变量名是weight (初值1)和 bias(初值0).

track_running_stats:设为True时,BatchNorm层会统计全局均值running_mean (初值0)和方差running_var(初值1).

注意在BatchNorm中,用于更新running_var时,使用无偏样本方差即,但是在对batch进行归一化时,使用有偏样本方差,因此如果batch_size=1,会报错。

torch.nn.ReLU(inplace=False)

inplace = False 时,不会修改输入对象的值,而是返回一个新创建的对象

inplace = True 时,会修改输入对象的值,返回的对象存储地址相同,类似于C语言的址传递。

torch.nn.MaxPool2d(kernel_sizestride=Nonepadding=0dilation=1return_indices=Falseceil_mode=False)

kernel_size:表示做最大池化的窗口大小.

stride:窗口的移动步长,默认值是kernel_size。

padding:在两侧添加隐式负无穷大填充。

dilation:控制窗口中元素步幅的参数.

return_indices :布尔类型,返回最大值位置索引.多返回了一个位置信息。元素位置从0开始计数,6表示第7个元素,9表示第10个元素.

ceil_mode: 布尔类型,为True,用向上取整的方法,计算输出形状;默认是向下取整。

向下取整的符号 : 这个就是由 ceil_mode 控制的。

dilation的作用:


torch.nn.Sequential(*args: Module)

torch.nn.Sequential(arg: OrderedDict[strModule])

torch.nn.AdaptiveAvgPool2d(output_size)

自适应池化层。函数通过输入原始尺寸和目标尺寸,自适应地计算核的大小和每次移动的步长。

torch.nn.Linear(in_featuresout_featuresbias=Truedevice=Nonedtype=None)

ResNet(
  (conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)
  (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (relu): ReLU(inplace=True)
  (maxpool): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False)
  (layer1): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
    (1): BasicBlock(
      (conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (layer2): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (downsample): Sequential(
        (0): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): BasicBlock(
      (conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (layer3): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (downsample): Sequential(
        (0): Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): BasicBlock(
      (conv1): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (layer4): Sequential(
    (0): BasicBlock(
      (conv1): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (downsample): Sequential(
        (0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)
        (1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      )
    )
    (1): BasicBlock(
      (conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
      (relu): ReLU(inplace=True)
      (conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
      (bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
    )
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(1, 1))
  (fc): Linear(in_features=512, out_features=1000, bias=True)
)
class ResNet(nn.Module):

   def __init__(self, block, layers, num_classes=1000, zero_init_residual=False,
                groups=1, width_per_group=64, replace_stride_with_dilation=None,
                norm_layer=None):
       """
       block: 残差块类型,定义了BasicBlock与Bottleneck两种
		layers: 每个stage中残差块的数目,长度为4
   	num_classes: 类别数目
   	zero_init_residual:若为True,则将残差块的最后一个BN层初始化为0,
   	这样残差分支从0开始每一个残差分支,每一个残差块表现的像一个恒等映射
   	根据论文:网络可提升0.2%~0.3%
           """
       super(ResNet, self).__init__()
       if norm_layer is None:
           norm_layer = nn.BatchNorm2d
       self._norm_layer = norm_layer

       self.inplanes = 64
       self.dilation = 1
       if replace_stride_with_dilation is None:
           # each element in the tuple indicates if we should replace
           # the 2x2 stride with a dilated convolution instead
           replace_stride_with_dilation = [False, False, False]
       if len(replace_stride_with_dilation) != 3:
           raise ValueError("replace_stride_with_dilation should be None "
                            "or a 3-element tuple, got {}".format(replace_stride_with_dilation))
       self.groups = groups
       self.base_width = width_per_group
       self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3,
                              bias=False)
       self.bn1 = norm_layer(self.inplanes)
       self.relu = nn.ReLU(inplace=True)
       self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
       self.layer1 = self._make_layer(block, 64, layers[0])
       self.layer2 = self._make_layer(block, 128, layers[1], stride=2,
                                      dilate=replace_stride_with_dilation[0])
       self.layer3 = self._make_layer(block, 256, layers[2], stride=2,
                                      dilate=replace_stride_with_dilation[1])
       self.layer4 = self._make_layer(block, 512, layers[3], stride=2,
                                      dilate=replace_stride_with_dilation[2])
       self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
       self.fc = nn.Linear(512 * block.expansion, num_classes)

       for m in self.modules():
           if isinstance(m, nn.Conv2d):
               nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
           elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):
               nn.init.constant_(m.weight, 1)
               nn.init.constant_(m.bias, 0)

       # Zero-initialize the last BN in each residual branch,
       # so that the residual branch starts with zeros, and each residual block behaves like an identity.
       # This improves the model by 0.2~0.3% according to https://arxiv.org/abs/1706.02677
       if zero_init_residual:
           for m in self.modules():
               if isinstance(m, Bottleneck):
                   nn.init.constant_(m.bn3.weight, 0)
               elif isinstance(m, BasicBlock):
                   nn.init.constant_(m.bn2.weight, 0)

   def _make_layer(self, block, planes, blocks, stride=1, dilate=False):
       norm_layer = self._norm_layer
       downsample = None
       previous_dilation = self.dilation
       if dilate:
           self.dilation *= stride
           stride = 1
       if stride != 1 or self.inplanes != planes * block.expansion:
           downsample = nn.Sequential(
               conv1x1(self.inplanes, planes * block.expansion, stride),
               norm_layer(planes * block.expansion),
           )

       layers = []
       layers.append(block(self.inplanes, planes, stride, downsample, self.groups,
                           self.base_width, previous_dilation, norm_layer))
       self.inplanes = planes * block.expansion
       for _ in range(1, blocks):
           layers.append(block(self.inplanes, planes, groups=self.groups,
                               base_width=self.base_width, dilation=self.dilation,
                               norm_layer=norm_layer))

       return nn.Sequential(*layers)

   def _forward_impl(self, x):
       # See note [TorchScript super()]
       x = self.conv1(x)
       x = self.bn1(x)
       x = self.relu(x)
       x = self.maxpool(x)

       x = self.layer1(x)
       x = self.layer2(x)
       x = self.layer3(x)
       x = self.layer4(x)

       x = self.avgpool(x)
       x = torch.flatten(x, 1)
       x = self.fc(x)

       return x

   def forward(self, x):
       return self._forward_impl(x)

resnet18 50网络结构以及pytorch实现代码 - 简书

BasicBlock:

def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1):
    """3x3 convolution with padding"""
    return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
                     padding=dilation, groups=groups, bias=False, dilation=dilation)


def conv1x1(in_planes, out_planes, stride=1):
    """1x1 convolution"""
    return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)


class BasicBlock(nn.Module):
    expansion = 1

    def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,
                 base_width=64, dilation=1, norm_layer=None):
        """
        inplanes: 输入的通道树,int
        planes:
        stride:卷积层的步长
        downsample: 分支下采样(nn.Sequential)
        """
        super(BasicBlock, self).__init__()
        if norm_layer is None:
            norm_layer = nn.BatchNorm2d
        if groups != 1 or base_width != 64:
            raise ValueError('BasicBlock only supports groups=1 and base_width=64')
        if dilation > 1:
            raise NotImplementedError("Dilation > 1 not supported in BasicBlock")
        # 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

每个block里依次包含:conv3x3, bn, relu, conv3x3, bn。在forward中用out+=x实现短接。如果参数stride=2,则会在第一个conv3x3中出现下采样。那么需要赋值downsample,down sample也是一个3x3卷积。

  • 14
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: b'models.resnet18(pretrained=true)'是一个Pytorch中已经预训练好的ResNet18模型的加载方式。ResNet18是一个深度学习模型,通常用于图像分类和特征提取任务。预训练意味着该模型已经在大规模数据集上进行了训练,可以直接用于解决相应的任务,而不需要再次训练。 ### 回答2: models.resnet18(pretrained=true)是一个非常常见的深度学习模型,它是由微软研究院的Kaiming He等人在2016年提出的ResNet模型的一个变种。ResNet模型(Residual Neural Network)通过引入残差连接(residual connection)解决了深度神经网络随着层数的增加,出现的梯度消失问题和网络表现的退化问题。而ResNet18则是ResNet模型的一个相对较小的版本,具有18层卷积层。 在PyTorch中,通过调用models.resnet18(pretrained=true)可以直接加载训练好的ResNet18模型,即使用ImageNet数据集训练好的权重参数。这个参数可以直接用于图像分类、目标检测、语义分割等任务,也可以在其基础上进行微调来适应不同的任务场景。 当我们调用models.resnet18(pretrained=true)时,首先会下载一个已经在ImageNet数据集上预训练好的ResNet18模型。然后,根据我们传递给模型的输入数据尺寸,在模型的第一个卷积层中设置不同的卷积核尺寸和步幅,将输入数据进行卷积和池化操作得到特征图。接下来,模型会通过四个不同层数的残差块(Residual Block)来提取图像特征,其中每个残差块包括两个卷积层和一个跨通道的残差连接。最后,将提取到的图像特征通过全局平均池化操作得到一维特征向量,再通过一个全连接层输出最终的分类或回归结果。 总的来说,models.resnet18(pretrained=true)提供了一种简便的方法来加载预训练好的ResNet18模型,并且可以在此基础上进行进一步的微调,从而实现在图像分类、目标检测、语义分割等任务中的应用。 ### 回答3: models.resnet18(pretrained=True)是一个PyTorch预定义的深度卷积网络模型,其中包含18个卷积层、全局平均池化层和最后一层输出层。它是ResNet(Residual Network)系列中的一员,ResNet模型是一种非常流行的卷积神经网络模型,其最大的特点就是添加了Residual连接,可以解决深度神经网络训练过程中的梯度消失和梯度爆炸问题,从而提高了模型训练的效果和稳定性。 其中,参数pretrained=True表示使用在ImageNet上预训练的模型参数来初始化模型权重,这是一种迁移学习的方式。ImageNet是一个庞大的图像数据集,包含超过100万个带标签的图像,用于识别1000个不同的物体类别,预训练的模型参数已经对这些物体类别进行了学习和分类,因此可以迁移学习到其他的图像识别任务中,加速模型训练和提高模型准确率。在实际场景中,很难得到足够大的图像数据集来训练深度卷积神经网络,因此迁移学习是非常常用的一种技术。 最后,使用该方式预训练好的ResNet18模型是一种非常强大和高效的图像识别算法,可以应用于各种计算机视觉任务,如对象识别、场景理解、人脸识别等。在实践中,可以使用PyTorch中的其他库和函数,如torchvision.datasets和torch.utils.data.DataLoader来构建数据集,torch.optim和torch.nn等函数来定义损失和优化函数,通过反向传播算法更新参数来训练模型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值