참고자료: https://wikidocs.net/book/2788
자주 사용하는 기능
5️⃣뷰(View)⭐️
👉🏻원소의 수를 유지하면서 텐서의 크기를 변경한다.
👉🏻넘파이의 리쉐이프 역할을 하는데 리쉐이프란 텐서의 크기(shape)를 변경해주는 것이다.
t = np.array([[[0, 1, 2],
[3, 4, 5]],
[[6, 7, 8],
[9, 10, 11]]])
ft = torch.FloatTensor(t)
print(ft.shape) #torch.Size([2, 2, 3])
👉🏻3차원 텐서인 ft를 만들었고 shape은 다음과 같다.
✅3차원 텐서에서 2차원 텐서로 변경
print(ft.view([-1, 3]))
print(ft.view([-1, 3]).shape)
#tensor([[ 0., 1., 2.],
# [ 3., 4., 5.],
# [ 6., 7., 8.],
# [ 9., 10., 11.]])
#torch.Size([4, 3])
👉🏻ft라는 텐서를 (?, 3)의 크기로 변경하는 것이다.
✍🏻view([[-1, 3])의 의미: 3차원 텐서를 2차원 텐서로 변경하되 (?, 3)의 크기로 변형하라는 의미이다. 결과적으로 (4, 3)의 크기를 갖는 텐서를 얻었다.
- -1: 첫번째 차원은 사용자가 잘 모르겠으니 파이토치에게 맡기겠다는 의미
- 3: 두번째 차원의 길이는 3을 가지도록 하라는 의미
👉🏻(2, 2, 3) → (2 *2, 3) → (4, 3)
👉🏻규칙
- view는 기본적으로 변경 전과 변경 후의 텐서 안의 원소의 개수가 유지되어야 한다.
- 파이토치의 view는 사이즈가 -1로 설정이 되면 다른 차원으로부터 해당 값을 유추한다.
✅3차원 텐서의 크기 변경
👉🏻차원은 유지하되 크기만 바꾼다.
print(ft.view([-1, 1, 3]))
print(ft.view([-1, 1, 3]).shape)
#tensor([[[ 0., 1., 2.]],
#
# [[ 3., 4., 5.]],
#
# [[ 6., 7., 8.]],
#
# [[ 9., 10., 11.]]])
#torch.Size([4, 1, 3])
✍🏻원소의 수가 유지되어야 함을 잊지말자! (2 * 2 * 3) 텐서를 (? * 1 * 3)텐서로 바꾸기 위해 ?는 4가 되어야 한다.
6️⃣스퀴즈(Squeeze)
👉🏻1인 차원을 제거한다.
ft = torch.FloatTensor([[0], [1], [2]])
print(ft)
print(ft.shape)
#tensor([[0.],
# [1.],
# [2.]])
#torch.Size([3, 1])
👉🏻(3 x 1)인 2차원 텐서가 있다. 두번째 차원이 2이므로 squeeze를 사용하면 (3,)의 크기를 가지는 텐서로 변경된다.
print(ft.squeeze())
print(ft.squeeze().shape)
#tensor([0., 1., 2.])
#torch.Size([3])
👉🏻1차원 벡터가 되었다!
7️⃣언스퀴즈(Unsqueeze)
👉🏻특정 위치에 1인 차원을 추가한다.
ft = torch.Tensor([0, 1, 2])
print(ft.shape)
#torch.Size([3])
👉🏻(3,)의 크기를 가지는 1인 차원 텐서(1차원 벡터)를 만들었다.
print(ft.unsqueeze(0))
print(ft.unsqueeze(0).shape)
#tensor([[0., 1., 2.]])
#torch.Size([1, 3])
👉🏻첫번째 차원의 인덱스를 의미하는 0을 인자로 넣으면 첫번째 차원에 1인 차원이 추가된다. 결과적으로 (1, 3)의 2차원 텐서로 변경되었다. 이는 view로도 구현이 가능하다.
print(ft.view([1, -1]))
print(ft.view([1, -1]).shape)
#tensor([[0., 1., 2.]])
#torch.Size([1, 3])
👉🏻view에서는 (1, -1)을 인자로 사용하면 1인 차원을 추가할 수 있다.
print(ft.unsqueeze(1))
print(ft.unsqueeze(1).shape)
#tensor([[0.],
# [1.],
# [2.]])
#torch.Size([3, 1])
👉🏻두번째 차원을 의미하는 1을 인자로 넣으면 두번째 차원에 1을 추가해서 (3, 1)의 크기를 가지게 된다.
print(ft.unsqueeze(-1))
print(ft.unsqueeze(-1).shape)
#tensor([[0.],
# [1.],
# [2.]])
#torch.Size([3, 1])
👉🏻마지막 차원을 의미하는 -1을 인자로 넣으면 (3, 1)의 크기를 가지게 된다.
📌view(), squeeze(), unsqueeze()는 텐서의 원소 수를 그대로 유지하면서 모양과 차원을 조절한다.
8️⃣타입 캐스팅(Type Casting)
👉🏻텐서에 자료형이 있는데 각 데이터형별로 정의되어 있다. 아래는 예시이고 이 자료형을 변환하는 것을 타입 캐스팅이라고 한다.
- torch.FloatTensor - 32비트의 부동 소수점
- torch.LongTensor - 64비트의 부호 있는 정수
- torch.cuda.FloatTensor - GPU연산을 위한 자료형
lt = torch.LongTensor([1, 2, 3, 4])
print(lt)
print(lt.float())
#tensor([1, 2, 3, 4])
#tensor([1., 2., 3., 4.])
👉🏻.float()를 붙이면 float형으로 타입이 변경된다.
bt = torch.ByteTensor([True, False, False, True])
print(bt)
#tensor([1, 0, 0, 1], dtype=torch.uint8)
print(bt.long())
print(bt.float())
#tensor([1, 0, 0, 1])
#tensor([1., 0., 0., 1.])
👉🏻Byte타입의 bt텐서를 long과 float 타입으로 변경해보았다.
9️⃣연결하기(concatenate)
x = torch.FloatTensor([[1, 2], [3, 4]])
y = torch.FloatTensor([[5, 6], [7, 8]])
print(torch.cat([x, y], dim=0))
#tensor([[1., 2.],
# [3., 4.],
# [5., 6.],
# [7., 8.]])
👉🏻torch.cat([])을 통해 연결해줄 수 있다. 게다나 어느 차원을 늘릴 것인지 인자로 줄 수 있다. 위와 같이 dim=0은 첫번째 차원을 늘리라는 의미를 담고 있다.
print(torch.cat([x, y], dim=1))
#tensor([[1., 2., 5., 6.],
# [3., 4., 7., 8.]])
👉🏻인자를 dim=1로 주었다. (2 x 2)텐서가 (2 x 4)가 되었다.
✍🏻딥러닝에서 두 텐서를 연결해 입력한다는 것은 두 가지의 정보를 모두 사용한다는 의미를 가진다.
🔟스택킹(Stacking)
👉🏻연결을 하는 것 외 스택킹이이라는 방법도 있다. 스택킹은 많은 연산을 포함하고 있다.
x = torch.FloatTensor([1, 4])
y = torch.FloatTensor([2, 5])
z = torch.FloatTensor([3, 6])
print(torch.stack([x, y, z]))
#tensor([[1., 4.],
# [2., 5.],
# [3., 6.]])
👉🏻(3 x 2)텐서가 되었다.
print(torch.cat([x.unsqueeze(0), y.unsqueeze(0), z.unsqueeze(0)], dim=0))
#tensor([[1., 4.],
# [2., 5.],
# [3., 6.]])
👉🏻위의 스택킹 작업은 이렇게 많은 연산과 동일한 작업이다.
✍🏻x, y, z는 기존에 (2,) 크기를 가졌지만 .unsqueeze(0)를 통해 모두 (1, 2)크기의 2차원 텐서가 되었다. 여기에 cat을 통해 연결하며 (3 x 2)텐서가 되었다.
print(torch.stack([x, y, z], dim=1))
#tensor([[1., 2., 3.],
# [4., 5., 6.]])
👉🏻스택킹에도 dim 인자를 줄 수 있다. dim=1을 인자로 주면서 두 번째 차원이 증가하도록 쌓았다.
🔟1️⃣ones_like와 zeros_like
x = torch.FloatTensor([[0, 1, 2], [2, 1, 0]])
print(x)
#tensor([[0., 1., 2.],
# [2., 1., 0.]])
👉🏻(2 x 3)텐서를 만들었다.
print(torch.ones_like(x))
print(torch.zeros_like(x))
#tensor([[1., 1., 1.],
# [1., 1., 1.]])
#tensor([[0., 0., 0.],
# [0., 0., 0.]])
👉🏻ones_like를 하면 동일한 크기지만 1로만 값이 채워진 텐서를 생성한다. zeros_like를 하면동일한 크기지만 0으로만 값이 채워진 텐서를 생성한다.
🔟2️⃣덮어쓰기 연산(In-place Operation)
x = torch.FloatTensor([[1, 2], [3, 4]])
print(x.mul(2.))
print(x)
#tensor([[2., 4.],
# [6., 8.]])
#tensor([[1., 2.],
# [3., 4.]])
👉🏻(2 x 2)텐서를 만들고 곱하기 연산을 한 x와 기존 x를 출력했다. 곱하기 연산을 해도 기존 x가 변하지 않은 것을 알 수 있다.
print(x.mul_(2.))
print(x)
#tensor([[2., 4.],
# [6., 8.]])
#tensor([[2., 4.],
# [6., 8.]])
👉🏻_를 붙이면 x의 값이 덮어쓰기된다.
'그 땐 AI했지 > 그 땐 DeepLearning했지' 카테고리의 다른 글
[TAVE/study] ch03 선형 회귀 | 02 자동 미분 (0) | 2022.04.07 |
---|---|
[TAVE/study] ch03 선형 회귀 | 01 선형 회귀 (0) | 2022.04.07 |
[TAVE/study] ch02 파이토치 기초 | 04 파이썬 클래스 (0) | 2022.04.01 |
[TAVE/study] ch02 파이토치 기초 | 02 텐서 조작하기① (0) | 2022.03.31 |
[TAVE/study] ch02 파이토치 기초 | 01 파이토치 패키지의 기본 구성 (0) | 2022.03.31 |