리서치

TOOLS / 중급

PyTorch 기초: 텐서와 자동미분

PyTorch의 핵심 개념인 텐서 연산, requires_grad와 자동미분(autograd), nn.Module 구조를 실제 코드로 설명합니다. 딥러닝 모델 구현의 출발점을 단단히 다집니다.

PALDYN Team5 MIN READ

지난 글에서 AI 개발에 필요한 Python 라이브러리 생태계를 살펴봤다. 이번에는 딥러닝 연구와 실전 개발의 표준이 된 PyTorch의 핵심 개념을 다룬다. 텐서 생성과 조작, 자동미분, 그리고 nn.Module로 모델을 정의하는 방식까지 코드 중심으로 이해한다.

왜 PyTorch인가

PyTorch는 2017년 Facebook AI Research(FAIR)에서 공개됐다. TensorFlow의 정적 계산 그래프(define-and-run) 방식과 달리 동적 계산 그래프(define-by-run)를 채택해 파이썬 제어 흐름(if, for)을 그대로 쓸 수 있다. 이 덕분에 디버깅이 쉽고, 가변 길이 시퀀스 처리가 자연스럽다. 현재 머신러닝 논문의 70% 이상이 PyTorch를 사용한다.

텐서: 모든 것의 기본 단위

PyTorch 텐서 — 구조와 자동미분

PyTorch의 기본 데이터 타입은 torch.Tensor다. NumPy ndarray와 유사하지만 GPU 연산과 자동미분을 지원한다.

import torch

# 생성
x = torch.tensor([[1.0, 2.0], [3.0, 4.0]])   # 직접 지정
z = torch.zeros(3, 4)                          # 영행렬
r = torch.randn(2, 3)                          # 표준정규분포
e = torch.ones_like(x)                         # x와 같은 shape, 전부 1

# 속성
print(x.shape)   # torch.Size([2, 2])
print(x.dtype)   # torch.float32
print(x.device)  # cpu

# GPU로 이동
if torch.cuda.is_available():
    x = x.to("cuda")   # 또는 x.cuda()

텐서 연산은 대부분 NumPy와 유사하다. 차이는 @(행렬 곱), .T(전치), unsqueeze/squeeze(차원 추가/제거) 등이다.

a = torch.randn(3, 4)
b = torch.randn(4, 5)

c = a @ b             # 행렬 곱 (3, 5)
d = a.T               # 전치 (4, 3)
e = a.unsqueeze(0)    # (1, 3, 4) — 배치 차원 추가
f = e.squeeze(0)      # (3, 4) — 차원 제거

# reshape vs view
g = a.reshape(2, 6)   # 비연속 텐서 OK
h = a.view(2, 6)      # 연속 메모리만 OK (빠름)

autograd: 자동미분의 원리

신경망 학습의 핵심은 역전파다. PyTorch는 계산 그래프를 동적으로 구성하고, backward()를 호출하면 체인 룰로 모든 파라미터의 그래디언트를 자동으로 계산한다.

import torch

x = torch.tensor([2.0], requires_grad=True)
y = x ** 2 + 3 * x   # y = x² + 3x

y.backward()          # dy/dx = 2x + 3 = 7
print(x.grad)         # tensor([7.])

# 그래디언트 초기화 (루프마다 필수!)
x.grad.zero_()

# 그래디언트 계산 비활성화 (추론 시 메모리 절약)
with torch.no_grad():
    pred = model(inputs)

requires_grad=True로 설정된 텐서는 이후 모든 연산이 계산 그래프에 기록된다. 학습 루프에서 optimizer.zero_grad()를 매번 호출하는 것이 이 때문이다 — 누적된 그래디언트를 초기화하지 않으면 이전 배치의 그래디언트가 더해진다.

nn.Module: 모델 정의의 표준

torch.nn.Module은 모든 PyTorch 모델의 기본 클래스다. __init__에서 레이어를 정의하고, forward에서 데이터 흐름을 작성한다.

nn.Module — PyTorch 모델 기본 구조

import torch
import torch.nn as nn

class MLP(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super().__init__()
        self.layers = nn.Sequential(
            nn.Linear(input_dim, hidden_dim),
            nn.ReLU(),
            nn.Dropout(0.3),
            nn.Linear(hidden_dim, output_dim),
        )

    def forward(self, x):
        return self.layers(x)

model = MLP(784, 256, 10)

# 파라미터 수 확인
total = sum(p.numel() for p in model.parameters())
print(f"파라미터 수: {total:,}")  # 204,810

# 저장 / 로드
torch.save(model.state_dict(), "model.pt")
model.load_state_dict(torch.load("model.pt"))

nn.Sequential은 레이어를 순서대로 연결해 forward를 자동으로 구성해준다. 커스텀 스킵 커넥션이나 분기가 필요한 경우에만 forward를 직접 작성한다.

주요 내장 레이어

레이어 용도
nn.Linear(in, out) 완전 연결층 (Wx + b)
nn.Conv2d(in, out, k) 2D 합성곱
nn.BatchNorm1d/2d 배치 정규화
nn.Dropout(p) 드롭아웃
nn.Embedding(V, d) 정수 → 벡터 변환
nn.LSTM(in, h) LSTM 셀
nn.MultiheadAttention 멀티헤드 어텐션

손실 함수와 옵티마이저는 별도 모듈이다.

criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)

다음 포스트에서는 이 요소들을 조합한 전체 학습 루프를 다룬다. DataLoader 구성, 에폭 반복, 검증 단계, 체크포인트 저장까지 실전 패턴을 모두 다룰 예정이다.


지난 글: AI 개발을 위한 Python 핵심 라이브러리

다음 글: PyTorch 학습 루프 완전 정복


읽어주셔서 감사합니다. 😊

KEEP READING

이어 읽기

모델 운영2026.05.29

GPU와 CUDA: 딥러닝 연산의 심장을 이해하다

CPU와 GPU의 구조적 차이, CUDA 프로그래밍 모델, PyTorch에서의 GPU 활용, 메모리 계층 구조를 딥러닝 관점에서 완전 정복한다.

중급12 MIN