resnet18模块结构图
时间: 2025-05-03 07:43:07 浏览: 19
### ResNet18 的模块结构图与架构详解
ResNet18 是一种基于残差网络 (Residual Network) 的深度学习模型,其核心特点是通过引入 **残差连接** 来缓解深层神经网络训练过程中可能出现的梯度消失问题。以下是关于 ResNet18 模块结构及其架构的具体分析。
#### 1. 基本概念
ResNet18 属于 ResNet 家族的一员,具有 18 层深度。这里提到的层数是指权重层的数量,即包括卷积层和全连接层,但不包括批量归一化层 (Batch Normalization Layer) 和池化层 (Pooling Layer)[^1]。
#### 2. 整体架构概述
ResNet18 的整体架构由以下几个部分组成:
- **输入层**: 接收图像数据作为输入。
- **初始卷积层**: 使用一个 $7 \times 7$ 卷积核进行特征提取,并配合最大池化操作减少空间维度。
- **四个阶段的残差块组**:
- `Conv2_x`: 包含两个基本残差块。
- `Conv3_x`: 包含两个基本残差块。
- `Conv4_x`: 包含两个基本残差块。
- `Conv5_x`: 包含两个基本残差块。
- **全局平均池化层**: 将最后一个特征图转换为固定长度向量。
- **全连接层**: 输出分类结果。
#### 3. 残差块设计
ResNet18 中使用的是一种简单的两层残差块 (Basic Block),每一块包含以下组件:
- 两次连续的 $3 \times 3$ 卷积操作。
- 批量归一化 (Batch Normalization)。
- ReLU 激活函数。
对于某些特定位置的残差块(如每个阶段的第一个块),会采用虚线残差结构来调整输入张量的空间尺寸和通道数量[^3]。这些结构调整通常涉及步长为 2 的卷积操作以及零填充或投影变换。
#### 4. 各阶段详细参数变化
| 阶段 | 输入形状 | 输出形状 | 特征描述 |
|------------|------------------|-----------------|--------------------------------------------------------------------------|
| Conv1 | $H \times W \times C_{in}$ | $\frac{H}{2} \times \frac{W}{2} \times 64$ | 初始卷积层 ($7 \times 7$, stride=2), 后接 Max Pooling |
| Conv2_x | $\frac{H}{2} \times \frac{W}{2} \times 64$ | $\frac{H}{2} \times \frac{W}{2} \times 64$ | 两个 Basic Blocks, 不改变分辨率 |
| Conv3_x | $\frac{H}{2} \times \frac{W}{2} \times 64$ | $\frac{H}{4} \times \frac{W}{4} \times 128$ | 第一个 block 调整分辨率至一半并增加 channel 至 128 |
| Conv4_x | $\frac{H}{4} \times \frac{W}{4} \times 128$ | $\frac{H}{8} \times \frac{W}{8} \times 256$ | 第一个 block 再次减半分辨率并将 channel 提升到 256 |
| Conv5_x | $\frac{H}{8} \times \frac{W}{8} \times 256$ | $\frac{H}{16} \times \frac{W}{16} \times 512$ | 最终 stage 减少分辨率至原始四分之一,channel 达到最高值 |
以上表格展示了不同阶段间的数据流动情况及主要特性转变过程。
#### 5. PyTorch 实现代码示例
下面是 ResNet18 的简化版 PyTorch 实现代码片段:
```python
import torch.nn as nn
class BasicBlock(nn.Module):
expansion = 1
def __init__(self, in_channels, out_channels, stride=1, downsample=None):
super(BasicBlock, self).__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(out_channels)
self.relu = nn.ReLU(inplace=True)
self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(out_channels)
self.downsample = downsample
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
class ResNet18(nn.Module):
def __init__(self, num_classes=1000):
super(ResNet18, self).__init__()
self.inplanes = 64
self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, bias=False)
self.bn1 = nn.BatchNorm2d(64)
self.relu = nn.ReLU(inplace=True)
self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
self.layer1 = self._make_layer(64, blocks=2, stride=1)
self.layer2 = self._make_layer(128, blocks=2, stride=2)
self.layer3 = self._make_layer(256, blocks=2, stride=2)
self.layer4 = self._make_layer(512, blocks=2, stride=2)
self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
self.fc = nn.Linear(512 * BasicBlock.expansion, num_classes)
def _make_layer(self, planes, blocks, stride):
layers = []
downsample = None
if stride != 1 or self.inplanes != planes * BasicBlock.expansion:
downsample = nn.Sequential(
nn.Conv2d(self.inplanes, planes * BasicBlock.expansion, kernel_size=1, stride=stride, bias=False),
nn.BatchNorm2d(planes * BasicBlock.expansion),
)
layers.append(BasicBlock(self.inplanes, planes, stride, downsample))
self.inplanes = planes * BasicBlock.expansion
for _ in range(1, blocks):
layers.append(BasicBlock(self.inplanes, planes))
return nn.Sequential(*layers)
def forward(self, x):
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
```
此代码定义了一个完整的 ResNet18 结构,包含了所有的必要组成部分。
---
阅读全文
相关推荐


















