[PyTorch] Tensor manipulation

지윤곽·2022년 3월 9일
0

Reference

Tensor

정의 : 다차원 Array 를 표현하는 Pytorch 클래스

  • numpy의 ndarray 와 동일 (Tensorflow의 Tensor와 동일) torch.FloatTensor(array)
## numpy - ndarray
import numpy as np
n_array = np.arange(10) # 10개의 1차원 벡터를 
n_array = n_array.reshape(2,5) # row 2 col 5의 2차원 벡터로 변환
print(n_array.ndim, n_array.shape) # 2차원의 (2,5)shape을 가짐
### ndim : 2 shape : (2, 5)

## torch - tensor
import torch # 위에 tensor만 붙음
t_array = torch.FloatTensor(n_array)
print(t_array.ndim, t_array.shape)
  • tensor를 생성할 때 list나 ndarray 사용 가능 torch.tensor(data) torch.from_numpy(ndarray)
data = [[3,5],[10,5]] # 리스트
x_data = torch.tensor(data)

nd_array_ex = np.array(data) # ndarray
tensor_array = torch.from_numpy(nd_array_ex)
  • ndarray의 문법을 그대로 사용한다.
data = [[3, 5, 20],[10, 5, 50], [1, 5, 10]]
x_data = torch.tensor(data)

# 1) slicing
print(x_data[:2, 1:]) # row, col

#2) flatten
print(x_data.flatten())

#3) ones_like
print(torch.ones_like(x_data)) # 크기를 맞춰 연산할 경우 많이 사용됨
### tensor([[1, 1, 1],
###        [1, 1, 1],
###        [1, 1, 1]])

#4) numpy
print(x_data.numpy())

#5) shape, dtype
print(x_data.shape, x_data.dtype)

GPU 사용

torch.cuda.is_available()

torch.to(device)

  • tensor가 가지는 data type은 numpy와 동일 → GPU를 사용하냐 마냐에 따라 차이가 있음 (x_data.device)

Untitled

# cpu 사용
x_data.device 
### device(type='cpu')

# GPU 사용
if torch.cuda.is_available():
	x_data_cuda = x_data.to('cuda')
x_data_cuda.device
# device(type='cuda', index=0)

# 실제 사용 예제
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)

Tensor Handling

view / reshape

: tensor의 shape 변환 # reshape보다는 view를 써라!

tensor_ex = torch.rand(size=(2,3,2))

tensor_ex.view([-1,6]) 
# 2*3*2=12인 tensor를 뒤에가 6으로 맞춰서 앞은 2로 알아서 계산됨
tensor_ex.reshape([-1,6])
# view 와 reshape의 결과값 똑같음

view와 reshape의 차이점

view : 얕은 복사 (주소값이 동일) - original을 변형하면 copy 값도 변경됨

reshape : 깊은 복사 (주소값이 다름) - 원형을 변경해도 copy된 값은 변하지 않음

a = torch.zeros(3,2)
b = a.view(2,3)
a.fill_(1)
########
a
tensor([[1., 1.],
        [1., 1.],
        [1., 1.]])

b (view) # 1로 채워진다
tensor([[1., 1., 1.],
        [1., 1., 1.]])

a =torch.zeros(3,2)
b = a.t().reshape(6)
a.fill_(1)

b (reshape) # 1로 채워지지 않음
tensor([0., 0., 0., 0., 0., 0.])

squeeze / unsqueeze

: 차원의 개수 1개 삭제/추가

Untitled

22 tensor = unsqeeze(0) ⇒ 122 (0), 212 (1), 22*1 (2) ← 차원의 위치를 지정해서 더해줄 수 있음

  • 행렬 곱 연산 : mm, matmul (dot은 사용하지 않기!)
a = torch.rand(5,2, 3)
b = torch.rand(3)
a.mm(b) # Error
a.matmul(b) # (5,2)

t1.dot(t2) # 5*2*3 3*1 => 5*2*1

Q. dot함수는 1차원 tensor에서만 가능? 왜 runtime error가 생기는 건가?

A: dot 함수는 1차원 텐서에만 적용되는 함수이다!

위의 예제에서 볼 수 있듯이 matmul은 braodcasting을 지원한다.

nn.functional

  • nn.functional 모듈을 사용해 다양한 수식을 제공

⇒ 외울 필요 없고 그때마다 찾아서 써라!

import torch
import torch.nn.functional as F
# softmax 변환
tensor = torch.FloatTensor([0.5, 0.7, 0.1])
h_tensor = F.softmax(tensor, dim=0)

# one hot encoding
y = torch.randint(5, (10,5))
y_label = y.argmax(dim=1)

F.one_hot(y_label)
tensor([[1, 0, 0, 0],
        [1, 0, 0, 0],
        [1, 0, 0, 0],
        [1, 0, 0, 0],
        [0, 0, 0, 1],
        [0, 1, 0, 0],
        [0, 0, 0, 1],
        [1, 0, 0, 0],
        [0, 1, 0, 0],
        [1, 0, 0, 0]])

# cartesian_product => 모든 경우의수 계산
import itertools
a = [1, 2, 3]
b = [4, 5]
list(itertools.product(a, b))
# [(1, 4), (1, 5), (2, 4), (2, 5), (3, 4), (3, 5)]
tensor_a = torch.tensor(a)
tensor_b = torch.tensor(b)
torch.cartesian_prod(tensor_a, tensor_b)
# tensor([[1, 4],
        [1, 5],
        [2, 4],
        [2, 5],
        [3, 4],
        [3, 5]])

AutoGrad

1) w = torch.tensor(2.0, requires_grad = True)

: 미분하는 대상에 requires_grad 를 True를 해준다. ⇒ 보통 linear나 함수를 사용하는 requires_grad가 true로 설정이 되어 있음

2) y = w**2

3) z = 10*y + 2

4) z.backward()

5) w.gard

스크린샷 2022-03-09 오후 1.33.31.png

#편미분인 경우

Untitled

a = torch.tensor([2., 3.], requires_grad=True)
b = torch.tensor([6., 4.], requires_grad=True)
Q = 3*a**3 - b**2
external_grad = torch.tensor([1., 1.])
Q.backward(gradient=external_grad)

a.grad # tensor([36., 81.])
b.grad # tensor([-12.,  -8.])

[추가질문] torch.tensor 와 torch.Tensor는 뭐가 다를까?

출처 : Documentation main - PyTorch 공식 문서

tensor.torch()

  • 함수
  • int → int
  • 입력 받은 데이터를 복사 후 사용

tensor.Tensor()

  • 클래스
  • int → float
  • torch : 입력받은 데이터의 메모리 사용, list, array : 데이터를 복사하여 사용

기본적인 차이는

  • tensor.torch() : function
  • tensor.Torch() : class

이라는 것이다.

⇒ 결과적으로 데이터 타입을 tensor로 바꾸고 싶으면 torch.tensor를 사용하는게 더 안전하다.

profile
아는게 힘이다

0개의 댓글

관련 채용 정보