텐서 (Tensor)
텐서(Tensor)는 PyTorch의 기본 데이터 구조입니다. NumPy의 ndarray와 유사하지만, GPU 연산과 자동 미분(Autograd)을 지원합니다.텐서 생성
Copy
import torch
# 직접 생성
x = torch.tensor([1, 2, 3]) # 1차원 텐서
matrix = torch.tensor([[1, 2], [3, 4]]) # 2차원 텐서 (행렬)
tensor_3d = torch.tensor([[[1, 2], [3, 4]]]) # 3차원 텐서
# 특수 텐서 생성
zeros = torch.zeros(3, 4) # 0으로 채운 3×4 행렬
ones = torch.ones(2, 3) # 1로 채운 2×3 행렬
rand = torch.rand(3, 3) # [0, 1) 균일 분포
randn = torch.randn(3, 3) # 표준 정규 분포 N(0, 1)
arange = torch.arange(0, 10, 2) # [0, 2, 4, 6, 8]
linspace = torch.linspace(0, 1, 5) # [0.0, 0.25, 0.5, 0.75, 1.0]
eye = torch.eye(3) # 3×3 단위 행렬
# 기존 텐서와 같은 형태
x_like = torch.zeros_like(matrix) # matrix와 같은 shape, 0으로 채움
x_rand = torch.rand_like(matrix, dtype=torch.float32)
print(f"shape: {matrix.shape}, dtype: {matrix.dtype}, device: {matrix.device}")
데이터 타입 (dtype)
| dtype | 설명 | 크기 | 주 사용처 |
|---|---|---|---|
torch.float32 | 32비트 부동소수 | 4B | 기본 학습 |
torch.float16 | 16비트 부동소수 | 2B | Mixed Precision |
torch.bfloat16 | Brain Float 16비트 | 2B | 최신 GPU 학습 |
torch.int64 | 64비트 정수 | 8B | 레이블, 인덱스 |
torch.bool | 불리언 | 1B | 마스크 |
Copy
# dtype 변환
x = torch.tensor([1.5, 2.7, 3.2])
x_int = x.to(torch.int64) # float → int
x_half = x.to(torch.float16) # float32 → float16
x_bool = x > 2.0 # 불리언 마스크
텐서 연산
Copy
a = torch.tensor([[1, 2], [3, 4]], dtype=torch.float32)
b = torch.tensor([[5, 6], [7, 8]], dtype=torch.float32)
# 요소별 연산
print(a + b) # 덧셈
print(a * b) # 요소별 곱셈 (Hadamard product)
print(a ** 2) # 제곱
# 행렬 연산
print(a @ b) # 행렬 곱 (matmul)
print(torch.matmul(a, b)) # 동일
print(torch.mm(a, b)) # 2D 전용
# 집계 연산
print(a.sum()) # 전체 합
print(a.mean(dim=0)) # 열 방향 평균
print(a.max(dim=1)) # 행 방향 최대값 (값 + 인덱스)
print(a.argmax(dim=1)) # 행 방향 최대값 인덱스
형태 변환 (Shape Manipulation)
Copy
x = torch.arange(12)
# reshape: 형태 변환
y = x.reshape(3, 4) # 3×4로 변환
z = x.reshape(2, -1) # 자동 계산: 2×6
# view: reshape과 유사하지만 메모리 연속성 필요
v = x.view(3, 4)
# squeeze / unsqueeze: 차원 추가/제거
a = torch.randn(1, 3, 1, 4)
print(a.squeeze().shape) # (3, 4) — 크기 1인 차원 제거
print(a.squeeze(0).shape) # (3, 1, 4) — 지정 차원만 제거
b = torch.randn(3, 4)
print(b.unsqueeze(0).shape) # (1, 3, 4) — 0번째에 차원 추가
print(b.unsqueeze(-1).shape) # (3, 4, 1) — 마지막에 차원 추가
# permute: 차원 순서 변경
img = torch.randn(3, 224, 224) # CHW 형식
img_hwc = img.permute(1, 2, 0) # HWC 형식으로 변환
print(f"CHW: {img.shape} → HWC: {img_hwc.shape}")
# flatten: 다차원을 1차원으로
flat = img.flatten() # (3*224*224,)
flat_partial = img.flatten(1) # (3, 224*224) — 1번 차원부터 평탄화
# cat / stack: 텐서 결합
t1 = torch.randn(2, 3)
t2 = torch.randn(2, 3)
cat = torch.cat([t1, t2], dim=0) # (4, 3) — 기존 차원에 이어 붙이기
stack = torch.stack([t1, t2], dim=0) # (2, 2, 3) — 새 차원 추가
인덱싱과 슬라이싱
Copy
x = torch.arange(20).reshape(4, 5)
# tensor([[ 0, 1, 2, 3, 4],
# [ 5, 6, 7, 8, 9],
# [10, 11, 12, 13, 14],
# [15, 16, 17, 18, 19]])
print(x[0]) # 첫 번째 행: [0, 1, 2, 3, 4]
print(x[:, 1]) # 두 번째 열: [1, 6, 11, 16]
print(x[1:3, 2:4]) # 부분 행렬: [[7, 8], [12, 13]]
# 불리언 인덱싱
mask = x > 10
print(x[mask]) # [11, 12, 13, 14, 15, 16, 17, 18, 19]
# 팬시 인덱싱
indices = torch.tensor([0, 2, 3])
print(x[indices]) # 0, 2, 3번째 행 선택
브로드캐스팅 (Broadcasting)
형태가 다른 텐서 간 연산 시 자동으로 차원을 맞춰줍니다. NumPy와 동일한 규칙을 따릅니다.Copy
# (3, 4) + (4,) → (3, 4) + (1, 4) → (3, 4)
a = torch.randn(3, 4)
b = torch.tensor([1.0, 2.0, 3.0, 4.0])
result = a + b # b가 (1, 4)로 확장 후 각 행에 더해짐
# (3, 1) + (1, 4) → (3, 4)
col = torch.tensor([[1], [2], [3]]) # (3, 1)
row = torch.tensor([10, 20, 30, 40]) # (4,)
result = col + row # (3, 4) 결과
GPU 연산
Copy
# 디바이스 확인
if torch.cuda.is_available():
device = torch.device('cuda')
elif torch.backends.mps.is_available():
device = torch.device('mps') # Apple Silicon
else:
device = torch.device('cpu')
print(f"사용 디바이스: {device}")
# 텐서를 GPU로 이동
x = torch.randn(1000, 1000)
x_gpu = x.to(device)
# GPU에서 직접 생성
y_gpu = torch.randn(1000, 1000, device=device)
# GPU 연산 (CPU보다 대규모 행렬 연산에서 훨씬 빠름)
result = x_gpu @ y_gpu
# 결과를 CPU로 가져오기 (NumPy 변환 등에 필요)
result_cpu = result.cpu()
result_numpy = result_cpu.numpy()
CPU와 GPU 텐서 간 연산은 불가능합니다. 반드시 같은 디바이스에서 연산해야 합니다.
RuntimeError: Expected all tensors to be on the same device 오류가 발생하면 디바이스를 통일하세요.NumPy 변환
Copy
import numpy as np
# NumPy → PyTorch (메모리 공유)
np_array = np.array([1, 2, 3])
tensor = torch.from_numpy(np_array) # 메모리 공유!
np_array[0] = 100
print(tensor) # tensor([100, 2, 3]) — 원본 변경이 반영됨
# PyTorch → NumPy (CPU 텐서만 가능)
tensor = torch.tensor([4, 5, 6])
np_result = tensor.numpy()
# 메모리 복사 (독립적)
np_copy = tensor.detach().clone().numpy()
체크리스트
- 다양한 방법으로 텐서를 생성할 수 있다
- reshape, permute, squeeze 등 형태 변환을 활용할 수 있다
- 텐서를 GPU로 이동하고 연산할 수 있다
- NumPy와 PyTorch 텐서 간 변환 시 메모리 공유 여부를 이해한다

