콘텐츠로 이동

산술 연산

PyTorch는 Python의 연산자 오버로딩을 지원하므로 일반 수식처럼 텐서 연산을 작성할 수 있습니다. 모든 산술 연산은 원소별(element-wise) 로 동작합니다.

import torch
a = torch.tensor([1.0, 2.0, 3.0])
b = torch.tensor([4.0, 5.0, 6.0])
# 연산자 방식
print(a + b) # tensor([5., 7., 9.])
print(a - b) # tensor([-3., -3., -3.])
print(a * b) # tensor([ 4., 10., 18.])
print(a / b) # tensor([0.2500, 0.4000, 0.5000])

연산자 방식과 함수형 API는 동일한 결과를 만들어냅니다. 함수형 API는 추가 옵션( out, alpha 등)을 지원합니다.

연산자함수형 API설명
a + btorch.add(a, b)덧셈
a - btorch.sub(a, b)뺄셈
a * btorch.mul(a, b)곱셈
a / btorch.div(a, b)나눗셈
a // btorch.div(a, b, rounding_mode='floor')정수 나눗셈
a % btorch.remainder(a, b)나머지
a ** btorch.pow(a, b)거듭제곱
x = torch.tensor([10.0, 20.0, 30.0])
y = torch.tensor([3.0, 4.0, 5.0])
# alpha 파라미터: torch.add(a, b, alpha=k) → a + k*b
result = torch.add(x, y, alpha=2)
print(result) # tensor([16., 28., 40.])
# out 파라미터: 결과를 기존 텐서에 저장
out = torch.empty(3)
torch.add(x, y, out=out)
print(out) # tensor([13., 24., 35.])

텐서와 스칼라(단일 숫자) 간의 연산은 자동으로 브로드캐스팅됩니다. 스칼라가 모든 원소에 적용됩니다.

t = torch.tensor([1.0, 2.0, 3.0, 4.0])
print(t + 10) # tensor([11., 12., 13., 14.])
print(t * 2) # tensor([2., 4., 6., 8.])
print(t / 2) # tensor([0.5000, 1.0000, 1.5000, 2.0000])
print(t ** 2) # tensor([ 1., 4., 9., 16.])
print(10 - t) # tensor([9., 8., 7., 6.]) — 순서도 유효
a = torch.tensor([1.0, 2.0, 3.0])
# out-of-place: 새 텐서 반환, 원본 유지
b = a.add(10)
print(a) # tensor([1., 2., 3.]) — 변화 없음
print(b) # tensor([11., 12., 13.])
# in-place: 원본을 직접 수정
a.add_(10)
print(a) # tensor([11., 12., 13.]) — 변경됨

주요 in-place 연산 목록:

in-placeout-of-place설명
a.add_(b)a.add(b)덧셈
a.sub_(b)a.sub(b)뺄셈
a.mul_(b)a.mul(b)곱셈
a.div_(b)a.div(b)나눗셈
a.fill_(v)값 채우기
a.zero_()0으로 초기화

PyTorch의 모든 산술 연산은 기본적으로 원소별 로 수행됩니다. 같은 위치의 원소끼리 연산이 이루어집니다.

a = torch.tensor([[1, 2],
[3, 4]])
b = torch.tensor([[10, 20],
[30, 40]])
# 원소별 곱셈 — 행렬 곱이 아님!
print(a * b)
# tensor([[ 10, 40],
# [ 90, 160]])
# 행렬 곱은 @ 또는 torch.matmul()
print(a @ b)
# tensor([[ 70, 100],
# [150, 220]])
원소별 곱셈 (a * b) — 결과 셀에 마우스를 올려보세요
A
1
2
3
4
 
*
B
10
20
30
40
 
=
결과
10
40
90
160

원소별 연산이 유용한 이유는 벡터화(vectorization) 때문입니다. Python for 루프보다 수십~수백 배 빠르게 동작합니다.

import time
n = 1_000_000
a = torch.randn(n)
b = torch.randn(n)
# for 루프 방식 (느림)
start = time.time()
result = torch.zeros(n)
for i in range(n):
result[i] = a[i] + b[i]
print(f"for 루프: {time.time() - start:.3f}초")
# 텐서 연산 방식 (빠름)
start = time.time()
result = a + b
print(f"텐서 연산: {time.time() - start:.4f}초")