
2025.03.01
Chapter 5. Basic of Pytorch
36. Pytorch Mnist - 이론 137. Pytorch Mnist - 이론 238. Pytorch Mnist - 이론 3import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from matplotlib import pyplot as plt
nn이라는 모듈에 있음.nn.functional에 저장되어 있음.optimtorchvision : 여러 데이터셋을 가지고 있는 모듈
Cuda가 가능하면Cuda사용

batch_size = 50
learning_rate = 0.001
epoch_num = 15
Mnist data set의 경우 약 60k 데이터가 있으니, 50으로 하면 1.2k 데이터 Epoch(에폭): 전체 데이터셋을 한 번 학습하는 횟수Batch Size(배치 크기): 한 번의 훈련(iteration)에서 사용할 데이터 개수Step(스텝, 반복 횟수): 한 epoch 동안 배치 단위로 훈련을 진행하는 횟수
skicit-learn에서 데이터를 불러오는 방식과 조금 상이하다.
shape을 확인하고 시작하는 습관이 중요해 보인다.

특히나
Pytorch유저들은class를 생성해서 학습하는 것을 보편적으로 생각한다.

코드분석
class CNN(nn.Module):
# PyTorch의 nn.Module을 상속해서 모델을 정의하는 부분.
# CNN이라는 이름의 **합성곱 신경망(Convolutional Neural Network, CNN)**을 설계하는 중.
def __init__(self):
super(CNN, self).__init__()
# 부모 클래스(nn.Module)의 생성자를 호출하여 PyTorch의 기능을 사용할 수 있게 함.
self.conv1 = nn.Conv2d(1, 32, 3, 1, padding='same')
# nn.Conv2d(in_channels=1, out_channels=32, kernel_size=3, stride=1, padding='same')
# in_channels=1: 입력 채널 수 (MNIST는 **흑백 이미지(1채널)**이므로 1)
# out_channels=32: 출력 채널 수 (32개의 필터를 사용)
# 필터 개수가 많을수록 더 복잡한 특징을 잡을 수 있음.
# kernel_size=3: 3×3 크기의 필터 사용
# 작은 커널(3×3)은 국소적인 특징을 잘 잡아냄.
# stride=1: 필터가 이동하는 간격 (한 번에 1픽셀씩 이동)
# padding='same': 입력과 출력 크기가 같도록 패딩 적용
# 입력이 28×28이면 출력도 28×28이 유지됨.
# 📏 크기 변화
# 입력 크기: (1, 28, 28) → (32, 28, 28)
# 이유: padding='same'이므로 크기가 유지됨.
self.conv2 = nn.Conv2d(32, 64, 3, 1, padding='same')
# 입력 채널 32, 출력 채널 64 → 더 많은 특징을 학습할 수 있음.
# 입력 크기: (32, 28, 28) → (64, 28, 28)
# 여전히 padding='same'이므로 크기 유지됨.
self.dropout = nn.Dropout2d(0.25)
# 과적합을 방지하기 위해 25%의 뉴런을 랜덤하게 제거(dropout).
self.fc1 = nn.Linear(3136, 1000)
self.fc2 = nn.Linear(1000, 10)
# fc1: 3136개의 입력 → 1000개 출력
# fc2: 1000개 → 10개 (숫자 0~9 예측)
------------------------------------------------------------
def forward(self, x):
# 모델이 입력 데이터를 받아서 어떻게 계산하는지를 정의하는 함수.
x = self.conv1(x)
x = F.relu(x)
x = F.max_pool2d(x, 2)
# conv1(x): (1, 28, 28) → (32, 28, 28)
# ReLU: 음수를 0으로 바꾸는 활성화 함수 적용
# MaxPooling(2): (32, 28, 28) → (32, 14, 14)
# 풀링 크기 2를 사용하여 크기 절반으로 축소.
x = self.conv2(x)
x = F.relu(x)
x = F.max_pool2d(x, 2)
# conv2(x): (32, 14, 14) → (64, 14, 14)
# ReLU 적용
# MaxPooling(2): (64, 14, 14) → (64, 7, 7)
x = self.dropout(x)
x = torch.flatten(x, 1)
# dropout 적용 (일부 뉴런 제거)
# flatten(x, 1): CNN의 2D 출력을 1D 벡터로 변환
# (64, 7, 7) → (64×7×7) = (3136,)
x = self.fc1(x)
x = F.relu(x)
x = self.fc2(x)
# fc1: (3136,) → (1000,)
# ReLU
# fc2: (1000,) → (10,) (출력 10개, 숫자 0~9 예측)
output = F.log_softmax(x, dim=1)
# 출력값을 확률 형태로 변환 (log softmax 사용)
# 크기: (batch_size, 10)


model = CNN().to(device)
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
criterion = nn.CrossEntropyLoss()
data = data.to(device)
target = target.to(device)
optimizer.zero_grad()
output = model(data)
loss = criterion(output, target)
loss.backward()
optimizer.step()
