넘파이로 텐서 만들기(벡터와 행렬 만들기)
PyTorch로 텐서를 만들어보기 전에 우선 Numpy로 텐서를 만들어보겠습니다. 우선 numpy를 임포트합니다.
import numpy as np
Numpy로 텐서를 만드는 방법은 간단한데 [숫자, 숫자, 숫자]와 같은 형식으로 만들고 이를 np.array()로 감싸주면 됩니다.
1) 1D with Numpy
Numpy로 1차원 텐서인 벡터를 만들어보겠습니다.
t = np.array([0., 1., 2., 3., 4., 5., 6.])
# 파이썬으로 설명하면 List를 생성해서 np.array로 1차원 array로 변환함.
print(t)
[0. 1. 2. 3. 4. 5. 6.]
이제 1차원 텐서인 벡터의 차원과 크기를 출력해보겠습니다.
print('Rank of t: ', t.ndim)
print('Shape of t: ', t.shape)
여기 주의할 것!
1행 7열이지만 .shape은 m행 n열로 나온다 헷갈리지 않게 조심하기!!
Rank of t: 1
Shape of t: (7,)
.ndim은 몇 차원인지를 출력합니다. 1차원은 벡터, 2차원은 행렬, 3차원은 3차원 텐서였습니다. 현재는 벡터이므로 1차원이 출력됩니다. .shape는 크기를 출력합니다. (7, )는 (1, 7)을 의미합니다. 다시 말해 (1 × 7)의 크기를 가지는 벡터입니다.
- 옮긴이 주 : 텐서의 크기(shape)를 표현할 때는 ,(컴마)를 쓰기도 하고 ×(곱하기)를 쓰기도 합니다. 예를 들어 2행 3열의 2D 텐서를 표현할 때 (2, 3)라고 하기도 하고 (2 × 3)이라고 하기도 합니다. (5, )의 형식은 (1 × 5)를 의미합니다.
1-1) Numpy 기초 이해하기
이제 Numpy에서 각 벡터의 원소에 접근하는 방법을 알아보겠습니다. Numpy에서 인덱스는 0부터 시작합니다.
파이썬의 인덱싱과 슬라이싱과 동일하다.
t = np.array([0., 1., 2., 3., 4., 5., 6.])
# 파이썬으로 설명하면 List를 생성해서 np.array로 1차원 array로 변환함.
print(t)
[0. 1. 2. 3. 4. 5. 6.]
print('t[0] t[1] t[-1] = ', t[0], t[1], t[-1]) # 인덱스를 통한 원소 접근
t[0] t[1] t[-1] = 0.0 1.0 6.0
위의 결과는 0번 인덱스를 가진 원소인 0.0, 1번 인덱스를 가진 원소인 1.0, -1번 인덱스를 가진 원소인 6.0이 출력되는 것을 보여줍니다. -1번 인덱스는 맨 뒤에서부터 시작하는 인덱스입니다.
범위 지정으로 원소를 불러올 수도 있습니다. 이를 슬라이싱(Slicing)이라고 합니다. 사용 방법은 [시작 번호 : 끝 번호]를 통해 사용합니다. 주의할 점은 슬라이싱은 [시작 번호 : 끝 번호]라고 했을 때, 끝 번호에 해당하는 것은 포함하지 않습니다.
print('t[2:5] t[4:-1] = ', t[2:5], t[4:-1]) # [시작 번호 : 끝 번호]로 범위 지정을 통해 가져온다.
t[2:5] t[4:-1] = [2. 3. 4.] [4. 5.]
위의 슬라이싱의 결과를 보겠습니다. [2:5]라고 한다면 2번 인덱스부터 4번 인덱스까지의 결과를 가져온다는 의미입니다. [4:-1]은 4번 인덱스부터 끝에서 첫번째 것까지의 결과를 가져온다는 의미입니다.
시작 번호 또는 끝 번호를 생략해서 슬라이싱을 하기도 합니다. [시작 번호:끝 번호]에서 시작 번호를 생략하면 처음부터 끝 번호까지 뽑아냅니다, 반면에 [시작 번호:끝 번호]에서 끝 번호를 생략하면 시작 번호부터 끝까지 뽑아냅니다.
print('t[:2] t[3:] = ', t[:2], t[3:]) # 시작 번호를 생략한 경우와 끝 번호를 생략한 경우
t[:2] t[3:] = [0. 1.] [3. 4. 5. 6.]
2) 2D with Numpy
Numpy로 2차원 행렬을 만들어보겠습니다.
t = np.array([[1., 2., 3.], [4., 5., 6.], [7., 8., 9.], [10., 11., 12.]])
print(t)
[[ 1. 2. 3.]
[ 4. 5. 6.]
[ 7. 8. 9.]
[10. 11. 12.]]
print('Rank of t: ', t.ndim)
print('Shape of t: ', t.shape)
Rank of t: 2
Shape of t: (4, 3)
.ndim은 몇 차원인지를 출력합니다. 1차원은 벡터, 2차원은 행렬, 3차원은 3차원 텐서였습니다. 현재는 행렬이므로 2차원이 출력됩니다. .shape는 크기를 출력합니다. (4, 3)입니다. 다른 표현으로는 (4 × 3)입니다. 이는 행렬이 4행 3열임을 의미합니다.
파이토치 텐서 선언하기(PyTorch Tensor Allocation)
파이토치는 Numpy와 매우 유사합니다. 하지만 더 낫습니다(better). 우선 torch를 임포트합니다.
import torch
Numpy를 사용하여 진행했던 실습을 파이토치로 똑같이 해봅시다.
1) 1D with PyTorch
파이토치로 1차원 텐서인 벡터를 만들어봅시다.
t = torch.FloatTensor([0., 1., 2., 3., 4., 5., 6.])
print(t)
dim()을 사용하면 현재 텐서의 차원을 보여줍니다. shape나 size()를 사용하면 크기를 확인할 수 있습니다.
print(t.dim()) # rank. 즉, 차원
print(t.shape) # shape
print(t.size()) # shape
1
torch.Size([7])
torch.Size([7])
현재 1차원 텐서이며, 원소는 7개입니다. 인덱스로 접근하는 것과 슬라이싱을 해봅시다. 방법은 Numpy 실습과 같습니다.
print(t[0], t[1], t[-1]) # 인덱스로 접근
print(t[2:5], t[4:-1]) # 슬라이싱
print(t[:2], t[3:]) # 슬라이싱
tensor(0.) tensor(1.) tensor(6.)
tensor([2., 3., 4.]) tensor([4., 5.])
tensor([0., 1.]) tensor([3., 4., 5., 6.])
2) 2D with PyTorch
파이토치로 2차원 텐서인 행렬을 만들어봅시다.
t = torch.FloatTensor([[1., 2., 3.],
[4., 5., 6.],
[7., 8., 9.],
[10., 11., 12.]
])
print(t)
tensor([[ 1., 2., 3.],
[ 4., 5., 6.],
[ 7., 8., 9.],
[10., 11., 12.]])
dim()을 사용하면 현재 텐서의 차원을 보여줍니다. size()를 사용하면 크기를 확인할 수 있습니다.
print(t.dim()) # rank. 즉, 차원
print(t.size()) # shape
2
torch.Size([4, 3])
현재 텐서의 차원은 2차원이며, (4, 3)의 크기를 가집니다. 슬라이싱을 해봅시다.
print(t_2d[1, 0])
print(t_2d[1, 0].size()) # ↑ 위의 경우의 크기
tensor(4.)
torch.Size([])
print(t[:, 1]) # 첫번째 차원을 전체 선택한 상황에서 두번째 차원의 첫번째 것만 가져온다.
print(t[:, 1].size()) # ↑ 위의 경우의 크기
tensor([ 2., 5., 8., 11.])
torch.Size([4])
위의 결과는 첫번째 차원을 전체 선택하고, 그 상황에서 두번째 차원의 1번 인덱스 값만을 가져온 경우를 보여줍니다. 다시 말해 텐서에서 두번째 열에 있는 모든 값을 가져온 상황입니다. 그리고 이렇게 값을 가져온 경우의 크기는 4입니다. (1차원 벡터)
print(t[:, :-1]) # 첫번째 차원을 전체 선택한 상황에서 두번째 차원에서는 맨 마지막에서 첫번째를 제외하고 다 가져온다.
tensor([[ 1., 2.],
[ 4., 5.],
[ 7., 8.],
[10., 11.]])
위의 결과는 첫번째 차원을 전체 선택한 상황에서 두번째 차원에서는 맨 마지막에서 첫번째를 제외하고 다 가져오는 경우입니다.