[Pytorch]텐서의 정의

Date:     Updated:

카테고리:

Pytorch Framework

1. Pytorch 개요

  • PyTorch는 기계 학습 프레임워크(framework) 중 하나다.
    • PyTorch의 텐서(tensor)는 NumPy 배열과 매우 유사하다.
  • PyTorch를 사용하면, GPU 연동을 통해 효율적으로 딥러닝 모델을 학습할 수 있다.

2. Tensor(텐서)

1) 텐서의 정의

  • 데이터 표현을 위한 기본 구조로 텐서(tensor)를 사용
  • 텐서는 데이터를 담기위한 컨테이너(container)로서 일반적으로 수치형 데이터를 저장
  • 넘파이(NumPy)의 ndarray와 유사
  • GPU를 사용한 연산 가속 가능

1

import torch

print(torch.__virsion__)

data = [
    [1,2],
    [3,4]
]

x = torch.tensor(data)  ## 텐서로 데이터 저장
print(x.is_cuda)

x = x.cuda()            ## GPU로 옮기기
print(x.is_cuda)

x = x.cpu()             ## CPU로 옮기기기
print(x.is_cuda)
1.13.1+cu116
False
True
False

# GPU 장치의 텐서
a = torch.tensor([
    [1,2],
    [3,4]
]).cuda()

# CPU 장치의 텐서
b = torch.tensor([
    [5,6],
    [7,8]
])

# print(torch.matmul(a,b)) # 오류 발생
print(torch.matmul(a.cpu(), b))
tensor([[19, 22],
        [43, 50]])

2) 텐서 초기화와 데이터 타입

텐서는 여러가지 방법으로 초기화할 수 있다.

  • Ex)
    • 데이터로부터 직접(directly) 생성하기
      • 데이터로부터 직접 텐서를 생성할 수 있습니다.
      • 데이터의 자료형(data type)은 자동으로 유추한다

데이터로부터 직접(directly) 생성

리스트를 이용


data = [[1,2],[3,4]]
x_data = torch.tensor(data)
print(x_data)
tensor([[1, 2],
        [3, 4]])

초기화되지 않은 센서

초기화되지 않은 값인데 왜 특정 값이 있나?
초기화가되지 않았으니깐, 메모리를 잡긴 잡더라도, 메모리에서 기존에 사용하던 값들을 그냥 그대로 가져온 것일 뿐임


# 실행마다 달라짐. 정말 아무 의미없는 값들로 채워짐. 쓰레기 값들
x = torch.empty(4,2)
print(x)
실행 1
tensor([[0., 0.],
        [0., 0.],
        [0., 0.],
        [0., 0.]])
실행 2
tensor([[-1.0367e+05,  4.5691e-41],
        [-1.0367e+05,  4.5691e-41],
        [ 4.4842e-44,  0.0000e+00],
        [ 8.9683e-44,  0.0000e+00]])

무작위(random)로 초기화 되는 텐서


x = torch.rand(4,2)
print(x)
tensor([[0.1168, 0.2962],
        [0.0421, 0.7551],
        [0.9146, 0.1689],
        [0.3916, 0.7220]]) 

dtype이 long, 0으로 채워진 텐서


x = torch.zeros(4,2, dtype = torch.long)  ## (4,2)의 원소가 0으로 채워진 행렬렬
print(x)
tensor([[0, 0],
        [0, 0],
        [0, 0],
        [0, 0]])

Numpy 배열로부터 생성하기


import numpy as np

data = [[1, 2], [3, 4]]
x_data = torch.tensor(data)

np_array = np.array(data)
x_np = torch.from_numpy(np_array)

print(x_np)
print('-----------------')
print(x_np.shape)
print('-----------------')
print(x_np.dtype)
tensor([[1, 2],
        [3, 4]])
----------------------
torch.Size([2, 2])
----------------------
torch.int64 

다른 텐서로부터 생성


x_ones = torch.ones_like(x_data) # x_data의 속성을 유지, x_data와 사이즈 동일, but 성분은 모두 1
print(f"Ones Tensor: \n {x_ones} \n")

x_rand = torch.rand_like(x_data, dtype=torch.float) # x_data의 속성을 덮어씀
print(f"Random Tensor: \n {x_rand} \n")
Ones Tensor: 
 tensor([[1, 1],
        [1, 1]]) 
Random Tensor: 
 tensor([[0.1945, 0.8921],
        [0.1632, 0.8592]]) 

기타


x = torch.tensor([3,2.3]) # 값을 직접 지정해줌
print(x)
tensor([3.0000, 2.3000])

x = x.new_ones(2,4,dtype = torch.double)
print(x)
tensor([[1., 1., 1., 1.],
       [1., 1., 1., 1.]], dtype=torch.float64)

x = torch.randn_like(x, dtype = torch.float)  ## like는 data의 shape을 그대로 가져와서 값을 채워넣겠다.
print(x)
## 위에서 x를 2,4 행렬로 잡았으니 like에 의해 2x4행렬로 나옴
tensor([[-0.2537,  1.3063,  1.4733, -0.9004],
      [-1.2198, -0.5154,  0.5316,  2.5383]])

shape = (2, 3,)
rand_tensor = torch.rand(shape)
ones_tensor = torch.ones(shape)
zeros_tensor = torch.zeros(shape)

print(f"Random Tensor: \n {rand_tensor} \n")
print(f"Ones Tensor: \n {ones_tensor} \n")
print(f"Zeros Tensor: \n {zeros_tensor}")
Random Tensor: 
 tensor([[0.8067, 0.4252, 0.0554],
        [0.0625, 0.1938, 0.8126]]) 
        
Ones Tensor: 
 tensor([[1., 1., 1.],
        [1., 1., 1.]])  

Zeros Tensor: 
 tensor([[0., 0., 0.],
        [0., 0., 0.]])  

x = torch.tensor([
    [5, 7],
    [1, 2]
])

# x와 같은 모양과 자료형을 가지지만, 값이 1인 텐서 생성
x_ones = torch.ones_like(x)
print(x_ones)

# x와 같은 모양을 가지되, 자료형은 float으로 덮어쓰고, 값은 랜덤으로 채우기
x_rand = torch.rand_like(x, dtype=torch.float32) # uniform distribution [0, 1)
print(x_rand)
tensor([[1, 1],
        [1, 1]])
tensor([[0.4862, 0.9064],
        [0.0512, 0.1819]])

3) 텐서의 속성

  • 텐서의 기본 속성으로는 다음과 같은 것들이 있다.
    • 모양(shape)
    • 자료형(data type)
    • 저장된 장치

텐서의 크기(shape)


x = torch.rand(4,2)
print(x)
print('-------------------------------')
print(x.shape)
tensor([[0.4579, 0.8034],
        [0.8778, 0.9338],
        [0.5151, 0.0725],
        [0.6880, 0.8795]])
-------------------------------
torch.Size([4, 2])

텐서의 자료형


x = torch.rand(4,2)
print("Data Type: ", x.dtype)
Data Type:  torch.float32

저장된 장치


x = torch. rand(4,2)
print("x.Device: ", x.device)
print("-----------------------")
y = torch. rand(4,2).cuda()
print("y.Device: ", y.device)
x.Device:  cpu
-----------------------
y.Device:  cuda:0

텐서 만들기 정리

  • torch.empty(x, y) = x * y 사이즈의 요소들의 값이 초기화 되지 않은 행렬 반환
  • torch.rand(x, y): x * y 사이즈의 요소들이 0 ~ 1 사이의 랜덤한 값으로 초기화 된 행렬 반환.
  • torch.randn(x, y): x * y 사이즈의 요소들이 정규분포 그래프 상의 랜덤한 값으로 초기화 된 행렬 반환.
  • torch.zeros(x, y, dtype=type): x * y 사이즈의 요소들이 0으로 초기화 된 행렬 반환, 요소들은 type에 맞게 초기화 된다.
  • torch.ones(x, y, dtype=type): x * y 사이즈의 요소들이 1으로 초기화 된 행렬 반환, 요소들은 type에 맞게 초기화 된다.
  • torch.tensor(iterable): iterable한 객체를 Tensor 객체로 변환한다.
  • torch.zeros_like(tensor, dtype=type): 파라미터로 들어 간 Tensor 객체의 사이즈과 똑같은 행렬을 반환하며, 요소들은 0으로 초기화 되어 있다.
  • torch.ones_like(tensor, dtype=type): 파라미터로 들어 간 Tensor 객체의 사이즈과 똑같은 행렬을 반환하며, 요소들은 1으로 초기화 되어 있다.
  • torch.randn_like(tensor, dtype=type): 파라미터로 들어 간 Tensor 객체의 사이즈과 똑같은 행렬을 반환하며, 요소들은 정규분포 그래프 상의 랜덤한 값으로 초기화 되어 있다.

empty_tensor = torch.empty(3, 3)							        # 3 * 3의 빈 행렬 생성
rand_tensor = torch.rand(3, 3)								        # 3 * 3의 요소들이 0 ~ 1의 랜덤 값으로 초기화된 행렬 생성
randn_tensor = torch.randn(3, 3, dtype=torch.double)	# 3 * 3의 요소들이 정규분포 그래프 값으로 초기화된 행렬 생성
zero_tensor = torch.zeros(3, 3, dtype=torch.long)			# 3 * 3의 요소들이 0으로 초기화된 행렬 생성
one_tensor = torch.ones(3, 3, dtype=torch.double)			# 3 * 3의 요소들이 1으로 초기화된 행렬 생성
iterable_tensor = torch.tensor([1, 2, 3])							# list 객체를 Tensor 객체로 변환
zeros_like_tensor = torch.zeros_like(iterable_tensor, dtype=torch.double)	# iterable_tensor와 사이즈가 같은, 요소들이 0으로 초기화된 행렬 생성
ones_like_tensor = torch.ones_like(iterable_tensor, dtype=torch.double)		# iterable_tensor와 사이즈가 같은, 요소들이 1으로 초기화된 행렬 생성
randn_like_tensor = torch.randn_like(iterable_tensor, dtype=torch.double)	# iterable_tensor와 사이즈가 같은, 요소들이 정규분포 그래프 값으로 초기화된 행렬 생성

print('1: ' , empty_tensor)
print('2: ', rand_tensor)
print('3: ', randn_tensor)
print('4: ', zero_tensor)
print('5: ', one_tensor)
print('6: ', iterable_tensor)
print('7: ', zeros_like_tensor)
print('8: ', ones_like_tensor)
print('9: ', randn_like_tensor)
1:  tensor([[2.1707e-18, 7.0952e+22, 1.7748e+28],
        [1.8176e+31, 7.2708e+31, 5.0778e+31],
        [3.2608e-12, 1.7728e+28, 7.0367e+22]])
2:  tensor([[0.2648, 0.6304, 0.1789],
        [0.5173, 0.1238, 0.4457],
        [0.8282, 0.7767, 0.2907]])
3:  tensor([[ 0.8707, -0.7935,  1.2842],
        [ 0.6186, -0.5729,  0.0480],
        [-1.8895, -1.5841,  0.6177]], dtype=torch.float64)
4:  tensor([[0, 0, 0],
        [0, 0, 0],
        [0, 0, 0]])
5:  tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]], dtype=torch.float64)
6:  tensor([1, 2, 3])
7:  tensor([0., 0., 0.], dtype=torch.float64)
8:  tensor([1., 1., 1.], dtype=torch.float64)
9:  tensor([0.0225, 0.7263, 0.2575], dtype=torch.float64)  

4) 텐서의 연산

덧셈

# 덧셈 1
a = torch.rand(4,2)
b = torch.rand(4,2)
print(a+b)
tensor([[1.0959, 0.9410],
        [0.1206, 0.9975],
        [1.1056, 1.2427],
        [0.8267, 1.1264]]) 

# 덧셈 2
print(torch.add(a,b))
tensor([[1.0959, 0.9410],
        [0.1206, 0.9975],
        [1.1056, 1.2427],
        [0.8267, 1.1264]])  

# 덧셈 3
# 결과 텐서를 인자로 제공
result = torch.empty(4,2)
torch.add(a,b, out = result)
print(result)
tensor([[1.0959, 0.9410],
        [0.1206, 0.9975],
        [1.1056, 1.2427],
        [0.8267, 1.1264]])  

# 덧셈 4
# in-place 방식
#  - in-place방식으로 텐서의 값을 변경하는 연산 뒤에는 _''가 붙음
#  - `x.copy_(y), x.t_()`
print(a)
print(b)
print('-----------------------------------')
b.add_(a)
print(b)
tensor([[0.5433, 0.2835],
        [0.0649, 0.0631],
        [0.5512, 0.6149],
        [0.3727, 0.4714]])
tensor([[0.5527, 0.6575],
        [0.0556, 0.9343],
        [0.5544, 0.6278],
        [0.4540, 0.6549]])
-----------------------------------
tensor([[1.0959, 0.9410],
        [0.1206, 0.9975],
        [1.1056, 1.2427],
        [0.8267, 1.1264]])

그 외의 연산

  • torch.sub : 뺄셈
  • torch.mul : 곱셈 ## Element-Wise
  • torch.div : 나눗셈 ## Element-Wise
  • torch.mm : 내적(dot product), 행렬곱
  • torch.matmul: 행렬곱

# 같은 크기를 가진 두 갸의 텐서에 대하여 사칙연산 가능
# 기본적으로 요소별(element-wise) 연산
a = torch.tensor([
    [1,2],
    [3,4]
                  ])
b = torch.tensor([
    [5,6],
    [7,8]
])
print(a+b)
print(a-b)
print(a*b)
print(a/b)
tensor([[ 6,  8],
        [10, 12]])
tensor([[-4, -4],
        [-4, -4]])
tensor([[ 5, 12],
        [21, 32]])
tensor([[0.2000, 0.3333],
        [0.4286, 0.5000]])

행렬 곱(matrix multiplicatio) 수행


a = torch.tensor([
    [1,2],
    [3,4],
])

b = torch.tensor([
    [5,6],
    [7,8]
])
print(a.matmul(b))
print(torch.matmul(a,b))
tensor([[19, 22],
        [43, 50]])
tensor([[19, 22],
        [43, 50]]) 

텐서의 평균 함수

텐서의 요소들의 평균을 계산


a = torch.Tensor([            # torch.tensor와 torch.Tensor는 다르다.
    [1,2,3,4],                # torch.tensor: (Python function, in torch.tensor) 즉 이거는 그냥 함수
    [5,6,7,8]                 # torch.Tensor: (Python class, in torch.tensor) 즉 이거는 클래스임
])

print(a)
print(a.mean())            # 전체 원소에 대한 평균 
print(a.mean(dim = 0))     # 각 열에 대하여 평균
print(a.mean(dim = 1))     # 각 행에 대하여 평균
tensor([[1., 2., 3., 4.],
        [5., 6., 7., 8.]])
tensor(4.5000)
tensor([3., 4., 5., 6.])
tensor([2.5000, 6.5000])  

텐서의 합계 함수

요소들의 합을 계산


a = torch.Tensor([
    [1,2,3,4,],
    [5,6,7,8]
])
print(a)
print(a.sum())          # 전체 원소에 대한 합계
print(a.sum(dim = 0))   # 각 열에 대하여 합계 계산
print(a.sum(dim = 1))   # 각 행에 대하여 합계 계산
tensor([[1., 2., 3., 4.],
        [5., 6., 7., 8.]])
tensor(36.)
tensor([ 6.,  8., 10., 12.])
tensor([10., 26.])

텐서의 최대 함수

max() 함수는 원소의 최댓값을 반환한다.
argmax() 함수는 가장 큰 원소(최댓값)의 인덱스를 반환한다.


a = torch.Tensor([
    [1,2,3,4],
    [5,6,7,8]
])

print(a)
print(a.max())                 # 전체 원소에 대한 최댓값
print(a.max(dim = 0))          # 각 열에 대하여 최댓값 계산
print(a.max(dim = 1))          # 각 행에 대하여 최댓값 계산
print()

print(a.argmax())            # 전체 원소에 대한 최댓값의 인덱스
print(a.argmax(dim = 0))     # 각 열에 대하여 최댓값의 인덱스
print(a.argmax(dim = 1))     # 각 행에 대하여 최댓값의 인덱스
tensor([[1., 2., 3., 4.],
        [5., 6., 7., 8.]])
tensor(8.)
torch.return_types.max(
values=tensor([5., 6., 7., 8.]),
indices=tensor([1, 1, 1, 1]))
torch.return_types.max(
values=tensor([4., 8.]),
indices=tensor([3, 3]))
tensor(7)
tensor([1, 1, 1, 1])
tensor([3, 3])

Reference

Youtube-파이토치 기초(이수안 컴퓨터 연구소)
패스트 캠퍼스

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

댓글 남기기