[Pytorch]텐서 조작

Date:     Updated:

카테고리:

#

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)

Pytorch 카테고리 내 다른 글 보러가기

댓글 남기기