Deep Learning #12 CNN 실습

김서영·2025년 6월 16일

딥러닝

목록 보기
12/13
post-thumbnail

1. nn.Conv2d()

계산 효율을 위해 다양한 추가 옵션을 사용할 수 있음

  • in_channels(필수) : 입력 채널 수
  • out_channels(필수) : 출력 채널 수
  • kernel_size(필수) : 커널(필터)의 크기
  • stride : 필터가 이동하는 보폭(기본값 :1)
  • padding : 입력 가장자리에 추가할 것(기본값 : zero padding)

2. nn.Pool2d()

이미지에서 대표값을 추출해 출력의 크기를 줄이는 연산으로,
불필요한 정보를 제거하고 계산량을 줄이는데 사용

MaxPooling : nn.MaxPool2d()
AveragePooling : nn.AvgPool2d()

  • kernel_size(필수) : 풀링 영역의 크기(ex. 2 -> 2X2)
  • stride : 풀링 영역의 이동 간격 (기본값 : kernel_size)
  • padding : 입력 주변에 추가하는 zero-padding의 크기 (기본값 : 0)

3. CNN 연산 후 size 구하기

Convolution layer 통과 후 FCN을 붙여 최종 출력하는데,
이때 입력의 크기를 알아야 Linear layer를 만들 수 있음

Option에 따른 size 구하기

Example 1. 28*28, kernel=3, stride=1, padding=1

Example 2. 32*32, kernel=5, stride=2, padding=0

특별한 옵션 없을 시 계산 후 내림 연산으로 출력


Pooling에 따른 size 구하기

Example 3. 28*28, kernel=2, stride=2, padding=0, Maxpool2d

실습. Pytorch를 이용하여 강아지, 고양이 이미지 분류

Step 1. Dataset

이미지 폴더를 이용하여 데이터셋 불러오기 및 나누기

from torchvision.datasets import ImageFolder
from sklearn.model_selection import train_test_split

dataset = ImageFolder('train_test_set_small')
train_data, test_data = train_test_split(dataset.imgs, test_size=0.2, random_state=42)

Step 2. Data Loader

2-1) Batch size만큼 RGB 데이터를 출력하는 데이터셋 클래스 만들기

  • init : 초기화
  • len : 데이터의 길이 파악용
  • getitem : 데이터 출력 방식 (item : 인덱스의 번호)
class ImageLoader(Dataset):
  def __init__(self, dataset):
    self.dataset=dataset

  def __len__(self):
    return len(self.dataset)
  
  def __getitem__(self, item):
    image=cv2.imread(self.dataset[item][0])
    image=cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    image=cv2.resize(image,(28,28))
    image=image.reshape(28*28)
    label=self.dataset[item][1]
    return image, label
    
train_dataset=ImageLoader(train_data)
test_dataset=ImageLoader(test_data)

2-2) 데이터 불러오기 방식 설정

train_loader=DataLoader(train_dataset, batch_size=16, shuffle=True)

for img, label in train_loader:
    break

img.shape

Step 3. 신경망 만들기

Pytorch에서 nn.Conv2d()/Maxpool2d() 를 사용하여 만들 수 있음

class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        self.conv1=nn.Conv2d(3,4)
        self.pool=nn.MaxPool2d(2,2)

    def forward(self,x):
        x=self.pool(self.relu(self.fc1(x)))
        return x

Step 4. 하이퍼 파라미터 정의

class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        
        self.conv1 = nn.Conv2d(in_channels=3, out_channels=16, kernel_size=3, padding=1)
        self.pool = nn.MaxPool2d(kernel_size=2, stride=2)

        self.conv2 = nn.Conv2d(16, 32, kernel_size=3, padding=1)
        self.conv3 = nn.Conv2d(32, 64, kernel_size=3, padding=1)

        # Fully connected layer
        self.fc1 = nn.Linear(64 * 3 * 3, 512)
        self.dropout = nn.Dropout(0.5)
        self.fc2 = nn.Linear(512, 2)

    def forward(self, x):
        x = F.relu(self.conv1(x))  # 28x28x3 → 28x28x16
        x = self.pool(x)           # → 14x14x16

        x = F.relu(self.conv2(x))  # → 14x14x32
        x = self.pool(x)           # → 7x7x32

        x = F.relu(self.conv3(x))  # → 7x7x64
        x = self.pool(x)           # → 3x3x64

        x = x.view(-1, 64 * 3 * 3) # Flatten
        x = F.relu(self.fc1(x))    # → 512
        x = self.dropout(x)
        x = self.fc2(x)            # → 2

        return x

Step 5. Model 학습

model = SimpleCNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

num_epochs = 10
for epoch in range(num_epochs):
    model.train()
    total_loss = 0

    for images, labels in train_loader:

        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        total_loss += loss.item()

    print(f"Epoch [{epoch+1}/{num_epochs}], Loss: {total_loss:.4f}")
profile
안녕하세요 :)

0개의 댓글