다음은 데이터로더를 이용하여 메모리로 불러온 훈련 데이터셋의 이미지 크기와 레이블에 대한 출력 결과입니다.
torch.Size([32, 3, 224, 224]) tensor([0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1])
이제 ResNet의 전체 네트워크 구성을 위해 그것을 구성하는 기본 블록과 병목 블록에 대한 코드를 먼저 살펴보겠습니다. 먼저 기본 블록은 ResNet18, ResNet34에서 사용되며 합성곱(3×3) 두 개로 구성됩니다.
코드 6-73 기본 블록 정의
class BasicBlock(nn.Module):
expansion = 1
def __init__(self, in_channels, out_channels, stride=1, downsample=False):
super().__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3,
stride=stride, padding=1, bias=False) ------ 3×3 합성곱층
self.bn1 = nn.BatchNorm2d(out_channels)
self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3,
stride=1, padding=1, bias=False) ------ 3×3 합성곱층
self.bn2 = nn.BatchNorm2d(out_channels)
self.relu = nn.ReLU(inplace=True)
if downsample: ------ ①
conv = nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride, bias=False)
bn = nn.BatchNorm2d(out_channels)
downsample = nn.Sequential(conv, bn)
else:
downsample = None
self.downsample = downsample
def forward(self, x):
i = x
x = self.conv1(x)
x = self.bn1(x)
x = self.relu(x)
x = self.conv2(x)
x = self.bn2(x)
if self.downsample is not None:
i = self.downsample(i)
x += I ------ ②
x = self.relu(x)
return x