안녕하세요, MoonLight입니다.
이번 Post에서는 Deep Learning에서 Data를 표현하기 위한 자료구조인 Tensor에 대해서 알아보도록 하겠습니다.

1. Tensor
1.1 Tensor의 개념
Tensor는 겉으로 보기에 숫자로 이루어진 다차원 배열(Multi-dimensional Array)입니다.
PyTorch를 비롯한 대부분의 딥러닝 프레임워크는 Tensor를 기본 데이터 구조로 사용합니다.
Tensor는 스칼라(Scalar), 벡터(Vector), 행렬(Matrix) 및 고차원 배열을 일반화한 개념으로 볼 수 있습니다.
딥러닝 모델에서 Tensor는 학습을 위한 데이터를 표현하는 필수적인 자료구조입니다.
모델이 데이터를 처리하고 가중치를 업데이트하기 위해 연속적인 수치 연산을 수행하는데, 이를 위해 Tensor가 사용됩니다.
딥러닝 모델에는 다양한 형태의 Data가 입력됩니다.
이미지, 텍스트, 소리와 같은 형태의 Data가 신경망에 입력으로 들어가야 하는데, 어떤 형태의 입력이든지 간에 부동소수점(Floating Point) Tensor로 변환이 되어야 합니다. 다양한 입력 데이터 형태를 부동소수점(Floating Point) Tensor로 변환하는 방법론은 매우 다양하기 때문에 여기서 다루기에는 어려울 것 같습니다.
딥러닝 모델의 입력으로 부동소수점(Floating Point) 형태로 표현이 되어야 할 이유는 몇 가지 있습니다.
1) 연속적인 값 표현이 가능
딥러닝 모델의 입력은 이미지, 센서 데이터, 소리 등과 같이 연속적인 값의 속성을 가진 것들이 대부분이며, 이를 표현하는 것에는 값 사이의 간격이 일정한 정수형(Integer) 값보다는 정밀한 값을 표현할 수 있는 부동소수점이 훨씬 더 적절합니다.
2) 신경망 학습 알고리즘에 적합
딥러닝 모델은 경사하강법(Gradient Descent)과 같은 최적화 기법을 사용하여 학습을 진행하며, 이떄 편미분이 필수적입니다.
경사하강법은 손실 함수의 미분이 필요하며, 미분 계산은 연속적인 값을 기반으로 이루어지므로 반드시 부동소수점이 필요합니다.
3) 부드러운 변화(Continuous Change) 표현
신경망을 이루는 가중치(weight)와 편향(bias)은 모델이 학습을 통해 점진적으로 조정하는 값들입니다.
만약 이 값들이 정수로 이루어졌다면 변화 단위가 너무 크기 때문에 미세한 조정이 불가능한 반면에 부동소수점은 이러한 문제가 없습니다.
1.2 Tensor vs Numpy
숫자를 다차원 배열의 형태로 표현한다는 점에서 Numpy의 ndarray와 동일해 보입니다.
실제로 PyTorch는 이 둘을 서로 간단하게 변환할 수 있는 기능을 제공합니다.
하지만, 이 둘의 가장 큰 차이점은 Tensor는 딥러닝과 고속 연산에 관련된 다양한 기능을 제공한다는 점이며, 아래와 같이 몇 가지 중요한 차이점을 가집니다.
※ Tensor와 NumPy 배열의 차이점
비교 항목
|
NumPy 배열 (`numpy.ndarray`)
|
PyTorch Tensor (`torch.Tensor`)
|
연산 장치
|
CPU 연산 전용
|
CPU & GPU 연산 지원
|
GPU 가속
|
지원하지 않음
|
`.to('cuda')`를 사용하여 GPU에서 연산 가능
|
자동 미분
|
지원하지 않음
|
`requires_grad=True`를 설정하면 자동 미분 지원
|
딥러닝 지원
|
직접적인 지원 없음
|
신경망 모델의 입력, 가중치 표현 가능
|
메모리 공유
|
NumPy 배열 간 독립적인 메모리 사용
|
Tensor는 `detach()`를 사용해 NumPy와 메모리 공유 가능
|
한마디로 정리하면, Tensor는 NumPy 배열을 기반으로 하지만, 딥러닝 학습을 위한 GPU 가속, 자동 미분, 딥러닝 모델과의 호환성을 갖춘 고급 자료구조라고 할 수 있습니다.
2. Tensor 생성
Tensor에 대해서 알아보았으니, 생성하는 방법에 대해서 알아보도록 하겠습니다.
PyTorch는 Tensor를 생성하는 매우 다양한 방법이 있습니다. 많이 사용되는 방법들 위주로 알아보도록 하겠습니다.
2.1. torch.tensor()
`torch.tensor()`를 사용하면 Python의 리스트 또는 NumPy 배열을 기반으로 Tensor를 생성할 수 있습니다.
import torch
# 스칼라 (0D Tensor)
scalar = torch.tensor(5)
# 벡터 (1D Tensor)
vector = torch.tensor([1, 2, 3])
# 행렬 (2D Tensor)
matrix = torch.tensor([[1, 2], [3, 4]])
# 3차원 Tensor
tensor_3d = torch.tensor([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
print(f"Scalar: {scalar}")
print(f"Vector: {vector}")
print(f"Matrix: {matrix}")
print(f"3D Tensor: {tensor_3d}")
Scalar: 5
Vector: tensor([1, 2, 3])
Matrix: tensor([[1, 2],
[3, 4]])
3D Tensor: tensor([[[1, 2],
[3, 4]],
[[5, 6],
[7, 8]]])
2.2. torch.zeros()
모든 원소가 0인 Tensor를 생성하려면 `torch.zeros()`를 사용합니다.
# 크기가 (3, 3)인 0으로 초기화된 Tensor 생성
zero_tensor = torch.zeros(3, 3)
print(zero_tensor)
tensor([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
2.3. torch.ones()
모든 원소가 1인 Tensor를 생성하려면 `torch.ones()`를 사용합니다.
# 크기가 (2, 4)인 1로 초기화된 Tensor 생성
ones_tensor = torch.ones(2, 4)
print(ones_tensor)
tensor([[1., 1., 1., 1.],
[1., 1., 1., 1.]])
2.4. torch.rand()
모든 원소가 0과 1 사이의 랜덤 값으로 초기화된 Tensor를 생성하려면 `torch.rand()`를 사용합니다.
#크기가 (3, 3)인 랜덤 Tensor 생성
rand_tensor = torch.rand(3, 3)
print(rand_tensor)
tensor([[0.5713, 0.1586, 0.7974],
[0.6063, 0.7429, 0.6758],
[0.4319, 0.5568, 0.3172]])
2.5. torch.randint()
정수 범위를 지정하여 랜덤한 정수를 갖는 Tensor를 생성할 수 있습니다.
# 0부터 10 사이의 정수값을 갖는 (2, 3) 크기의 Tensor 생성
rand_int_tensor = torch.randint(low=0, high=10, size=(2, 3))
print(rand_int_tensor)
tensor([[6, 7, 6],
[7, 6, 7]])
2.6. torch.full()
모든 원소가 동일한 값으로 초기화된 Tensor를 만들려면 `torch.full()`을 사용합니다.
# 크기가 (3, 3)이고, 모든 값이 7인 Tensor 생성
full_tensor = torch.full((3, 3), 7)
print(full_tensor)
tensor([[7, 7, 7],
[7, 7, 7],
[7, 7, 7]])
2.7. torch.arange()
NumPy의 `np.arange()`와 유사하게, 특정 범위 내에서 일정한 간격의 값을 갖는 Tensor를 생성합니다.
# 0부터 9까지 1씩 증가하는 Tensor 생성
arange_tensor = torch.arange(0, 10, step=1)
print(arange_tensor)
tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2.8. torch.linspace()
`torch.linspace(start, end, steps)`를 사용하면, 주어진 구간에서 균등한 간격으로 값을 배치한 Tensor를 생성할 수 있습니다.
# 0과 1 사이를 5등분한 값으로 구성된 Tensor 생성
linspace_tensor = torch.linspace(0, 1, steps=5)
print(linspace_tensor)
tensor([0.0000, 0.2500, 0.5000, 0.7500, 1.0000])
2.9. torch.eye()
`torch.eye()`는 단위 행렬(Identity Matrix)을 생성합니다.
# 3x3 단위 행렬 생성
identity_matrix = torch.eye(3)
print(identity_matrix)
tensor([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
2.10. torch.empty()
`torch.empty()`는 초기화되지 않은 Tensor를 생성합니다. (메모리상의 기존 값이 그대로 들어갈 수 있음)
# 크기가 (2, 3)인 초기화되지 않은 Tensor 생성
empty_tensor = torch.empty(2, 3)
print(empty_tensor)
tensor([[-9.8824e+04, 1.9114e-42, 0.0000e+00],
[ 0.0000e+00, 0.0000e+00, 0.0000e+00]])
`torch.empty()`는 메모리를 초기화하지 않으므로, 무작위 값이 포함될 수 있습니다.
2.11. torch.from_numpy
`torch.from_numpy()`는 NumPy 배열을 직접 Tensor로 변환할 때 사용합니다.
이 방법을 사용하면 NumPy 배열과 Tensor가 메모리를 공유하기 때문에, 하나를 변경하면 다른 하나에도 영향을 미칠수 있습니다.
import numpy as np
import torch
# NumPy 배열 생성
np_array = np.array([[1, 2, 3], [4, 5, 6]])
# NumPy 배열을 PyTorch Tensor로 변환
tensor_from_numpy = torch.from_numpy(np_array)
print("NumPy Array:")
print(np_array)
print("\nTensor from NumPy:")
print(tensor_from_numpy)
NumPy Array:
[[1 2 3]
[4 5 6]]
Tensor from NumPy:
tensor([[1, 2, 3],
[4, 5, 6]], dtype=torch.int32)
반대로, Tensor를 Numpy 배열로 변환도 가능합니다.
#Tensor를 NumPy 배열로 변환
numpy_from_tensor = tensor_from_numpy.numpy()
print("Converted NumPy Array:")
print(numpy_from_tensor)
Converted NumPy Array:
[[1 2 3]
[4 5 6]]
2.12. Summary
다양한 Tensor 생성 함수에 대해서 간략히 정리한 내용입니다.
생성 함수
|
특징
|
용도
|
torch.tensor()
|
리스트로부터 직접 생성
|
데이터 변환
|
torch.zeros()
|
모든 값이 0
|
가중치 초기화
|
torch.ones()
|
모든 값이 1
|
특정 연산 테스트
|
torch.rand()
|
0~1 사이 난수
|
가중치 초기화
|
torch.randint()
|
지정된 범위의 정수값
|
범주형 데이터 생성
|
torch.full()
|
특정 값으로 채움
|
초기화
|
torch.arange()
|
연속된 정수값
|
반복적인 연산 필요 시
|
torch.linspace()
|
균등한 간격의 값
|
그래프 샘플링
|
torch.eye()
|
단위 행렬
|
선형대수 연산
|
torch.empty()
|
초기화되지 않은 Tensor
|
빠른 할당
|
torch.from_numpy()
|
Numpy 배열을 Tensor로 변환
|
변환
|
torch.numpy()
|
Tensor롤 Numpy로 변환
|
변환
|
3. Tensor 조작
PyTorch의 Tensor는 다양한 조작 방법을 통해 크기 변경, 변환, 연결 및 분할, 메모리 공유 등을 수행할 수 있습니다.
신경망의 입력 혹은 다른 상황에서 Tensor의 전체 모양을 변경해야 하는 경우는 매우 빈번하게 발생합니다.
이 절에서는 Tensor의 차원 및 크기 확인, 변환, 연결 및 분할, 차원 변경, 복사 및 메모리 공유에 대해 알아보겠습니다
3.1 Tensor의 차원 및 크기 확인
Tensor의 크기와 차원을 확인하는 방법은 다음과 같습니다.
함수
|
설명
|
tensor.shape
|
Tensor의 크기를 반환 (튜플 형태)
|
tensor.size()
|
Tensor의 크기를 반환 (튜플 형태)
|
tensor.dim()
|
Tensor의 차원 수를 반환
|
import torch
# 3차원 Tensor 생성 (Batch, Height, Width)
tensor = torch.rand(2, 3, 4)
print("Tensor:\n", tensor)
print("\nShape:", tensor.shape) # 크기 출력
print("Size:", tensor.size()) # 크기 출력
print("Dimensions:", tensor.dim()) # 차원 수 출력
Tensor:
tensor([[[0.9924, 0.2103, 0.3828, 0.9077],
[0.7350, 0.2868, 0.6011, 0.8886],
[0.0642, 0.2522, 0.6462, 0.3248]],
[[0.7136, 0.1212, 0.9811, 0.2830],
[0.8917, 0.3153, 0.7823, 0.0091],
[0.3998, 0.7973, 0.1496, 0.1551]]])
Shape: torch.Size([2, 3, 4])
Size: torch.Size([2, 3, 4])
Dimensions: 3
`shape`과 `size()`는 동일한 역할을 합니다.
3.2 Tensor 변환
Tensor의 차원을 변경하거나 새로운 형태로 변환할 때 사용됩니다.
함수
|
설명
|
reshape()
|
새로운 크기로 변환 (데이터 복사 가능)
|
view()
|
새로운 크기로 변환 (메모리 공유)
|
squeeze()
|
크기가 1인 차원을 제거
|
unsqueeze()
|
특정 위치에 차원 추가
|
Ex. 1. `reshape()`
#Tensor를 새로운 크기로 변환합니다.
tensor = torch.arange(8)
# (8,) -> (2, 4)로 변환
reshaped = tensor.reshape(2, 4)
print(reshaped)
tensor([[0, 1, 2, 3],
[4, 5, 6, 7]])
Ex. 2. `view()`
Tensor를 새로운 크기로 변환합니다. (메모리 공유됨)
tensor = torch.arange(8)
# (8,) -> (2, 4)로 변환 (메모리 공유)
viewed = tensor.view(2, 4)
print(viewed)
tensor([[0, 1, 2, 3],
[4, 5, 6, 7]])
`view()`는 원본 Tensor와 메모리를 공유하므로, 원본 Tensor가 변경되면 `view()`된 Tensor도 영향을 받습니다.
Ex. 3. `squeeze()`
Tensor Shape에서 크기가 1인 차원 제거합니다.
tensor = torch.rand(1, 3, 1, 4)
squeezed = tensor.squeeze()
print("Before Squeeze:", tensor.shape)
print("After Squeeze:", squeezed.shape)
Before Squeeze: torch.Size([1, 3, 1, 4])
After Squeeze: torch.Size([3, 4])
`squeeze()`는 크기가 1인 차원을 자동으로 제거합니다.
Ex. 4. `unsqueeze()`
Tensor 특정 위치에 차원을 추가하는 기능을 합니다.
tensor = torch.rand(3, 4)
# 첫 번째 차원(0)에 추가
unsqueezed = tensor.unsqueeze(0)
print("Before Unsqueeze:", tensor.shape)
print("After Unsqueeze:", unsqueezed.shape)
Before Unsqueeze: torch.Size([3, 4])
After Unsqueeze: torch.Size([1, 3, 4])
Ex. 5. `torch.flatten()`
Tensor를 1차원으로 평탄화합니다.
tensor = torch.tensor([[1, 2], [3, 4]])
flat_tensor = torch.flatten(tensor)
print(flat_tensor)
tensor([1, 2, 3, 4])
Ex. 6. `torch.unbind()`
특정 차원을 따라 Tensor를 분리합니다.
tensor = torch.tensor([[1, 2, 3], [4, 5, 6]])
unbind_tensors = torch.unbind(tensor, dim=0)
for t in unbind_tensors:
print(t)
tensor([1, 2, 3])
tensor([4, 5, 6])
3.3 Tensor 연결 및 분할
Tensor를 결합하거나 분할할 때 사용됩니다.
함수
|
설명
|
cat()
|
특정 차원을 기준으로 연결
|
stack()
|
새로운 차원을 추가하여 연결
|
split()
|
특정 크기로 나누어 리스트 반환
|
chunk()
|
균등한 개수로 나누어 리스트 반환
|
Ex. 1. `cat()`
Tensor의 차원을 유지한 채 서로 연결하여 붙입니다.
A = torch.rand(2, 3)
B = torch.rand(2, 3)
concatenated = torch.cat([A, B], dim=0)
print(concatenated.shape) # (4, 3)
print(concatenated)
torch.Size([4, 3])
tensor([[0.5043, 0.5224, 0.9575],
[0.7870, 0.9939, 0.2833],
[0.6619, 0.2978, 0.4978],
[0.5750, 0.8437, 0.8101]])
Ex. 2. `stack()`
`stack()`은 새로운 차원을 추가한 상태에서 연결합니다.
A = torch.rand(2, 3)
B = torch.rand(2, 3)
stacked = torch.stack([A, B], dim=0)
print(stacked.shape) # (2, 2, 3)
print(stacked)
torch.Size([2, 2, 3])
tensor([[[0.7922, 0.2840, 0.3070],
[0.0351, 0.6589, 0.3992]],
[[0.2528, 0.6137, 0.4277],
[0.1077, 0.8962, 0.2469]]])
Ex. 3. `split()`
Tensor를 특정 크기로 나누어줍니다. Tensor크기가 나누는 크기와 다른 경우에는 크기가 다른 Tensor가 생길 수 있습니다.
tensor = torch.arange(10)
split_tensors = torch.split(tensor, 3) # 크기 3으로 나누기
for t in split_tensors:
print(t)
tensor([0, 1, 2])
tensor([3, 4, 5])
tensor([6, 7, 8])
tensor([9])
Ex. 4. `chunk()`
Tensor를 균등한 개수로 나눕니다.
tensor = torch.arange(10)
chunk_tensors = torch.chunk(tensor, 3) # 3개로 균등하게 나누기
for t in chunk_tensors:
print(t)
tensor([0, 1, 2, 3])
tensor([4, 5, 6, 7])
tensor([8, 9])
torch.chunk() 함수는 Tensor를 균등한 크기에 가깝게 나누는 기능을 합니다.
하지만 개별 청크(조각)의 크기를 직접 지정할 수는 없고, PyTorch가 자동으로 크기를 결정합니다.
PyTorch는 앞쪽 청크부터 최대한 같은 크기로 맞추고, 마지막 청크에 남은 데이터를 배정하는 방식을 사용합니다.
즉, 각 청크의 크기는 가능한 한 균등하게 배분되되, 앞쪽이 더 크게 유지됩니다.
위 예제에서 다른 분할 방식(3,3,4)을 기대할 수도 있지만, torch.chunk()는 고정된 규칙을 따르기 때문에 원하는 방식으로 나눌 수 없습니다.
만약 torch.chunk() 대신 특정 크기로 나누고 싶다면 torch.split()을 사용하면 됩니다
3.4 차원 변경
함수
|
설명
|
permute()
|
특정 차원 순서로 재배열
|
transpose()
|
두 차원을 교환
|
Ex. 1. `permute()`
Tensor의 차원 순서를 입력한 순서대로 차원을 재배치합니다.
tensor = torch.rand(2, 3, 4)
# 차원 변경: (0,1,2) -> (2,0,1)
permuted = tensor.permute(2, 0, 1)
print(permuted.shape) # (4, 2, 3)
torch.Size([4, 2, 3])
Ex. 2. `transpose()`
`transpose(dim0, dim1)`는 특정 두 차원을 교환합니다.
tensor = torch.rand(2, 3)
transposed = tensor.transpose(0, 1)
print(transposed.shape) # (3, 2)
torch.Size([3, 2])
3.5 Tensor 복사 및 메모리 공유
함수
|
설명
|
clone()
|
메모리를 새롭게 복사
|
detach()
|
Autograd 그래프에서 분리
|
Ex. 1. `clone()` & `detach()`
`clone()`은 새로운 Tensor를 만들고, `detach()`는 자동 미분에서 제외합니다.
tensor = torch.rand(2, 2, requires_grad=True)
cloned = tensor.clone()
detached = tensor.detach()
print(cloned)
print(detached)
tensor([[0.2411, 0.9387],
[0.4739, 0.0760]], grad_fn=<CloneBackward0>)
tensor([[0.2411, 0.9387],
[0.4739, 0.0760]])
4. Tensor 연산
PyTorch에서 Tensor는 다양한 연산을 수행할 수 있으며, 기본적인 산술 연산부터 고급 행렬 연산, 인덱싱 및 슬라이싱,브로드캐스팅, 그리고 자동 미분까지 폭넓은 기능을 제공합니다.
이번 섹션에서는 기본 연산, 행렬 연산, 인덱싱, 브로드캐스팅, 자동 미분과 관련된 주요 개념을 설명하고, 코드 예제를 통해 알아보겠습니다.
4.1 기본 산술 연산
PyTorch에서는 기본적인 사칙연산을 지원하며, `torch.add()`, `torch.mul()`과 같은 함수형 API도 사용할 수 있습니다.
Ex. 1. 기본 산술 연산
import torch
a = torch.tensor([1, 2, 3])
b = torch.tensor([4, 5, 6])
# 기본 연산
add_result = a + b
sub_result = a - b
mul_result = a * b
div_result = a / b
print("덧셈 결과:", add_result)
print("뺄셈 결과:", sub_result)
print("곱셈 결과:", mul_result)
print("나눗셈 결과:", div_result)
# 함수형 연산
add_func_result = torch.add(a, b)
sub_func_result = torch.sub(a, b)
mul_func_result = torch.mul(a, b)
div_func_result = torch.div(a, b)
print("함수형 덧셈 결과:", add_func_result)
print("함수형 뺄셈 결과:", sub_func_result)
print("함수형 곱셈 결과:", mul_func_result)
print("함수형 나눗셈 결과:", div_func_result)
덧셈 결과: tensor([5, 7, 9])
뺄셈 결과: tensor([-3, -3, -3])
곱셈 결과: tensor([ 4, 10, 18])
나눗셈 결과: tensor([0.2500, 0.4000, 0.5000])
함수형 덧셈 결과: tensor([5, 7, 9])
함수형 뺄셈 결과: tensor([-3, -3, -3])
함수형 곱셈 결과: tensor([ 4, 10, 18])
함수형 나눗셈 결과: tensor([0.2500, 0.4000, 0.5000])
`torch.add()`, `torch.mul()` 같은 함수형 연산은 In-Place 연산(`out` 매개변수 지원) 가능성이 있으며, 메모리 효율성을 높일 수 있습니다.
기본적으로 PyTorch에서 함수형 연산(functional operation)은 원본 Tensor를 변경하지 않고 새로운 Tensor를 반환하는 연산을 의미하지만,
out 매개변수를 지원하여 기존 Tensor의 메모리를 재사용할 수 있습니다.
4.2 행렬 연산
Tensor간의 연산을 지원하는 함수들입니다.
Ex. 1. 행렬 곱 (`matmul`, `mm`)
일반적인 행렬 곱 연산을 수행합니다.
A = torch.tensor([[1, 2], [3, 4]])
B = torch.tensor([[5, 6], [7, 8]])
# 일반 행렬 곱 (Broadcasting 지원)
matmul_result = torch.matmul(A, B)
# 2D 행렬 간 곱
mm_result = torch.mm(A, B)
print("matmul 결과:\n", matmul_result)
print("mm 결과:\n", mm_result)
matmul 결과:
tensor([[19, 22],
[43, 50]])
mm 결과:
tensor([[19, 22],
[43, 50]])
`matmul()`은 2D, 3D, Broadcasting이 가능하지만 `mm()`은 2D 행렬에 한정됩니다.
※ Broadcasting이란?
Broadcasting(브로드캐스팅)은 크기가 다른 Tensor 간 연산을 자동으로 확장하여 수행하는 기능입니다.
PyTorch에서 기본적으로 두 개의 Tensor가 연산될 때, 크기가 동일해야 합니다.
하지만 크기가 다를 경우, PyTorch는 자동으로 작은 크기의 Tensor를 확장(반복)하여 연산이 가능하도록 조정합니다.
이를 Broadcasting이라고 합니다.
A = torch.tensor([[1, 2, 3], [4, 5, 6]]) # (2,3)
B = torch.tensor([10, 20, 30]) # (3,)
C = A + B # B가 (2,3) 크기로 Broadcasting됨
print(C)
tensor([[11, 22, 33],
[14, 25, 36]])
Ex. 2. 배치 행렬 곱 (`bmm`)
`bmm()`는 배치(batch) 연산을 위한 행렬 곱 전용 함수입니다.
batch_A = torch.rand(2, 3, 4)
batch_B = torch.rand(2, 4, 5)
batch_matmul_result = torch.bmm(batch_A, batch_B)
print("배치 행렬 곱 결과 Shape:", batch_matmul_result.shape) # (2, 3, 5)
배치 행렬 곱 결과 Shape: torch.Size([2, 3, 5])
Ex. 3. 아인슈타인 합 (`einsum`)
`einsum()`은 다양한 다차원 연산을 효율적으로 수행하는 강력한 도구입니다.
A = torch.tensor([[1, 2], [3, 4]])
B = torch.tensor([[5, 6], [7, 8]])
einsum_result = torch.einsum('ij,jk->ik', A, B)
print("아인슈타인 합 결과:\n", einsum_result)
아인슈타인 합 결과:
tensor([[19, 22],
[43, 50]])
4.3 인덱싱 및 슬라이싱
Tensor들을 특정한 방법으로 일정 부분을 선택하거나 추출하는 함수들입니다.
함수
|
설명
|
index_select()
|
특정 차원의 특정 인덱스 선택
|
masked_select()
|
조건을 만족하는 값 선택
|
gather()
|
주어진 인덱스에 따라 값을 추출
|
scatter()
|
특정 위치에 값 할당
|
Ex. 1. 특정 인덱스 선택 (`index_select`)
특정 행 또는 열을 선택하는 데 유용합니다.
x = torch.tensor([[1, 2], [3, 4], [5, 6]])
indices = torch.tensor([0, 2])
selected = torch.index_select(x, dim=0, index=indices)
print("index_select 결과:\n", selected)
index_select 결과:
tensor([[1, 2],
[5, 6]])
위 예제에서 사용된 torch.index_select()는 아래와 같이 사용됩니다.
torch.index_select(input, dim, index)
input : 원본 Tensor
dim : 선택할 차원 (예: dim=0이면 행, dim=1이면 열 기준 선택)
index : 선택할 인덱스를 포함한 1D Tensor
이 함수는 dim 차원에서 index에 해당하는 원소들을 선택하여 새로운 Tensor를 반환합니다.
dim=0이므로 행을 기준으로 선택하고, 인덱스 리스트 indices = [0, 2]이므로, 0번째 행과 2번째 행을 선택하게 됩니다.
즉, 0번째 행: [1, 2] , 2번째 행: [5, 6] 을 선택하여서 새로운 Tensor, 'selected'에 대입합니다.
4.4 브로드캐스팅 개념
브로드캐스팅(Broadcasting)이란 앞서 잠깐 설명한 것과 같이, 차원이 다른 Tensor 간 연산을 수행할 때 자동으로 크기를 맞춰주는 기능입니다.
함수
|
설명
|
expand()
|
특정 차원 크기를 늘려서 재사용 가능하게 확장
|
expand_as()
|
기존 Tensor와 동일한 크기로 확장
|
x = torch.tensor([[1], [2], [3]]) # Shape: (3,1)
# (3,1) -> (3,4)로 확장
expanded = x.expand(3, 4)
print("expand 결과:\n", expanded)
expand 결과:
tensor([[1, 1, 1, 1],
[2, 2, 2, 2],
[3, 3, 3, 3]])
더욱 다양한 PyTorch 강의를 보시려면 아래 강의 목록을 읽어보시면 도움이 됩니다.
1. PyTorch 소개
https://moonlight314.tistory.com/entry/1-PyTorch-%EC%86%8C%EA%B0%9C
1. PyTorch 소개
안녕하세요, MoonLight입니다.Deep Learning Framework의 양대산맥이라고 하면 Tensorflow와 PyTorch일 것입니다.예전에는 다양한 Framework이 많이 있었지만, 이제는 거의 이 2개가 대부분을 차지한다고 할
moonlight314.tistory.com
2. PyTorch의 주요 Module 소개
2. PyTorch의 주요 Module 소개
안녕하세요, MoonLight입니다.이번 Post에서는 PyTorch를 구성하는 다양한 Module에 대해서 소개해 드리고자 합니다.Model을 설계하고 Train 시키는데 매우 다양한 기능이 필요한 것은 어찌보면 당
moonlight314.tistory.com
3. Tensor
https://moonlight314.tistory.com/entry/3-Tensor
3. Tensor
안녕하세요, MoonLight입니다.이번 Post에서는 Deep Learning에서 Data를 표현하기 위한 자료구조인 Tensor에 대해서 알아보도록 하겠습니다.1. Tensor1.1 Tensor의 개념Tensor는 겉으로 보기에 숫자로
moonlight314.tistory.com
4. Basic Train Loop
https://moonlight314.tistory.com/entry/4-Basic-Train-Loop
4. Basic Train Loop
안녕하세요, MoonLight입니다.이번 글에서는 PyTorch를 이용한 기본적인 Train Loop를 분석하고, 각 구성 요소가 하는 역할을 상세히 설명합니다. 이를 통해 신경망 모델을 학습하는 과정에서 필요
moonlight314.tistory.com
5. Dataset & DataLoader
https://moonlight314.tistory.com/entry/5-Dataset-DataLoader
5. Dataset & DataLoader
안녕하세요, MoonLigt입니다.이번 Post에서는 Train Data를 효율적으로 가공하고 Model에 공급(?)해 주는 역할을 하는 Dataset & DataLoader Module에 대해서 알아보도록 하겠습니다.1. Dataset & DataLoader
moonlight314.tistory.com
6. 신경망 구성 - Container Class
6. 신경망 구성 - Container Class
안녕하세요, MoonLight입니다.이번 장에서는 신경망을 구성하는 기본 개념과, PyTorch에서 제공하는 다양한 Container Class를 활용하여 신경망을 구축하는 방법에 대해 알아보겠습니다.1. Model
moonlight314.tistory.com
7. Loss Function( 손실 함수 )
https://moonlight314.tistory.com/entry/7-Loss-Function-%EC%86%90%EC%8B%A4-%ED%95%A8%EC%88%98
7. Loss Function( 손실 함수 )
안녕하세요, MoonLight입니다.이번 Post에서는 모델이 학습을 잘하고 있는지 정량적으로 표현할 수 있게 해주는 손실함수(Loss Function)에 대해서 알아보도록 하겠습니다.1. Loss Function1.1. Loss F
moonlight314.tistory.com
8. Optimizers
https://moonlight314.tistory.com/entry/8-Optimizers
8. Optimizers
안녕하세요, MoonLight입니다.이번 장에서는 딥러닝 모델의 Train을 하는데 있어서 중요한 요소중의 하나인, Optimizer에 대해서 알아보도록 하겠습니다.1. Optimization in Deep Learning1.1. Optimizati
moonlight314.tistory.com
9. Learning Rate Schedulers
https://moonlight314.tistory.com/entry/9-Learning-Rate-Schedulers
9. Learning Rate Schedulers
안녕하세요, MoonLight입니다.이번 Post에서는 Learning Rate를 효율적으로 변경하여 학습이 잘 이루어지도록 도와주는 Learning Rate Scheduler에 대해서 알아보도록 하겠습니다.1. Learning Rate1
moonlight314.tistory.com
10. Early Stopping
https://moonlight314.tistory.com/entry/10-Early-Stopping
10. Early Stopping
안녕하세요, MoonLight입니다.이번 Post에서는 모델의 학습을 적절한 시점에 마무리 할 수 있도록 해주는 Early Stopping이라는 개념과 구현에 대해서 알아보도록 하겠습니다.1. Early Stopping1.1. E
moonlight314.tistory.com
'PyTorch' 카테고리의 다른 글
7. Loss Function( 손실 함수 ) (0) | 2025.03.03 |
---|---|
6. 신경망 구성 - Container Class (0) | 2025.03.03 |
5. Dataset & DataLoader (0) | 2025.03.03 |
4. Basic Train Loop (0) | 2025.03.03 |
1. PyTorch 소개 (0) | 2025.03.03 |