Pytorch란? Python 기반의 과학 연산 패키지
- numpy를 대체하면서 GPU를 이용한 연산이 필요한 경우
- 최대한의 유연성과 속도를 제공하는 딥러닝 연구 플랫폼이 필요한 경우
사용한다.
먼저 numpy 기초에 대해 알아보자.
numpy란, numerical python 의 줄임말로 고성능의 수치 계산을 하기 위해 만들어진 파이썬 패키지.
벡터 및 행렬 계산을 쉽고 빠르게 도와준다.
- ndarray 는 numpy 에서 가장 중요한 'N차원의 배열 객체' 를 의미한다. (numpy에서 사용하는 데이터구조)
- ndarray 는 기존 파이썬과는 다르게 오직 같은 종류의 데이터만을 배열에 담을 수 있음
- ndarray 는 np.array() 를 통해 생성할 수 있고, 행렬도 생성 가능함
한번 np.array()를 통해 ndarray 를 만들어보자.
1
2
3
4
5
|
import numpy as np
data = [[1,2,3,4], [5,6,7,8], [9,10,11,12]]
arr = np.array(data)
arr
|
cs |
output : array([[ 1, 2, 3, 4], [ 5, 6, 7, 8], [ 9, 10, 11, 12]])
- arange 함수를 통해 범위 내의 값을 순차적으로 가지는 배열도 생성 가능하다.
1
|
np.arange(5)
|
cs |
output : array([0, 1, 2, 3, 4])
1
2
3
4
|
# ndarray의 차수 및 배열모양, 배열 자료 타입 확인 : ndim, shape, dtype
print(arr.ndim)
print(arr.shape)
print(arr.dtype)
|
cs |
output :
2
(3,4)
int32
- ndarray 는 행렬 각각의 값에 대한 연산이 가능하다.
단순히 리스트 두개를 더하면 옆에 붙어 나오지만 ndarray 를 더하면 행렬 각각 덧셈이 가능하다.
1
2
3
4
5
6
|
data2 = [[1,2,3], [4,5,10], [6,7,8]]
data3 = [[1,2,3],[4,5,6],[7,8,9]]
arr2 = np.array(data2)
arr3 = np.array(data3)
print(data2+data3)
print(arr2+arr3)
|
cs |
output:
[[1, 2, 3], [4, 5, 10], [6, 7, 8], [1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[ 2 4 6] [ 8 10 16] [13 15 17]]
그렇다면, pytorch 에서 사용하는 tensor 란 뭘까?
- Tensor 는 numpy 의 ndarray 와 유사하며 GPU 를 사용한 연산 가속도 가능.
1
2
3
4
|
import torch
x = torch.empty(5,3) # 초기화되지 않은 5*3 행렬 선언
print(x)
|
cs |
output :
tensor([[8.4490e-39, 9.6428e-39, 1.1112e-38],
[9.5511e-39, 1.0102e-38, 1.0286e-38],
[1.0194e-38, 9.6429e-39, 9.2755e-39],
[9.1837e-39, 9.3674e-39, 1.0745e-38],
[1.0653e-38, 9.5510e-39, 1.0561e-38]])
1
2
|
x = torch.rand(5,3) # 무작위로 초기화된 행렬 생성
print(x)
|
cs |
output :
tensor([[0.2016, 0.1377, 0.6422],
[0.3460, 0.6562, 0.7865],
[0.5337, 0.3458, 0.6445],
[0.8760, 0.3464, 0.0485],
[0.2403, 0.9001, 0.4829]])
1
2
3
|
# dtype이 long이고 0으로 채워진 행렬 생성
x = torch.zeros(5, 3, dtype = torch.long)
print(x)
|
cs |
output :
tensor([[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]])
1
2
|
x = torch.tensor([5.5, 3]) # 데이터로부터 tensor 직접 생성
print(x)
|
cs |
output : tensor([5.5000, 3.0000])
1
2
|
print(x.size()) # 행렬의 크기 구하기
# torch.Size는 tuple 타입으로 모든 튜플 연산을 지원
|
cs |
output : torch.Size([5, 3])
1
2
|
y = torch.rand(5,3)
print(x+y) # tensor 끼리 덧셈은 이렇게 간단히도 가능
|
cs |
output :
tensor([[-0.1573, 0.6331, 0.4012],
[-1.8234, 1.8117, 0.5832],
[ 0.1654, -0.2825, 0.3407],
[ 1.3222, -1.6147, 1.9411],
[ 0.7481, 0.2140, -1.3441]])
1
|
print(torch.add(x,y)) # 다른 방법으로는 torch.add()사용
|
cs |
또는 위의 방법으로도 tensor 끼리 덧셈 가능.
1
2
3
4
|
# 덧셈 결과 tensor를 인자로 제공
result = torch.empty(5,3)
torch.add(x,y, out=result)
print(result)
|
cs |
output :
tensor([[-0.1573, 0.6331, 0.4012],
[-1.8234, 1.8117, 0.5832],
[ 0.1654, -0.2825, 0.3407],
[ 1.3222, -1.6147, 1.9411],
[ 0.7481, 0.2140, -1.3441]])
1
2
3
4
5
|
# 덧셈 : 바꿔치기(in-place) 방식
# y 에 x 더하기
# 바꿔치기 방식으로 텐서값을 변경하는 연산 뒤에는 _ 가 붙어서 y를 바꿔치기함
y.add_(x)
print(y)
|
cs |
output :
tensor([[-12.3553, -3.4144, 1.4519],
[-32.6566, 16.7263, 0.7115],
[ -4.2308, -16.0735, 4.4737],
[ 13.3836, -29.8986, 17.8578],
[ 11.6050, -0.2505, -35.6062]])
1
2
|
print(x)
print(x[:, 1]) # 두번째 열만 추출
|
cs |
output :
tensor([[-0.8132, -0.2698, 0.0700],
[-2.0555, 0.9943, 0.0086],
[-0.2931, -1.0527, 0.2755],
[ 0.8041, -1.8856, 1.0611],
[ 0.7238, -0.0310, -2.2841]])
tensor([-0.2698, 0.9943, -1.0527, -1.8856, -0.0310])
1
2
3
4
5
6
7
8
9
|
# 텐서의 크기(size)나 모양(shape)을 변경하고 싶다면
# torch.view 사용
x = torch.randn(4,4)
print(x)
y = x.view(16)
print(y)
z = x.view(8, -1) # -1은 다른 차원에서 유추
print(z) # 행이 8이니 뒤에는 알아서 유추해서 2열로
print(x.size(), y.size(), z.size())
|
cs |
output :
tensor([[-0.1264, -0.1502, -1.2004, -0.8349],
[-0.4374, -0.1657, -0.1755, -0.4863],
[ 0.7886, 0.3134, -0.0652, -1.2268],
[ 0.6866, 1.2647, -1.2523, 0.3365]])
tensor([-0.1264, -0.1502, -1.2004, -0.8349, -0.4374, -0.1657, -0.1755, -0.4863,
0.7886, 0.3134, -0.0652, -1.2268, 0.6866, 1.2647, -1.2523, 0.3365])
tensor([[-0.1264, -0.1502],
[-1.2004, -0.8349],
[-0.4374, -0.1657],
[-0.1755, -0.4863],
[ 0.7886, 0.3134],
[-0.0652, -1.2268],
[ 0.6866, 1.2647],
[-1.2523, 0.3365]])
torch.Size([4, 4]) torch.Size([16]) torch.Size([8, 2])
1
2
3
4
5
|
# 만약 tensor 에 하나의 값만 존재한다면
# .item() 을 사용해 숫자 값 얻을 수 있음
x = torch.randn(1)
print(x)
print(x.item())
|
cs |
output : tensor([-0.4263])
-0.4262644946575165
- torch tensor 를 numpy 배열인 ndarray 로 변환하기 --> .numpy()
1
2
|
a = torch.ones(5)
a
|
cs |
output : tensor([1., 1., 1., 1., 1.])
1
2
|
b = a.numpy() # tensor를 numpy 로 변환
b
|
cs |
output : array([1., 1., 1., 1., 1.], dtype=float32)
1
2
3
4
5
6
7
|
# torch tensor가 CPU 상에 있다면
# torch tensor와 numpy 배열은 메모리 공간을 공유하기 때문에
# 하나를 변경하면 다른 하나도 자동 변경
a.add_(1)
print(a) # torch 인 a 만 add 해도
print(b) # numpy 인 b 도 변경된 것을 확인
|
cs |
output :
tensor([2., 2., 2., 2., 2.])
[2. 2. 2. 2. 2.]
위와 반대로 numpy 배열을 torch tensor 로 변환하기
- 이것도 numpy 배열을 변경하면 torch tensor 값도 자동 변경됨
- torch.from_numpy()
1
2
3
4
5
6
|
import numpy as np
a = np.ones(5)
b = torch.from_numpy(a)
np.add(a, 1, out=a)
print(a) # numpy 값인 a만 변경해도
print(b) # b 도 자동변경된 것을 확인
|
cs |
output :
[2. 2. 2. 2. 2.]
tensor([2., 2., 2., 2., 2.], dtype=torch.float64)
'Pytorch' 카테고리의 다른 글
NVIDIA의 APEX - 학습 시간 단축, 성능 개선 (0) | 2022.05.26 |
---|
댓글