티스토리 뷰
PyTorch와 같은 딥러닝 프레임워크를 공부하다 보면, 자주 등장하지만 처음에는 헷갈릴 수 있는 개념 중 하나가 바로 "In-place 연산"입니다. 이는 새로운 값을 담을 공간을 만들지 않고, 기존 메모리 공간에서 직접 값을 수정하는 연산을 뜻합니다. 개념을 이해하고 나면 optimizer.zero_grad()나 optimizer.step()과 같은 연산에서 왜 = 할당 없이도 값이 바뀌는지 자연스럽게 이해할 수 있습니다.
예제로 보는 In-place 연산
import torch
# 일반 연산
x = torch.tensor([1.0, 2.0, 3.0])
y = x + 1
print(x) # tensor([1., 2., 3.])
print(y) # tensor([2., 3., 4.])
# In-place 연산
x.add_(1)
print(x) # tensor([2., 3., 4.])
add_()처럼 언더스코어(_)가 붙은 PyTorch의 연산 함수들은 In-place 연산을 수행합니다. 이 연산은 기존 텐서 x의 값을 직접 바꾸며, 새로운 텐서를 생성하지 않습니다.
Python의 객체, 참조, 그리고 변경 가능성
- Python에서는 모든 데이터가 '객체'입니다.
- 변수는 객체를 가리키는 '참조(reference)'에 불과합니다.
- 객체는 두 가지로 나뉩니다:
- 변경 불가능 (Immutable): int, float, str, tuple
- 변경 가능 (Mutable): list, dict, torch.Tensor
예제 1: 변경 불가능한 객체
x = 10
y = x
x = x + 1
print(x, y) # 11 10
x = x + 1은 새로운 객체 11을 만들고 x가 그것을 가리키게 됩니다.
예제 2: 변경 가능한 객체
x = [1, 2, 3]
x.append(4)
print(x) # [1, 2, 3, 4]
append()는 기존 객체 x를 그대로 수정합니다. 이게 바로 In-place 연산입니다.
PyTorch Tensor와 In-place 연산
PyTorch의 Tensor는 변경 가능한 객체입니다. 텐서는 실제 데이터를 메모리에 연속적으로 저장하고 있으며, 다음과 같은 속성을 함께 가지고 있습니다:
- 데이터 값 (data)
- 모양 (shape)
- 자료형 (dtype)
- 장치 정보 (device)
- 기울기 저장 공간 (.grad)
x = torch.tensor([1., 2., 3.], requires_grad=True)
print(x.grad) # None (backward 전)
- .grad는 backward가 수행된 이후에 gradient 값이 저장되는 텐서입니다.
- 이 .grad 역시 Tensor이기 때문에 In-place 연산이 가능합니다.
Optimizer가 In-place 연산을 사용하는 방식
optimizer.zero_grad()의 역할
for p in model.parameters():
if p.grad is not None:
p.grad.zero_()
모델의 모든 파라미터에 대해 .grad가 존재한다면, 해당 gradient를 In-place 연산으로 0으로 초기화합니다.
optimizer.step()의 역할
for p in model.parameters():
p.data.add_(-lr * p.grad)
학습률(lr)과 gradient를 곱한 값을 현재 파라미터에 In-place로 더해줍니다. 즉, 새로운 파라미터 객체를 만들지 않고 기존 값을 직접 수정합니다.
이러한 방식이 가능한 이유는 optimizer가 모델 파라미터 객체의 '참조'를 가지고 있기 때문입니다.
In-place 연산의 장점
이유 설명
메모리 효율 | 새 텐서를 생성하지 않기 때문에 메모리 사용량을 줄일 수 있습니다. |
속도 | 메모리 재할당이 없으므로 연산 속도가 더 빠릅니다. |
간결한 코드 | 값의 복사 없이 모델 파라미터를 바로 수정할 수 있습니다. |
주의할 점: Autograd와의 충돌
In-place 연산은 편리하지만, 자동 미분(autograd)과 함께 사용할 때는 주의해야 합니다. 이미 autograd 연산 그래프에 연결된 텐서에 대해 In-place 연산을 수행하면 오류가 발생할 수 있습니다.
a = torch.tensor([2.], requires_grad=True)
b = a * 3
b.backward()
a.add_(1) # RuntimeError 발생
이 경우, a.clone()이나 a.detach()로 복사본을 만든 후 연산을 수행하는 것이 안전합니다.
마무리 정리
In-place 연산은 PyTorch 텐서가 갖는 변경 가능성(Mutability)을 적극 활용하는 중요한 기술입니다. 새로운 객체를 만들지 않고 기존 객체를 직접 수정함으로써 메모리 효율성과 속도를 높이며, 학습 과정에서 필요한 파라미터 업데이트 등을 더 간단하게 처리할 수 있습니다.
특히 optimizer의 zero_grad()와 step() 내부에서 어떻게 In-place 연산이 사용되는지를 이해하면, PyTorch의 작동 방식과 연산 흐름을 훨씬 깊이 있게 파악할 수 있습니다.
'머신러닝&딥러닝' 카테고리의 다른 글
PyTorch 데이터셋 분할 및 DataLoader (2) | 2025.05.01 |
---|---|
PyTorch 이미지 데이터셋: torchvision.datasets + 현실 데이터 사용법 (0) | 2025.05.01 |
PyTorch Compose를 통한 데이터 전처리: 심층 분석 (0) | 2025.05.01 |
torchvision 완전 정복: PyTorch 비전 프로젝트의 핵심 라이브러리 (0) | 2025.05.01 |
모델 저장 및 재사용 (0) | 2025.02.28 |
- Total
- Today
- Yesterday
- 케라스
- 텍스트 마이닝
- 토치비전
- chat gpt 모델별 예산
- 장고 orm sql문 비교
- chat gpt 가격 예상
- python 문자열 슬라이싱
- 로또 ai
- 클래스형 뷰
- 1164회 로또
- 로또 1164회 당첨
- Numpy
- f-string
- 티스토리챌린지
- TorchVision
- python import
- 1165회 로또
- Python
- chat gpt 4o 예산
- GitHub
- 텍스트 전처리
- pytorch
- github action
- chat gpt 한국어 가격
- chat gpt 모델 별 가격
- 오블완
- chat gpt 모델 api 가격 예측
- 인공지능 로또 예측
- chat gpt api 비용 계산
- postgre
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |