forward() 의 역할 정리 노트

JJang-404·2025년 11월 26일

1. forward()가 하는 일

  1. 입력 → 연산 → 출력
    forward() 안에서 self.conv1, self.pool, self.upconv 같은 레이어를 차례대로 호출해 입력 x를 변형시킵니다.

    x = torch.relu(self.conv1(x))   # [B, 32, 128, 128]
    x = self.pool(x)                # [B, 32, 64, 64]
    x = self.upconv(x)              # [B, 3, 128, 128]
    return x
  2. 계산 그래프 기록
    forward() 안에서 수행되는 모든 연산(Conv, Pool, ReLU 등)은 autograd에 의해 자동으로 기록됩니다.
    따라서 나중에 손실(loss)에 대해 loss.backward()를 호출하면, autograd가 이 그래프를 따라 역전파(Back‑Propagation)를 수행해 파라미터에 대한 기울기를 계산합니다.

  3. 모델 호출
    실제로 모델을 사용하려면 output = model(input)처럼 model(input) 로 호출합니다.
    nn.Module 내부의 __call__ 메서드가 먼저 실행되고, 그 안에서 self.forward()가 호출됩니다.
    그래서 보통 model.forward() 를 직접 호출할 필요는 없으며, model(x) 를 쓰는 것이 관례입니다.

1-1. 왜 [B, 32, 128, 128] 이 나오는가?

차원의미계산식 (conv1)
B배치 크기 (Batch Size)입력에서 그대로 전달
32feature map(채널) 수conv1 가 out_channels=32 로 정의되었으므로 32개의 채널을 생성
128높이H_out = floor((H_in + 2·padding – kernel_size)/stride + 1)
입력 높이 H_in = 128, padding = 1, kernel = 3, stride = 1 → 128
128너비위와 동일 (W_in = 128)

입력이 [B, 3, 128, 128] 인 경우

x = torch.randn(B, 3, 128, 128)        # 예시 입력
x = torch.relu(self.conv1(x))          # conv1 -> [B, 32, 128, 128]
  • conv13채널(입력)32채널(출력) 으로 바꾸고,
  • padding=1, stride=1 으로 인해 공간 크기(HxW) 가 변하지 않음 → 128x128.

주의: 입력이 다른 크기(예: 224x224)라면, conv1 후에도 같은 공식을 적용해 다른 HxW 가 나오게 됩니다.

1-2. B 가 무엇인가?

B배치 크기를 나타내는 차원입니다.

  • 배치란 한 번에 모델에 넣는 이미지(또는 샘플)의 개수입니다.
  • B 값은 학습 중에 자유롭게 정할 수 있으며, 일반적으로 8, 16, 32, 64 등으로 설정합니다.

예시:

B입력 텐서 모양 (예시)의미
1[1, 3, 128, 128]한 장의 이미지 (테스트/추론 시)
32[32, 3, 128, 128]한 번에 32장의 이미지 (훈련 시)

실제 사용 예시

batch = 32
input_imgs = torch.randn(batch, 3, 128, 128)   # [32, 3, 128, 128]
output = model(input_imgs)                     # output shape -> [32, 3, 128, 128]

1-3. FCN 특성 때문인가?

  • FCN(Fully Convolutional Network) 은 완전 연결(FC) 레이어 없이 컨볼루션만 사용하기 때문에, 공간 해상도를 그대로 유지하거나 필요에 따라 변형할 수 있습니다.
  • 하지만 conv1 뒤에 MaxPool2d(2,2) 를 넣었으니, 공간 해상도는 2배로 감소됩니다.
  • 그 후 ConvTranspose2d(업컨볼루션) 로 2배로 증가시켜 원래 해상도로 복원합니다.

즉, [B, 32, 128, 128] 형태는 컨볼루션 연산과 파라미터(채널 수, 커널 크기, padding, stride) 설정에 의해 결정되며, FCN이라서만 그런 것이 아니라 일반적인 CNN에서도 동일한 규칙이 적용됩니다.

4. 한 줄씩 이해하기

x = torch.relu(self.conv1(x))  # conv1 : 3→32 채널, H,W = 128→128 (stride=1, padding=1)
  • conv1nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1) 로 정의되었습니다.
  • 입력의 높이와 너비는 다음 공식으로 보존됩니다.
    H_out = (H_in + 2*padding - kernel_size) // stride + 1
    W_out 역시 같은 계산.
x = self.pool(x)               # MaxPool2d(2,2) → H,W = 128→64 (2배 축소)
x = self.upconv(x)             # ConvTranspose2d(32, 3, kernel_size=2, stride=2) → H,W = 64→128 (2배 확대)

결과적으로 최종 출력은 원본 이미지와 동일한 해상도(128x128) 가지만 채널 수는 다시 3(RGB)으로 바뀝니다.


요약

항목설명
B배치 크기(한 번에 넣는 이미지 개수)
32conv1 가 생성한 feature map(채널) 수
128 × 128입력 해상도(높이 × 너비) → conv1 에서 그대로 유지
FCNFCN이란 풀링 없이(또는 필요에 따라) 공간 해상도를 보존/복원하는 구조이지만, 실제 차원 변화는 커널, stride, padding, pooling 설정에 따라 결정

2. forward()train() / eval() 모드

  • model.train() : Dropout, BatchNorm 같은 레이어가 학습 모드로 동작하도록 설정합니다.
  • model.eval() : 동일 레이어가 평가(추론) 모드로 동작하도록 설정합니다.

이러한 모드 전환은 forward() 안에서 self.training 플래그를 확인해 조건부 로직을 넣을 때 사용됩니다.
예를 들어:

def forward(self, x):
    if self.training:
        x = torch.dropout(x, p=0.5, training=True)
    return x

하지만 forward() 그 자체가 학습/추론 모드에 관계없이 순전파 로직만 수행합니다.


3. 실제 학습 루프 예시

model = FCN()
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)

for epoch in range(num_epochs):
    for inputs, targets in dataloader:      # inputs: [B,3,H,W], targets: [B, H, W] (클래스 라벨)
        optimizer.zero_grad()               # 기울기 초기화
        outputs = model(inputs)             # <‑‑ forward() 실행
        loss = criterion(outputs, targets)  # 손실 계산
        loss.backward()                     # 역전파(Back‑Propagation) 실행
        optimizer.step()                    # 파라미터 업데이트

forward() 는 여기서 outputs = model(inputs) 를 통해서만 호출됩니다.
loss.backward() 가 호출될 때 autograd가 forward() 에서 생성된 연산 그래프를 따라 기울기를 계산합니다.


4. 요약

용어의미
forward()입력 데이터를 받아서 레이어를 순서대로 적용한 뒤, 출력을 반환하는 함수. (순전파)
backward()손실에 대한 기울기를 계산하는 함수. autograd가 forward() 에서 기록된 연산 그래프를 이용해 자동으로 수행.
model(x)nn.Module__call__ 메서드가 forward() 를 호출. (일반적으로 이렇게 사용)

따라서 forward()는 바로 “순전파”를 담당하는 함수이며, 학습 루프 안에서 model(inputs) 로 호출하면 자동으로 실행됩니다.

profile
V I S I O N _ E N G I N E E R

0개의 댓글