평행이동 불변성
지역화된 패턴이 이미지의 어떤 위치에 있더라도 동일하게 출력에 영향을 주는 것.
행렬로 평행이동 불변성 효과를 주려면 다소복잡한 가중치 패턴을 구현해야한다.
convolution 이미지에 대해 지역적인 평생이동 불변성을 보장하는 선형연산.
이산 컨볼루션은 2차원 이미지에 가중치 행렬을 스칼라곱을 수행하는 것으로 가중치 행렬. kernel 입력의 모든 이웃에 수행된다.
nn.Conv1d는 시계열용이고 nn.Conv2d 는 이미지용, nn.Conv3d 는 용적 데이터나 동영상용이다
전체 이미지를 돌며 해당 가중치를 최적화하기 때문에부분 패턴을 찾는 훨씬 더 작은 모델을 만들었다
이미지의 경계에 값이 0인 가짜 핅셀을 ghost 패딩해주는 기능을 제공한다. padding
import torch
import torch.nn as nn
# 입력 이미지 (배치크기=1, 채널=1, 높이=28, 너비=28)
x = torch.randn(1, 1, 28, 28)
# Conv2d
conv = nn.Conv2d(
in_channels=1, # 입력 채널
out_channels=16, # 출력 채널(필터 개수)
kernel_size=3, # 3×3 커널
stride=1,
padding=1 # 가장자리에 0을 한 칸 추가
)
y = conv(x)
print(x.shape)
print(y.shape)
다운샘플링
이미지의 크기를 줄여 계산량을 감소시키고 중요한 특징만 남기기 위해 수행
평균풀링을 하거나최댓값 맥스 풀링, n번째 픽셀만 계산하기의 방법이있으나 현재 맥스풀링의 접근방법이 가장 널리 사용된다.
import torch
import torch.nn as nn
# (배치, 채널, 높이, 너비)
x = torch.randn(1, 1, 28, 28)
pool = nn.MaxPool2d(kernel_size=2)
y = pool(x)
print(x.shape)
print(y.shape)
nn.module PyTorch에서 모든 신경망 모델의 부모(기반) 클래스, 직접 모델을 만들 때 반드시 상속받는 클래스 nn.module를 서브 클래싱하려면 먼저 forward 함수를 정의해 모듈로 입력을 전달하고 출력을 반환하게 해야한다.
먼저 init으로 생성자를 호출하고 forward 함수를 정의해 모듈로 입력을 전달하고 출력을 반환하게 해야한다.
파이토치에서는 표준 torch 연산을 사용하면 자동미분 기능이 자동으로 역방향 경로를 만들어줌으로 nn.Module에서는 backward 가 필요없다.
import torch
import torch.nn as nn
# 사용자 정의 신경망
class MyModel(nn.Module):
def __init__(self):
super().__init__() # nn.Module 초기화
self.fc = nn.Linear(4, 2) # 입력 4개 → 출력 2개
def forward(self, x):
x = self.fc(x) # 순전파(Forward)
return x
# 모델 생성
model = MyModel()
# 입력 데이터와 정답
x = torch.randn(3, 4) # 배치 크기 3
target = torch.tensor([0, 1, 0])
# 손실 함수
criterion = nn.CrossEntropyLoss()
# 순전파
output = model(x)
# 손실 계산
loss = criterion(output, target)
# 역전파 (Autograd가 자동 수행)
loss.backward()
print("출력:\n", output)
print("손실:", loss.item())
파이토치는 모든 모듈에 대한 함수형을 제공한다.
torch.nn.fuctional은 nn에서찾을 수있는 모듈과 동일한 함수를 많이제공한다.
torch.nn은 학습 가능한 계층을 포함한 모듈(Module) API이고, torch.nn.functional은 활성화 함수, 풀링, 손실 함수 등 다양한 연산을 함수 형태로 제공하는 API
import torch
import torch.nn as nn
import torch.nn.functional as F
# nn.Module을 상속받아 모델 생성
class CNN(nn.Module):
def __init__(self):
super().__init__()
# 학습할 가중치를 가지는 계층 → nn 사용
self.conv = nn.Conv2d(
in_channels=1,
out_channels=16,
kernel_size=3
)
self.fc = nn.Linear(
16 * 26 * 26,
10
)
def forward(self, x):
# Conv2d : nn.Module
x = self.conv(x)
# ReLU : torch.nn.functional
x = F.relu(x)
# Flatten
x = x.view(x.size(0), -1)
# Linear : nn.Module
x = self.fc(x)
# Softmax : torch.nn.functional (확률 출력용)
x = F.softmax(x, dim=1)
return x
# 모델 생성
model = CNN()
# 입력 이미지
# (배치 크기, 채널, 높이, 너비)
x = torch.randn(4, 1, 28, 28)
# 순전파
output = model(x)
print(output.shape)
print(output)
정규화
모델이 수렴하고 일반화하도록 돕는방법
- 항을 조작해서 모델의 가중치가 상대적으로 작게만들어 훈련을 통해 증가할 수 있는 크기를 제한한다. 큰 가중치에 페널티를 부과하는 셈
- 입력 하나에 너무 너무 의존하지않기 드랍아웃
- 활성함수억제하기 배치 정규화 nn.BatchNorm1D, nn.BatchNorm2d, BatchNorm3d몯ㅍㄹ로 각 입력 차원에 따라 골라서 사용한다.
import torch
import torch.nn as nn
import torch.nn.functional as F
class CNN(nn.Module):
def __init__(self):
super().__init__()
self.conv = nn.Conv2d(
1, 16, 3
)
# Batch Normalization
self.bn = nn.BatchNorm2d(16)
# Dropout
self.dropout = nn.Dropout(0.5)
self.fc = nn.Linear(
16 * 26 * 26,
10
)
def forward(self, x):
x = self.conv(x)
# 활성값 정규화
x = self.bn(x)
x = F.relu(x)
# 일부 뉴런 제거
x = self.dropout(x)
x = x.view(x.size(0), -1)
x = self.fc(x)
return x
model = CNN()
x = torch.randn(8, 1, 28, 28)
output = model(x)
print(output.shape)
| nn.BatchNorm1d | 벡터 데이터, 완전연결층(Linear), 시계열 |
| nn.BatchNorm2d | 이미지 데이터(CNN) |
| nn.BatchNorm3d | 3차원 데이터, 영상, 의료 이미지 |
일반적으로 파이토치로 매우 깊은 모델을 만드려면 conv2d, relu, conv2d skipconnection같은 빌딩 블럭을 정의해 for문으로 돌린다. 대표적인 예 ResNet(Residual Network) Skip Connection은 입력을 몇 개의 층을 건너뛰어 출력에 더해주는 구조. 층이 많아질수록 기울기 소실(Vanishing Gradient) 문제가 발생하니 입력을 직접 전달해 gradient가 쉽게 전달되도록 한다.
import torch
import torch.nn as nn
import torch.nn.functional as F
# 하나의 Building Block
class Block(nn.Module):
def __init__(self, channels):
super().__init__()
self.conv1 = nn.Conv2d(
channels,
channels,
kernel_size=3,
padding=1
)
self.conv2 = nn.Conv2d(
channels,
channels,
kernel_size=3,
padding=1
)
def forward(self, x):
# 원본 입력 저장 (Skip Connection)
shortcut = x
# 일반적인 CNN 흐름
x = self.conv1(x)
x = F.relu(x)
x = self.conv2(x)
# Skip Connection
x = x + shortcut
x = F.relu(x)
return x
# 여러 Block을 반복해서 쌓는 깊은 모델
class DeepCNN(nn.Module):
def __init__(self):
super().__init__()
self.blocks = nn.Sequential(
Block(16),
Block(16),
Block(16),
Block(16)
)
def forward(self, x):
x = self.blocks(x)
return x
model = DeepCNN()
input = torch.randn(1, 16, 32, 32)
output = model(input)
print(output.shape)
'Personal > Book' 카테고리의 다른 글
| 파이토치 딥러닝 마스터 - 1부 - 7장 새와 비행기 구별하기: 이미지 학습 (0) | 2026.07.14 |
|---|---|
| 파이썬 머신러닝 판다스 데이터 분석 - part1_판다스 입문 (0) | 2026.07.03 |
| 파이토치 딥러닝 마스터 - 1부 - 6장 신경망을 활용한 데이터 적합 (1) | 2026.06.28 |
| 파이토치 딥러닝 마스터 - 1부 - 5장 학습기법 (0) | 2026.06.28 |
| 파이토치 딥러닝 마스터 - 1부 - 4장 실제 데이터를 텐서로 표현해보기 (0) | 2026.06.28 |