딥러닝 파이토치 강좌, Faster R-CNN

본 강좌에서는 딥러닝을 활용한 객체 탐지(Object Detection) 기법 중 하나인 Faster R-CNN(Region-based Convolutional Neural Network)에 대해 다룹니다. 또한, PyTorch 프레임워크를 사용하여 Faster R-CNN을 구현하고 실제 데이터를 통해 학습시키는 과정을 설명하겠습니다.

1. Faster R-CNN 개요

Faster R-CNN은 이미지 내 객체를 탐지하는 데 있어 높은 정확도를 자랑하는 딥러닝 모델입니다. 이는 CNN(Convolutional Neural Network) 기반의 두 가지 주요 구성 요소인:

  • Region Proposal Network (RPN): 잠재적인 객체 영역을 제안하는 역할을 합니다.
  • Fast R-CNN: RPN에서 나온 영역들을 정제하여 최종 객체 클래스와 바운딩 박스를 예측합니다.

Faster R-CNN의 주요 강점은 RPN이 CNN의 기울기를 직접 공유하여 객체 제안을 수행하기 때문에 이전의 방법들보다 훨씬 빠르고 효율적이라는 점입니다.

2. Faster R-CNN의 작동 원리

Faster R-CNN은 다음과 같은 단계로 작동합니다:

  1. 입력 이미지를 CNN에 통과시켜 피쳐 맵(feature map)을 생성합니다.
  2. 피쳐 맵을 기반으로 RPN이 제안된 객체 영역(Region Proposals)을 생성합니다.
  3. 제안된 영역을 기반으로 Fast R-CNN이 각 영역의 클래스를 예측하고, 바운딩 박스를 보정합니다.

이러한 부분들은 모두 학습 과정에서 파라미터를 조정하기 때문에, 데이터가 잘 준비되어 있다면 높은 성능을 이끌어낼 수 있습니다.

3. 환경 설정

Faster R-CNN을 구현하기 위해 필요한 라이브러리는 다음과 같습니다:

  • torch: PyTorch 라이브러리
  • torchvision: 이미지 처리 및 전처리 기능을 제공
  • numpy: 배열 및 수치 계산에 필요한 라이브러리
  • matplotlib: 결과 시각화에 사용

이 외에도 데이터셋을 다루기 위해 torchvision.datasets에서 제공하는 데이터셋을 활용할 수 있습니다.

3.1. 라이브러리 설치

아래 코드를 통해 필요 라이브러리를 설치할 수 있습니다:

pip install torch torchvision numpy matplotlib

4. 데이터셋 준비

Faster R-CNN을 학습시키기 위해 사용할 데이터셋은 PASCAL VOC, COCO, 또는 직접 구축한 데이터셋일 수 있습니다. 여기에서는 COCO 데이터셋을 사용해 보겠습니다.

4.1. COCO 데이터셋 다운로드

COCO 데이터셋은 여러 공개된 소스에서 다운로드할 수 있으며, 이를 PyTorch의 Dataloader를 통해 쉽게 불러올 수 있습니다. 필요한 데이터셋은 [COCO 데이터셋 공식 웹사이트](https://cocodataset.org/#download)에서 다운로드할 수 있습니다.

5. Faster R-CNN 모델 구현

이제 PyTorch로 Faster R-CNN 모델을 구축해보겠습니다. PyTorch의 torchvision 패키지를 사용하면 기본 프레임워크를 손쉽게 활용할 수 있습니다.

5.1. 모델 로드

Pre-trained 모델을 로드하여 Transfer Learning을 수행할 수 있습니다. 이를 통해 학습 속도와 성능을 개선할 수 있습니다.


import torch
import torchvision
from torchvision.models.detection import FasterRCNN
from torchvision.models.detection.rpn import AnchorGenerator

# Pre-trained Faster R-CNN 모델 로드
model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)

# 모델의 분류기를 조정
num_classes = 91  # COCO 데이터셋의 클래수 수
in_features = model.roi_heads.box_predictor.cls_score.in_features
model.roi_heads.box_predictor = torchvision.models.detection.faster_rcnn.FastRCNNPredictor(in_features, num_classes)
    

5.2. 데이터 전처리

데이터를 모델에 맞춰 전처리하는 과정이 필요합니다. 이미지를 텐서로 변환하고, 정규화 과정을 수행해야 합니다.


from torchvision import transforms

transform = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
    

5.3. 데이터 로더 구성

PyTorch의 DataLoader를 사용하여 배치 단위로 데이터를 효율적으로 로드합니다.


from torch.utils.data import DataLoader
from torchvision.datasets import CocoDetection

dataset = CocoDetection(root='path/to/coco/train2017',
                         annFile='path/to/coco/annotations/instances_train2017.json',
                         transform=transform)

data_loader = DataLoader(dataset, batch_size=4, shuffle=True, collate_fn=lambda x: tuple(zip(*x)))
    

6. 모델 훈련

이제 모델을 훈련할 준비가 되었습니다. 옵티마이저와 손실 함수를 정의하고, 에폭을 설정하여 모델을 학습시킵니다.

6.1. 손실 및 옵티마이저 정의


device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
model.to(device)

params = [p for p in model.parameters() if p.requires_grad]
optimizer = torch.optim.SGD(params, lr=0.005, momentum=0.9, weight_decay=0.0005)
    

6.2. 훈련 루프


num_epochs = 10

for epoch in range(num_epochs):
    model.train()
    for images, targets in data_loader:
        images = list(image.to(device) for image in images)
        targets = [{k: v.to(device) for k, v in t.items()} for t in targets]
    
        # 기울기 초기화
        optimizer.zero_grad()
    
        # 모델의 예측 결과
        loss_dict = model(images, targets)
    
        # 손실 계산
        losses = sum(loss for loss in loss_dict.values())
    
        # 역전파
        losses.backward()
        optimizer.step()
    
    print(f"Epoch {epoch+1}/{num_epochs}, Loss: {losses.item()}")
    

7. 검증 및 평가

모델의 성능을 평가하기 위해 검증 데이터셋을 사용하여 학습된 모델을 테스트합니다.

7.1. 평가 함수 정의


def evaluate(model, data_loader):
    model.eval()
    list_of_boxes = []
    list_of_scores = []
    list_of_labels = []

    with torch.no_grad():
        for images, targets in data_loader:
            images = list(image.to(device) for image in images)
            outputs = model(images)
     
            # 결과 저장
            for output in outputs:
                list_of_boxes.append(output['boxes'].cpu().numpy())
                list_of_scores.append(output['scores'].cpu().numpy())
                list_of_labels.append(output['labels'].cpu().numpy())

    return list_of_boxes, list_of_scores, list_of_labels
    

8. 결과 시각화

모델의 객체 탐지 결과를 시각화하여 실제로 얼마나 잘 작동하는지 확인합니다.


import matplotlib.pyplot as plt
import torchvision.transforms.functional as F

def visualize_results(images, boxes, labels):
    for img, box, label in zip(images, boxes, labels):
        img = F.to_pil_image(img)
        plt.imshow(img)

        for b, l in zip(box, label):
            xmin, ymin, xmax, ymax = b
            plt.gca().add_patch(plt.Rectangle((xmin, ymin), xmax - xmin, ymax - ymin,
                                    fill=False, edgecolor='red', linewidth=3))
            plt.text(xmin, ymin, f'Class: {l}', bbox=dict(facecolor='yellow', alpha=0.5))

        plt.axis('off')
        plt.show()

# 이미지와 정답을 불러온 후 시각화
images, targets = next(iter(data_loader))
boxes, scores, labels = evaluate(model, [images])
visualize_results(images, boxes, labels)
    

9. 결론

이번 강좌에서는 Faster R-CNN을 PyTorch로 구현하는 방법을 알아보았습니다. 객체 탐지의 기본 원리와 RPN, Fast R-CNN의 작동 방식을 이해했으며, 학습과 검증, 시각화 과정을 통해 모델의 성능을 확인할 수 있었습니다. 실제 프로젝트에 활용하여 여러분의 데이터에 맞는 객체 탐지 모델을 구축해 보시기를 바랍니다.