Deep Learning & Machine Learning/PyTorch

[PyTorch] tutorial, 1.텐서(TENSOR)

cho.nii 2024. 5. 19. 19:16

텐서란?

  • 배열(array)이나 행렬(matrix)과 매우 유사한 특수 자료구조
  • PyTorch에서는 텐서를 사용하여 모델의 입출력, 모델의 매개변수들을 부호화(encode)한다.
  • GPU나 다른 하드웨어 가속기에서 실행할 수 있다는 점을 제외하면 Numpy의 ndarray와 유사하다.
import torch
import numpy as np

 

텐서를 초기화할 수 있는 다양한 방법

(1) 데이터로부터 직접(directly) 생성하기

  • 데이터로부터 직접 텐서 생성 가능하며, 데이터의 자료형(data type)은 자동으로 유추한다.
data = [[1, 2],[3, 4]]
x_data = torch.tensor(data)
x_data.type

 

Out:

<function Tensor.type>

 

 

(2) Numpy 배열로부터 생성하기

  • 텐서를 Numpy 배열로 생성할 수도 있고, 그 반대의 경우도 가능하다.
data = [[1, 2],[3, 4]]
np_array = np.array(data)
x_np = torch.from_numpy(np_array)
print(x_np)
print(x_np.type)

 

Out:

tensor([[1, 2],
        [3, 4]])
<built-in method type of Tensor object at 0x7ba0342e7100>

 

 

(3) 다른 텐서로부터 생성하기

  • 명시적으로 재정의(override)하지 않는다면, 인자로 주어진 텐서의 속성(모양(shape), 자료형(datatype))을 유지한다.
x_ones = torch.ones_like(x_data) # x_data의 속성을 유지합니다.
print(f"Ones Tensor: \n {x_ones} \n")

x_rand = torch.rand_like(x_data, dtype=torch.float) # x_data의 속성을 덮어씁니다.
print(f"Random Tensor: \n {x_rand} \n")

 

 

Out:

Ones Tensor: 
 tensor([[1, 1],
        [1, 1]]) 

Random Tensor: 
 tensor([[0.7089, 0.1605],
        [0.8326, 0.8503]])

 

 

(4) 무작위(random) 또는 상수(constant) 값을 사용하기

  • shape 은 텐서의 차원(dimension)을 나타내는 튜플로, 아래 함수들에서는 출력 텐서의 차원을 결정한다.
shape = (2,3,)
rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)

print(f"Random Tensor: \n {rand_tensor} \n")
print(f"Ones Tensor: \n {ones_tensor} \n")
print(f"Zeros Tensor: \n {zeros_tensor}")

 

Out:

Random Tensor: 
 tensor([[0.7140, 0.8006, 0.7532],
        [0.6828, 0.6624, 0.9133]]) 

Ones Tensor: 
 tensor([[1., 1., 1.],
        [1., 1., 1.]]) 

Zeros Tensor: 
 tensor([[0., 0., 0.],
        [0., 0., 0.]])

 

 

텐서의 속성(Attribute)

  • 텐서의 모양(shape), 자료형(datatype) 및 어느 장치에 저장되는지를 나타낸다.
tensor = torch.rand(3,4)

print(f"Shape of tensor: {tensor.shape}")
print(f"Datatype of tensor: {tensor.dtype}")
print(f"Device tensor is stored on: {tensor.device}")

 

Out:

Shape of tensor: torch.Size([3, 4])
Datatype of tensor: torch.float32
Device tensor is stored on: cpu

 

 

텐서 연산(Operation)

  • 전치(transposing), 인덱싱(indexing), 슬라이싱(slicing), 수학 계산, 선형 대수, 임의 샘플링(random sampling) 외에도 다양한 텐서 연산들이 있다.
  • 기본적으로 텐서는 CPU에 생성되는데, .to 메소드를 사용하면 GPU의 가용성을 확인한 뒤 GPU로 텐서를 명시적으로 이동할 수 있다.
# GPU가 존재하면 텐서를 이동합니다
if torch.cuda.is_available():
    tensor = tensor.to("cuda")

 

Numpy식의 표준 인덱싱과 슬라이싱

tensor = torch.ones(4, 4)
print(f"First row: {tensor[0]}")
print(f"First column: {tensor[:, 0]}")
print(f"Last column: {tensor[..., -1]}")
tensor[:,1] = 0
print(tensor)

 

Out:

First row: tensor([1., 1., 1., 1.])
First column: tensor([1., 1., 1., 1.])
Last column: tensor([1., 1., 1., 1.])
tensor([[1., 0., 1., 1.],
        [1., 0., 1., 1.],
        [1., 0., 1., 1.],
        [1., 0., 1., 1.]])

 

텐서 합치기

  • torch.cat 을 사용하여 주어진 차원에 따라 일련의 텐서를 연결할 수 있다.
  • 또 다른 텐서 결합 연산으로 torch.stack도 있는데 torch.cat 과 약간 다르다.

torch.cat

t1 = torch.cat([tensor, tensor, tensor], dim=1)
print(t1)

 

Out:

tensor([[1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],
        [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],
        [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.],
        [1., 0., 1., 1., 1., 0., 1., 1., 1., 0., 1., 1.]])

 

torch.stack

t1_ = torch.stack([tensor, tensor, tensor], dim=1)
print(t1_)

 

Out:

tensor([[[1., 0., 1., 1.],
         [1., 0., 1., 1.],
         [1., 0., 1., 1.]],

        [[1., 0., 1., 1.],
         [1., 0., 1., 1.],
         [1., 0., 1., 1.]],

        [[1., 0., 1., 1.],
         [1., 0., 1., 1.],
         [1., 0., 1., 1.]],

        [[1., 0., 1., 1.],
         [1., 0., 1., 1.],
         [1., 0., 1., 1.]]])

 

산술 연산(Arithmetic operations)

tensor.matmul

print(y1)
print(y2)
print(y3)

 

Out:

tensor([[3., 3., 3., 3.],
        [3., 3., 3., 3.],
        [3., 3., 3., 3.],
        [3., 3., 3., 3.]])
tensor([[3., 3., 3., 3.],
        [3., 3., 3., 3.],
        [3., 3., 3., 3.],
        [3., 3., 3., 3.]])
tensor([[3., 3., 3., 3.],
        [3., 3., 3., 3.],
        [3., 3., 3., 3.],
        [3., 3., 3., 3.]])

 

# 두 텐서 간의 행렬 곱(matrix multiplication)을 계산합니다. y1, y2, y3은 모두 같은 값을 갖습니다.
# ``tensor.T`` 는 텐서의 전치(transpose)를 반환합니다.
y1 = tensor @ tensor.T
y2 = tensor.matmul(tensor.T)

y3 = torch.rand_like(y1)
torch.matmul(tensor, tensor.T, out=y3)

 

Out:

tensor([[3., 3., 3., 3.],
        [3., 3., 3., 3.],
        [3., 3., 3., 3.],
        [3., 3., 3., 3.]])

 

tensor.mul

print(z1)
print(z2)
print(z3)

 

Out:

tensor([[1., 0., 1., 1.],
        [1., 0., 1., 1.],
        [1., 0., 1., 1.],
        [1., 0., 1., 1.]])
tensor([[1., 0., 1., 1.],
        [1., 0., 1., 1.],
        [1., 0., 1., 1.],
        [1., 0., 1., 1.]])
tensor([[1., 0., 1., 1.],
        [1., 0., 1., 1.],
        [1., 0., 1., 1.],
        [1., 0., 1., 1.]])

 

# 요소별 곱(element-wise product)을 계산합니다. z1, z2, z3는 모두 같은 값을 갖습니다.
z1 = tensor * tensor
z2 = tensor.mul(tensor)

z3 = torch.rand_like(tensor)
torch.mul(tensor, tensor, out=z3)

 

Out:

tensor([[1., 0., 1., 1.],
        [1., 0., 1., 1.],
        [1., 0., 1., 1.],
        [1., 0., 1., 1.]])

 

 

단일-요소(single-element) 텐서

  • 텐서의 모든 값을 하나로 집계(aggregate)하여 요소가 하나인 텐서의 경우, item()을 사용하여 Python 숫자 값으로 변환할 수 있다.
agg = tensor.sum()
agg_item = agg.item()
print(agg_item, type(agg_item))

 

Out:

12.0 <class 'float'>

 

 

바꿔치기(in-place) 연산

  • 연산 결과를 피연산자(operand)에 저장하는 연산으로, _ 접미사를 가진다.
  • 예를 들어, x.copy_(y) 또는 x.t_()는 x를 변경한다.
  • 해당 연산은 메모리를 일부 절약하지만, 기록(history)이 즉시 삭제되어 도함수(derivation) 계산에 문제가 발생할 수 있어, 사용을 권장하지 않는다.
print(f"{tensor} \n")
tensor.add_(5)
print(tensor)

 

Out:

tensor([[1., 0., 1., 1.],
        [1., 0., 1., 1.],
        [1., 0., 1., 1.],
        [1., 0., 1., 1.]]) 

tensor([[6., 5., 6., 6.],
        [6., 5., 6., 6.],
        [6., 5., 6., 6.],
        [6., 5., 6., 6.]])

 

 

Numpy 변환(Bridge)

  • CPU 상의 텐서와 Numpy 배열은 메모리 공간을 공유하기 때문에, 하나를 변경하면 다른 하나도 변경된다.

텐서를 Numpy 배열로 변환하기

t = torch.ones(5)
print(f"t: {t}")
n = t.numpy()
print(f"n: {n}")

 

Out:

t: tensor([1., 1., 1., 1., 1.])
n: [1. 1. 1. 1. 1.]

 

텐서의 변경 사항이 Numpy 배열에 반영된다.

t.add_(1)
print(f"t: {t}")
print(f"n: {n}")

 

Out:

t: tensor([2., 2., 2., 2., 2.])
n: [2. 2. 2. 2. 2.]

 

Numpy 배열을 텐서로 변환하기

n = np.ones(5)
t = torch.from_numpy(n)

 

Numpy 배열의 변경 사항이 텐서에 반영된다. 

np.add(n, 1, out=n)
print(f"t: {t}")
print(f"n: {n}")

 

Out:

t: tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
n: [2. 2. 2. 2. 2.]

 

 

https://tutorials.pytorch.kr/beginner/basics/tensorqs_tutorial.html

 

텐서(Tensor)

파이토치(PyTorch) 기본 익히기|| 빠른 시작|| 텐서(Tensor)|| Dataset과 Dataloader|| 변형(Transform)|| 신경망 모델 구성하기|| Autograd|| 최적화(Optimization)|| 모델 저장하고 불러오기 텐서(tensor)는 배열(array)이

tutorials.pytorch.kr