[Pytorch]텐서 조작
카테고리: Pytorch
#
1. 텐서의 조작
1) 인덱싱
넘파이처럼 사용 가능하다.
print(x)
tensor([[0.7306, 0.9375],
[0.8360, 0.9402],
[0.7399, 0.6204],
[0.3343, 0.6229]])
print(x[:,0]) ## 모든 행, 열은 1열만 (0번째 열)
print(x[:,1]) ## 모든 행, 열을 2열만 (1번째 열)
print(x[0,:]) ## 1행만, 모든 열 (0번재 행)
print(x[1,:]) ## 2행만, 모든 열 (1번째 행)
tensor([0.7306, 0.8360, 0.7399, 0.3343])
tensor([0.9375, 0.9402, 0.6204, 0.6229])
tensor([0.7306, 0.9375])
tensor([0.8360, 0.9402])
2) Concatenation
두 텐서를 이어 붙여 연결하여 새로운 텐서를 생성
tensor = torch.tensor([
[1,2,3,4],
[5,6,7,8],
[9,10,11,12]
])
# dim: 텐서를 이어 붙이기 위한 축!!
# 0번 축(행)을 기준으로 이어 붙이기
result1 = torch.cat([tensor, tensor, tensor], dim = 0)
print(result1)
print(result1.shape)
print()
# 1번 축(열)을 기준으로 이어 붙이기
result2 = torch.cat([tensor, tensor, tensor], dim = 1)
print(result2)
print(result2.shape)
tensor([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
torch.Size([9, 4])
tensor([[ 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4],
[ 5, 6, 7, 8, 5, 6, 7, 8, 5, 6, 7, 8],
[ 9, 10, 11, 12, 9, 10, 11, 12, 9, 10, 11, 12]])
torch.Size([3, 12])
x = torch.randn(1,1,3,3)
y = torch.randn(1,1,3,3)
z0 = torch.cat((x,y),dim = 0)
z1 = torch.cat((x,y),dim = 1)
z2 = torch.cat((x,y),dim = 2)
z3 = torch.cat((x,y),dim = 3)
print(x)
print("--------------------------------------------------------------------------")
print(y)
print("--------------------------------------------------------------------------")
print()
print()
print(z0)
print(z0.size())
print("--------------------------------------------------------------------------")
print(z1)
print(z1.size())
print("--------------------------------------------------------------------------")
print(z2)
print(z2.size())
print("--------------------------------------------------------------------------")
print(z3)
print(z3.size())
print("--------------------------------------------------------------------------")
tensor([[[[ 1.2783, 0.5060, -0.2689],
[ 0.1078, -0.0052, -1.7982],
[-0.3712, 0.3075, 2.0494]]]])
--------------------------------------------------------------------------
tensor([[[[-0.4325, -0.8958, 0.4735],
[ 0.4846, -0.5966, -0.4007],
[-0.0394, -1.7800, 0.4572]]]])
--------------------------------------------------------------------------
tensor([[[[ 1.2783, 0.5060, -0.2689],
[ 0.1078, -0.0052, -1.7982],
[-0.3712, 0.3075, 2.0494]]],
[[[-0.4325, -0.8958, 0.4735],
[ 0.4846, -0.5966, -0.4007],
[-0.0394, -1.7800, 0.4572]]]])
torch.Size([2, 1, 3, 3])
--------------------------------------------------------------------------
tensor([[[[ 1.2783, 0.5060, -0.2689],
[ 0.1078, -0.0052, -1.7982],
[-0.3712, 0.3075, 2.0494]],
[[-0.4325, -0.8958, 0.4735],
[ 0.4846, -0.5966, -0.4007],
[-0.0394, -1.7800, 0.4572]]]])
torch.Size([1, 2, 3, 3])
--------------------------------------------------------------------------
tensor([[[[ 1.2783, 0.5060, -0.2689],
[ 0.1078, -0.0052, -1.7982],
[-0.3712, 0.3075, 2.0494],
[-0.4325, -0.8958, 0.4735],
[ 0.4846, -0.5966, -0.4007],
[-0.0394, -1.7800, 0.4572]]]])
torch.Size([1, 1, 6, 3])
--------------------------------------------------------------------------
tensor([[[[ 1.2783, 0.5060, -0.2689, -0.4325, -0.8958, 0.4735],
[ 0.1078, -0.0052, -1.7982, 0.4846, -0.5966, -0.4007],
[-0.3712, 0.3075, 2.0494, -0.0394, -1.7800, 0.4572]]]])
torch.Size([1, 1, 3, 6])
--------------------------------------------------------------------------
3) 텐서의 형 변환(Type Casting)
텐서의 자료형(정수, 실수 등)을 변환할 수 있다.
a = torch.tensor([2], dtype = torch.int)
b = torch.tensor([5,0])
print(a.dtype)
print(b.dtype)
# 텐서 a는 자동으로 float32로 형변환 처리
print(a*b)
print(a+b.type(torch.int32))
torch.int32
torch.int64
tensor([10, 0])
tensor([7, 2], dtype=torch.int32)
4) 텐서의 모양 변경 - view()
- 텐서의 크기(size)나 모양(shape)을 변경
-
numpy에서 reshape와 같음
tensor.size()
: tensor 객체의 사이즈를 리턴tensor.view(size)
: 파라미터로 들어간 사이즈로 tensor 객체의 사이즈를 변환- 파라미터로 -1이 들어갈 시: 행렬의 차원 수를 찾춰 resizing
- 파라미터로 (-1,n)이 들어갈 시: 하위 차원에서 n개씩 끊어 넣는 방식으로 resizing
# view()는 텐서의 모양을 변경할 때 사용한다.
# 이때, 텐서(tensor)의 순서는 변경되지 않는다.
a = torch.tensor([1,2,3,4,5,6,7,8])
b = a.view(4, 2)
print('1: ', b)
# a의 값을 변경하면 b도 변경
a[0] = 7
print('2: ', b)
# a의 값을 복사(copy)한 뒤에 변경
c = a.clone().view(4,2)
a[0] = 9
print('3: ', c)
print()
x = torch.randn(4,5)
y = x.view(20)
z = x.view(5,-1)
print("----------------------------------------------------------------------------------")
print(x.size())
print(x)
print("----------------------------------------------------------------------------------")
print(y.size())
print(y)
print("----------------------------------------------------------------------------------")
print(z.size())
print(z)
print("----------------------------------------------------------------------------------")
1: tensor([[1, 2],
[3, 4],
[5, 6],
[7, 8]])
2: tensor([[7, 2],
[3, 4],
[5, 6],
[7, 8]])
3: tensor([[7, 2],
[3, 4],
[5, 6],
[7, 8]])
----------------------------------------------------------------------------------
torch.Size([4, 5])
tensor([[ 0.0551, -2.5972, 0.0485, -1.5488, -0.4064],
[-0.8209, 0.4011, 0.6402, -0.3660, -0.6319],
[ 0.8988, -0.0870, 1.2674, 1.3570, -0.4930],
[ 0.1183, 1.2218, 0.1275, 0.2907, 0.8701]])
----------------------------------------------------------------------------------
torch.Size([20])
tensor([ 0.0551, -2.5972, 0.0485, -1.5488, -0.4064, -0.8209, 0.4011, 0.6402,
-0.3660, -0.6319, 0.8988, -0.0870, 1.2674, 1.3570, -0.4930, 0.1183,
1.2218, 0.1275, 0.2907, 0.8701])
----------------------------------------------------------------------------------
torch.Size([5, 4])
tensor([[ 0.0551, -2.5972, 0.0485, -1.5488],
[-0.4064, -0.8209, 0.4011, 0.6402],
[-0.3660, -0.6319, 0.8988, -0.0870],
[ 1.2674, 1.3570, -0.4930, 0.1183],
[ 1.2218, 0.1275, 0.2907, 0.8701]])
----------------------------------------------------------------------------------
a = torch.tensor([ # 4x4 행렬
[1,2,3,4],
[5,6,7,8],
[9,10,11,12],
[13,14,15,16]
])
print("1. a")
print(a)
print(a.size())
print()
b = a.view(16) ## 사이즈가 16인 array가 된다. 즉 flatten한 것과 같아짐
print("2. b")
print(b)
print(b.size())
print()
c = a.view(-1,8) ## 4 x 4 ~> 2 x 8
print("3. c")
print(c)
print(c.size())
print()
d = a.view(-1) ## 축이 2개 였으므로, 축을 하나로 줄이면 flatten한것과 같음
print("4. d")
print(d)
print(d.size())
print()
e = a.view(8,2)
print("5. e")
print(e)
print(e.size())
1. a
tensor([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, 15, 16]])
torch.Size([4, 4])
2. b
tensor([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])
torch.Size([16])
3. c
tensor([[ 1, 2, 3, 4, 5, 6, 7, 8],
[ 9, 10, 11, 12, 13, 14, 15, 16]])
torch.Size([2, 8])
4. d
tensor([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16])
torch.Size([16])
5. e
tensor([[ 1, 2],
[ 3, 4],
[ 5, 6],
[ 7, 8],
[ 9, 10],
[11, 12],
[13, 14],
[15, 16]])
torch.Size([8, 2])
5) 텐서의 차원 교환
하나의 텐서에서 특정한 차원끼리 순서를 교체할 수 있다.
a = torch.rand((64,32,3))
print(a.shape)
b = a.permute(2,1,0) # 차원 자체를 교환
# (2번째 축, 1번째 축, 0번째 축)의 형태가 되도록 한다.
print(b.shape)
torch.Size([64, 32, 3])
torch.Size([3, 32, 64])
6) 텐서의 차원 줄이기 or 차원 늘리기
- unsqueeze() 함수는 크기가 1 인 차원을 추가한다.
- 배치(batch) 차원을 추가하기 위한 목적으로 흔히 사용된다.
- squeeze() 함수는 크기가 1인 차원을 제거한다.
a = torch.Tensor([
[1,2,3,4],
[5,6,7,8]
])
print(a.shape)
# 첫 번째 축에 차원 추가
a = a.unsqueeze(0)
print(a)
print(a.shape)
print()
# 네 번째 축에 차원 추가
a = a.unsqueeze(3)
print(a)
print(a.shape)
torch.Size([2, 4])
tensor([[[1., 2., 3., 4.],
[5., 6., 7., 8.]]])
torch.Size([1, 2, 4])
tensor([[[[1.],
[2.],
[3.],
[4.]],
[[5.],
[6.],
[7.],
[8.]]]])
torch.Size([1, 2, 4, 1])
# 크기가 1인 차원 제거
a = a.squeeze()
print(a)
print(a.shape)
tensor([[1., 2., 3., 4.],
[5., 6., 7., 8.]])
torch.Size([2, 4])
7) 텐서의 값 - item()
# 텐서에 값이 단 하나라도 존재하면 숫자값을 얻을 수 있음
x = torch.randn(1)
print(x)
print(x.item())
print(x.dtype)
tensor([0.4202])
0.4202098250389099
torch.float32
# x가 scalar가 아니라 vector나 matrix가 되면 오류남
x = torch.randn(2)
print(x)
print(x.item)
print(x.dtype)
tensor([-0.5604, 0.5759])
<built-in method item of Tensor object at 0x7f6f436ab950>
torch.float32
8) 텐서간 결합 - stack()
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.]])
9.1) 텐서간 분할 - chunk()
- 텐서를 여러 개로 나눌 때 사용
- 몇 개의 텐서로 나눌 것이냐
x = torch.rand(3,6)
t1, t2, t3 = torch.chunk(x, 3, dim = 1) ## x를 3개로 나눈다.
print(x)
print("------------------------------------------------------------------")
print(t1)
print("------------------------------------------------------------------")
print(t2)
print("------------------------------------------------------------------")
print(t3)
tensor([[0.6757, 0.1670, 0.8002, 0.3195, 0.2859, 0.1874],
[0.5722, 0.7830, 0.6999, 0.7082, 0.5811, 0.4180],
[0.4047, 0.6115, 0.0471, 0.0122, 0.2065, 0.8178]])
------------------------------------------------------------------
tensor([[0.6757, 0.1670],
[0.5722, 0.7830],
[0.4047, 0.6115]])
------------------------------------------------------------------
tensor([[0.8002, 0.3195],
[0.6999, 0.7082],
[0.0471, 0.0122]])
------------------------------------------------------------------
tensor([[0.2859, 0.1874],
[0.5811, 0.4180],
[0.2065, 0.8178]])
x = torch.FloatTensor(17,4)
chunks = x.chunk(4, dim = 0) ## 0번째 축을 기준으로 4덩이를 나누고 싶다.
## chunk(4, dim = 0) ==> chunk(4(n), dim = 0)
## 각 data set마다 최대 5개를 갖고 있음(0번째 축 이 17)
## 마지막 데이터가 부족한 경우 그냥 내보냄
for c in chunks:
print(c.size())
torch.Size([5, 4])
torch.Size([5, 4])
torch.Size([5, 4])
torch.Size([2, 4])
9.2) 텐서의 분할
chunk
와 동일기능이지만 다름- 하나의 텐서당 크기가 얼마?
x = torch.FloatTensor(17,4)
splits = x.split(4, dim = 0) ## 0번째 축을 기준으로 4개의 데이터로 나누어짐
## split(4,dim = 0) ==> split(4(n), dim = 0)
## 17이 5개의 데이터로 나누어짐, 텐서당 크기가 4이므로 17/4 = 4.25
## 각 data set마다 최대 4n개를 갖고 있음(이 경우 n = 1이됨)
## 마지막에 부족한 데이터는 그냥 내보냄
for s in splits:
print(s.size())
print("------------------------------------------------")
y = torch.FloatTensor(17,4)
splits = y.split(4, dim = 1) ## 1번째 축을 기준으로 1개의 데이터로 나누어짐
## 하나의 텐서당 크기가 4이므로 4/4 = 1
for s in splits:
print(s.size())
torch.Size([4, 4])
torch.Size([4, 4])
torch.Size([4, 4])
torch.Size([4, 4])
torch.Size([1, 4])
------------------------------------------------
torch.Size([17, 4])
10.1) Torch <-> Numpy
- Torch Tensor(텐서)를 Numpy array(배열)로 변환 가능
numpy()
from_numpy()
- (참고)
- Tensor가 CPU상에 있다면 Numpy 배열은 메모리 공간을 공유하므로 하나가 변하면, 다른 하나도 변함
import torch
a = torch.ones(7)
print(a)
b = a.numpy()
print(b)
a.add_(1)
print(a)
print(b)
## 메모리를 공유하기 때문에, a에 1을 더해도 b도 더해짐
import numpy as np
a = np.ones(7)
b = torch.from_numpy(a)
np.add(a,1,out = a)
print(a)
print(b)
tensor([1., 1., 1., 1., 1., 1., 1.])
[1. 1. 1. 1. 1. 1. 1.]
tensor([2., 2., 2., 2., 2., 2., 2.])
[2. 2. 2. 2. 2. 2. 2.]
[2. 2. 2. 2. 2. 2. 2.]
tensor([2., 2., 2., 2., 2., 2., 2.], dtype=torch.float64)
10.2) CUDA Tensors
.to
메소드를 사용하여 텐서를 어떠한 장치로도 옮길 수 있음- 예) cpu, gpu
import torch
x = torch.randn(1)
print(x)
print(x.item())
print(x.dtype)
device = torch.device('cuda' if torch.cuda.is_available() else"cpu")
y = torch.ones_like(x, device = device)
x = x.to(device)
z = x + y
print(device)
print(z)
print(z.to("cpu", torch.double)) ## z값 자체를 cpu 환경으로 다시 바꿈. device(cuda:0)가 사라지고 데이터 타입만 나옴
tensor([-0.7686])
-0.7685998678207397
torch.float32
cuda
tensor([0.2314], device='cuda:0')
tensor([0.2314], dtype=torch.float64)
댓글 남기기