Pytorch 모델 학습

2025. 4. 28. 22:27·Bootcamp_zerobase/Pytorch

2025.04.27

 

Part12. 파이토치

  • Chapter.03 간단한 Model 학습 시키기
    • 01_deeplearning Flow (1)
    • 02_deeplearning Flow (2) 
    • 03_deeplearning Flow (3)

 

Deeplearning Flow

데이터 Load 및 전처리

 

관련 패키지를 import하고, torch에서 제공하는 MNIST 데이터를 Load 한다.

DataLoader는 제너레이터 양식으로 불러진다.

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

## pytorch 관련 패키지
import torch
from torchvision import datasets, transforms
import torch.utils

batch_size = 32
## MNIST 데이터 Load

# "datasets/" : 데이터를 저장할 폴더 (없으면 만들어짐)
# download=True : 데이터가 없으면 자동으로 인터넷에서 다운로드. 있으면 다운로드 하지 않음.
# train=True : 훈련용 데이터를 쓰겠다는 의미 (False면 Test용 데이터)


train_loader = torch.utils.data.DataLoader(
    datasets.MNIST("datasets/",download=True, train=True,
                   transform=transforms.Compose([
                       transforms.ToTensor(),
                       transforms.Normalize(mean=(0.5,), std=(0.5,))
                   ])),
                   batch_size = batch_size,
                   shuffle = True,
    
)

 

  • transforms.ToTensor(  ) : (정규화) 
    • 데이터 타입 변환
      • (H, W, C) 형태의 PIL 이미지 또는 numpy 배열을
      • (C, H, W) 형태의 PyTorch Tensor로 변환해.
    • 값 스케일링
      • 원래 이미지 픽셀값은 0~255 (8-bit unsigned int)이잖아?
      • 이걸 0.0 ~ 1.0 사이로 나눈다.
      • 즉, pixel_value / 255.0 을 자동으로 해줌. (0~1사이)

 

 

  • transforms.Normalize( mean = (0.5,), std = (0.5,) ) : 왜하는가?? (표준화)
    • ToTensor()로 0~1 범위로 스케일만 했을 때, 데이터는 이렇게 분포할 수 있어:
      • 모든 값이 양수야 (0.0 ~ 1.0)
      • 평균은 대략 0.5쯤
      • 값들이 0을 중심으로 대칭적이지 않아
    • 이렇게 되면 문제가 생겨:
      • 뉴럴 네트워크에서 활성함수(ReLU, Sigmoid 등) 들이 작동할 때, 양수 방향으로 치우쳐.
      • 가중치 업데이트(=경사 하강법) 방향도 한쪽으로 치우쳐서, 학습 속도가 느려지고 최적점을 제대로 못 찾을 수도 있어.
    • Normalize(mean=0.5, std=0.5)를 하면:
      • 데이터 범위가 대략 [-1, 1]로 바뀌고
      • 평균은 0이 되고
      • 표준편차는 1이 돼
      • 장점:
        • 데이터가 0 주변에 고르게 퍼져 있음 → 뉴런이 양방향(양수/음수) 으로 고르게 활성화돼.
        • 경사하강법(optimizer)이 훨씬 빠르고 안정적으로 작동해.
        • Vanishing Gradient 같은 문제도 어느 정도 완화할 수 있어.
    • "mean=0.5, std=0.5를 주는 건 [0~1] 스케일을 [-1, 1]로 맞추기 위해서다."
      • 현재 ToTensor( )를 통해서 픽셀값들이 0~1사이 값으로 맞추어져있음.
      • 표준화를 하기 위해선, ${output} = \frac{input - mean}{std}$ 형태인데, input이 0인 경우 결과값은 -1, input이 1인 경우 결과값은 1이기 때문에, mean 과 std를 0.5로 설정한다.

 

 

표준화 (Normalize) 과정

문제: [3, 5, 7, 8] 이라는 데이터를 Normalize(평균 0, 표준편차 1) 하면 어떻게 되는지.

 

1. 평균(mean) 계산

평균은 값들의 합을 데이터 개수로 나눈 거야.

$${mean} = \frac{3+5+7+8}{4} = \frac{23}{4} = 5.75$$

 

2. 표준편차(std) 계산

표준편차는 각 값과 평균의 차이를 제곱하고, 그걸 평균낸 다음 루트 씌운 거야.

 

각 값과 평균의 차이를 제곱

  • (3 - 5.75)² = (-2.75)² = 7.5625
  • (5 - 5.75)² = (-0.75)² = 0.5625
  • (7 - 5.75)² = (1.25)² = 1.5625
  • (8 - 5.75)² = (2.25)² = 5.0625

평균낸다

$${var} = \frac{7.5625 + 0.5625 + 1.5625 + 5.0625}{4} = \frac{14.75}{4} = 3.6875$$

 

 

루트 씌운다 (표준편차)

$${std} = \sqrt{3.6875} \approx 1.920$$

 

 

3. 각 값을 Normalize 한다

Normalize 공식은:

$${normalized\_value} = \frac{\text{원래 값} - \text{mean}}{\text{std}}$$​

 

계산하면:

  • (3 - 5.75) / 1.920 ≈ -1.432
  • (5 - 5.75) / 1.920 ≈ -0.391
  • (7 - 5.75) / 1.920 ≈ 0.651
  • (8 - 5.75) / 1.920 ≈ 1.172

 

최종 결과

 

원래값 정규화 값
3 -1.432
5 -0.391
7 0.651
8 1.172

 

[3, 5, 7, 8]
👉 평균 5.75, 표준편차 약 1.920
👉 Normalize 하면 [-1.432, -0.391, 0.651, 1.172]

이렇게 각각 값이 변환돼! 🎯

 

 

 

데이터 확인

Pytorch에서는 TensorFlow와 이미지를 표현하는데 있어서 차이점이 있음 (차원, 채널)

  • TensorFlow : (batch, height, width, channel)   → 마지막 차원이 흑백이면 1, 컬러면 3 이었던 차원요소
  • Pytorch : (batch, channel, heightm width) → 컬러와 흑백을 표현하는 차원이 앞에 있다.

 

 

일단 batch-size만큼 32개의 데이터를 불러오게 되고, label 값이 같이 들어있는 자료형태로 반환된다.

images 와 labels에 할당하고 각각의 shape을 확인하면 아래와 같다.

 

 

 

iterater 실행 참고.

하지만 대부분 반복문을 이용해서 데이터를 꺼낸다.

 
# DataLoader로부터 배치를 순차적으로 가져오기
for batch in train_loader:
    # 각 배치에 대해 처리
    print(batch)
 

 

학습할때는 굳이 꺼내지 않아도 자동으로 꺼내서 학습된다.

 

 

 

 

 

 

 

 

 

iter에서 불러온 첫번째 배치의 아무 데이터를 꺼내서 사진을 확인해보면....

images[18].shape
	>> torch.Size([1, 28, 28])
    
## squeeze 를 통해서 첫번째 차원 축소
image = torch.squeeze(images[18])
image.shape
	>> torch.Size([28, 28])


image = image.numpy()

## 커널충돌 설정
import os
os.environ['KMP_DUPLICATE_LIB_OK'] = 'True'

plt.imshow(image)
plt.title(labels[18].numpy())
plt.axis('off')
plt.tight_layout()
plt.show()

 

 

 

 

 

pytorch 모델정의

tensorflow 처럼 모델정의하기 위해 필요한 패키지를 import 한다.

from torch import nn
import torch.nn.functional as f
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(
            in_channels=1, out_channels=32, kernel_size=5, stride=1, padding=2)
        self.conv2 = nn.Conv2d(
            in_channels=32, out_channels=64, kernel_size=5, stride=1, padding=2)
        
        # Linear 사용 시 채널계산 필요
            # 데이터 1X28X28

            # conv1 = 32(out_channels) X 28X28 (출력크기 계산 참조)
            # maxpool = 32 X 14 X 14 (커널 2X2, stride 2 → 절반으로 줄어듬)
            # ( input - 커널 + 2 X padding ) / stride = ( 28 - 2 + 2 X 1 ) / 2 = 14

            # conv2 = 64(out_channels) X 14X14
            # axpool = 64 X 7 X 7 (커널 2X2, stride 2 → 절반으로 줄어듬)
            # ( input - 커널 + 2 X padding ) / stride = ( 14 - 2 + 2 X 1 ) / 2 = 7
            # 64 X 7 X 7 

        self.fc1 = nn.Linear(64*7*7, 256)
        self.fc2 = nn.Linear(256, 10)   # labels은 10개 (0 ~ 9)


    def forward(self, x):
        
        #F.max_pool2d(input, kernel_size, stride, padding=0, dilation=1, ceil_mode=False, return_indices=False)
        x = F.relu(self.conv1(x))
        x = F.max_pool2d(x, 2, 2)

        x = F.relu(self.conv2(x))
        x = F.max_pool2d(x, 2, 2)

        x = x.reshape(x.size(0), -1)    #Flatten
        x = F.relu(self.fc1(x))
        x = self.fc2(x)

        return F.log_softmax(x, dim=1)

 

 

 

모델 선언

# device 설정
device = torch.device("cuda" if torch.cuda.is_available else "cpu")


model = Net().to(device)
print(model)

 

 

 

 

 

padding 값에 따른 출력크기 변화 (출력크기 계산)

 

 

 

 

 

 

 

학습로직 구현

Pytorch에서는 model을 Training 모드로 변경 후 Training 할 수 있다. 앞서 모델을 확인하면, 아래와 같이 확인할 수 있다.

 

import torch.optim as optim

optimizer = optim.SGD(model.parameters(), 0.0003)


for epoch in range(10):
    model.train()   #train mode 선언

    for batch_idx, (data, target) in enumerate(train_loader):
        data, target = data.to(device), target.to(device)   #cuda 설정

        optimizer.zero_grad()   # 초기화 (누적값 초기화화)
        
        output = model(data)    # 예측측
        
        # cross_entropy X (one_hot encoding 안되어 있음)
        # nll_loss = negative log likelihood loss 
        loss = F.nll_loss(output, target) # 순서 : 예측값, 정답값

        loss.backward()     # 오차 역전파파
        optimizer.step()    #loss에서 계산한 미분값(가중치) 업데이트

        print(f'batch : {batch_idx},  loss : {loss.item()}')

 

 

 

이제 evaluation을 진행해보면, 우선 train 모드를 끄고 eval() 모드를 설정한 뒤 진행해야 한다.

model.eval()
test_loss = []

with torch.no_grad():
    for data, target in test_loader:
        data, target = data.to(device), target.to(device)   #cuda 설정
        output = model(data)    # 예측
        test_loss.append(F.nll_loss(output, target).item())


# batch 의 평균 Loss
mean_loss = sum(test_loss) / (len(test_loader.dataset) // 32)

 

 

 

단. test 데이터도 마찬가지로 "cuda"로 보내주어야 학습이 된다. 모델 선언 및 학습 시 "cuda"에서 학습했기 때문이다.

'Bootcamp_zerobase > Pytorch' 카테고리의 다른 글

Pytorch 데이터 다루기  (1) 2025.05.28
Pytorch의 모델링 및 학습  (0) 2025.05.18
최적화 및 미분  (0) 2025.04.27
Tensor 다루기  (1) 2025.04.27
Pytorch #4 : 식물잎 사진으로 질병분류  (0) 2025.04.26
'Bootcamp_zerobase/Pytorch' 카테고리의 다른 글
  • Pytorch 데이터 다루기
  • Pytorch의 모델링 및 학습
  • 최적화 및 미분
  • Tensor 다루기
Loft_mind
Loft_mind
건축 전공자의 전공 갈아타기
  • Loft_mind
    오늘의 설계
    Loft_mind
  • 공지사항

    • 분류 전체보기 (36)
      • Bootcamp_zerobase (35)
        • Pytorch (12)
        • Image Augmentation (2)
        • YOLO & RNN (4)
        • Git & GitHub (2)
        • Tensorflow (11)
        • OpenCV (4)
      • Architecture (0)
  • 블로그 메뉴

    • 홈
    • 태그
  • 태그

    역전파
    제로베이스
    subclass
    zerobase
    deeplearning
    ResNet
    image augmentation
    tensorflow
    mnist
    ComputerVision
    컴퓨터 비전
    pytorch
    VGGNET
    정규표현식
    bash
    rnn
    PIL
    autoencoders
    CNN
    git
    github
    opencv
    YOLO
    RE
  • hELLO· Designed By정상우.v4.10.3
Loft_mind
Pytorch 모델 학습
상단으로

티스토리툴바