콘텐츠로 이동

리덕션 연산

리덕션(reduction) 연산은 텐서의 여러 원소를 하나 또는 더 적은 수의 값으로 줄이는 연산입니다.

import torch
t = torch.tensor([1.0, 2.0, 3.0, 4.0, 5.0])
print(torch.sum(t)) # tensor(15.)
print(t.sum()) # tensor(15.) — 메서드 방식도 동일
print(torch.mean(t)) # tensor(3.)
print(torch.std(t)) # tensor(1.5811) — 표본 표준편차 (Bessel's correction)
print(torch.var(t)) # tensor(2.5000) — 표본 분산
print(torch.prod(t)) # tensor(120.) — 전체 곱
t = torch.tensor([3.0, 1.0, 4.0, 1.0, 5.0, 9.0, 2.0])
# 값 반환
print(torch.max(t)) # tensor(9.)
print(torch.min(t)) # tensor(1.)
# 인덱스 반환
print(torch.argmax(t)) # tensor(5) — 9.0의 위치
print(torch.argmin(t)) # tensor(1) — 첫 번째 1.0의 위치
# max/min은 dim 지정 시 (값, 인덱스) 쌍을 반환
values, indices = torch.max(t, dim=0)
print(values) # tensor(9.)
print(indices) # tensor(5)

2D 이상의 텐서에서 dim 파라미터로 어느 축을 따라 줄일지 지정합니다.

텐서 shape: (3, 4)
dim=0 → 행 방향으로 줄임 → 결과 shape: (4,) [각 열의 집계]
dim=1 → 열 방향으로 줄임 → 결과 shape: (3,) [각 행의 집계]
m = torch.tensor([[1.0, 2.0, 3.0, 4.0],
[5.0, 6.0, 7.0, 8.0],
[9.0, 10., 11., 12.]])
# shape: (3, 4)
# dim=0: 각 열의 합 (3개 행이 1개로 줄어듦)
print(m.sum(dim=0)) # tensor([15., 18., 21., 24.]) shape: (4,)
# dim=1: 각 행의 합 (4개 열이 1개로 줄어듦)
print(m.sum(dim=1)) # tensor([10., 26., 42.]) shape: (3,)
# 평균도 동일하게 dim 지정 가능
print(m.mean(dim=0)) # tensor([5., 6., 7., 8.])
print(m.mean(dim=1)) # tensor([ 2.5, 6.5, 10.5])
# argmax: 각 행에서 최댓값의 위치
print(m.argmax(dim=1)) # tensor([3, 3, 3]) — 각 행의 마지막 열이 최대

keepdim=True 를 지정하면 줄어든 차원을 제거하지 않고 크기 1로 유지합니다. 이 옵션은 브로드캐스팅 과 함께 사용할 때 특히 유용합니다.

keepdim=False (기본값):
(3, 4) → sum(dim=1) → (3,)
keepdim=True:
(3, 4) → sum(dim=1, keepdim=True) → (3, 1)
m = torch.tensor([[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0]])
# shape: (2, 3)
# keepdim=False (기본값)
s_no_keepdim = m.sum(dim=1)
print(s_no_keepdim.shape) # torch.Size([2])
# keepdim=True
s_keepdim = m.sum(dim=1, keepdim=True)
print(s_keepdim.shape) # torch.Size([2, 1])
print(s_keepdim)
# tensor([[ 6.],
# [15.]])

keepdim 없이 정규화할 때 발생하는 문제

섹션 제목: “keepdim 없이 정규화할 때 발생하는 문제”
m = torch.tensor([[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0]])
row_sum = m.sum(dim=1) # shape: (2,)
# m / row_sum 은 shape 불일치로 브로드캐스팅이 잘못됨
# → (2, 3) / (2,) 는 열 방향 브로드캐스팅 시도 → 오류 또는 잘못된 결과
row_sum_kd = m.sum(dim=1, keepdim=True) # shape: (2, 1)
normalized = m / row_sum_kd # (2, 3) / (2, 1) → 올바르게 브로드캐스팅
print(normalized)
# tensor([[0.1667, 0.3333, 0.5000],
# [0.2667, 0.3333, 0.4000]])

PyTorch는 dim 에 튜플을 전달해 여러 축을 동시에 집계할 수 있습니다.

t = torch.randn(2, 3, 4) # shape: (2, 3, 4)
# dim 0과 2를 동시에 줄임
result = t.sum(dim=(0, 2))
print(result.shape) # torch.Size([3])
# 전체 합
print(t.sum()) # 단일 스칼라 텐서
함수설명반환값
sum(dim)합계텐서
mean(dim)평균텐서
std(dim)표준편차텐서
var(dim)분산텐서
prod(dim)전체 곱텐서
max(dim)최댓값값 또는 (값, 인덱스)
min(dim)최솟값값 또는 (값, 인덱스)
argmax(dim)최댓값 인덱스텐서
argmin(dim)최솟값 인덱스텐서
any(dim)하나라도 Truebool 텐서
all(dim)모두 Truebool 텐서