PyTorch는 Deep Learning Framework 중 하나로 주로 research 분야에서 많이 사용되는 것으로 알려져있다. PyTorch에서는 tensor를 사용하는데 이 tensor는 PyTorch의 기본적인 data structure라고 생각하면 된다.
tensor는 numpy와 비슷하게 n 차원 배열을 다룬다. 하지만 Deep Learning의 특성 상 계산량이 많아 보통 GPU에서 계산해야 하는데, numpy와 다르게 PyTorch의 tensor는 GPU에서 계산할 수 있기 때문에 Deep Learning Model을 사용할 때, 이 tensor를 사용한다.
여기에서는 PyTorch의 tensor를 GPU에 올려서 계산하고 Deep Learning Model을 만들기 위해 사용되는 기본적인 GPU 연산들(back propagation 등)을 알아본다.
1. PyTorch tensor를 GPU에 올리기
device: 해당 tensor가 CPU, GPU 중 어디에 있는지 확인할 때 사용한다.
ex1> CPU에 있는 경우
print(a.device)
>> cpu
print(a)
>> tensor([1, 2, 3, 4])
ex2> GPU에 있는 경우
print(a.device)
>> cuda:0
print(a)
>> tensor([1, 2, 3, 4], device='cuda:0')
-> GPU에 있는 경우 그냥 tensor를 출력해도 cuda에 올라가 있는 것이 표시
cuda.is_available(): GPU(cuda)를 사용할 수 있는지 확인할 때 사용한다.
ex>
print(torch.cuda.is_available())
>> True
to('cuda'): tensor를 GPU에 올릴 때 사용한다.
to('cpu'): tensor를 다시 CPU에서 계산할 때 사용한다.
ex>
a = torch.tensor([1, 2, 3, 4])
print(a.device)
>> cpu
a = a.to('cuda')
print(a.device)
>> cuda:0
a = a.to('cpu') print(a.device)
>> cpu
-> 위 내용들을 포함해서 보통 다음과 같은 문법으로 tensor를 GPU에 올리는 작업을 한다.
ex1>
a = torch.tensor([1, 2, 3, 4])
if torch.cuda.is_available():
device = 'cuda'
else:
device = 'cpu'
a = a.to(device)
ex2>
a = torch.tensor([1, 2, 3, 4])
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
a = a.to(device)
2. Autograd
Autograd는 tensor에 대한 미분 계산을 도와주는 pytorch 패키지다. AI model을 학습할 때 parameter에 대한 gradient가 필요한데, 그 gradient를 계산할 때 주로 사용되므로 AI 학습에 핵심적인 패키지 중 하나라고 할 수 있다.
requires_grad: True로 설정 시 모든 연산들을 기억(track all operation) <참고: tensor 내 element는 int가 아닌 float 자료형이어야>
retain_grad(): 해당 변수에 대한 gradient 연산을 기억 -> 이것을 하지 않으면 중간 변수에 대한 gradient는 저장 안됨
backward(): 기억한 연산들에 대해서 gradient 계산 -> grad attribute(속성)에 gradient 정보 축적
detach(): 계산 정보를 더 이상 기억하지 않음(stop tracking history)
ex>
다음과 같은 연산이 있다고 하자.
이 연산에 대해서 z에 대한 미분 연산을 하면 다음과 같다.
이 내용을 Python code 결과로 확인하면 다음과 같다.
--- Python Code ---
w = torch.tensor([[1., 2.], [3., 2.]], requires_grad=True)
print(w)
>> tensor([[1., 2.],
[3., 2.]], requires_grad=True)
-> tensor에 requires_grad가 True인 것이 표시되는 것 확인
x = w**3
print(x)
>> tensor([[ 1., 8.],
[27., 8.]], grad_fn=<PowBackward0>)
y = x + 3
print(y)
>> tensor([[ 4., 11.],
[30., 11.]], grad_fn=<AddBackward0>)
z = y.mean()
print(z)
>> tensor(14., grad_fn=<MeanBackward0>)
x.retain_grad() y.retain_grad()
z.backward() print(y.grad)
>> tensor([[0.2500, 0.2500],
[0.2500, 0.2500]])
print(x.grad)
>> tensor([[0.2500, 0.2500],
[0.2500, 0.2500]])
print(w.grad)
>> tensor([[0.7500, 3.0000],
[6.7500, 3.0000]])
-> x.retain_grad(), y.retain_grad()를 하지 않으면 x.grad, y.grad를 하는 경우 다음과 같은 에러 메시지가 발생한다.
RuntimeError: Trying to backward through the graph a second time, but the buffers have already been freed. Specify retain_graph=True when calling backward the first time.
torch.no_grad(): torch.no_grad()를 사용하면 연산을 하는 동안 그 history를 기억하지 않는다. 그러므로 memory를 덜 사용한다. 때문에 gradient 계산이 필요없는 경우 즉, training이 아닌 inference를 하는 경우 사용한다. 더 적은 memory를 사용하기 때문에 더 빠른 계산이 가능해진다.
ex>
with torch.no_grad():
w = torch.tensor([[1., 2.], [3., 2.]], requires_grad=True)
x = w**3
y = x + 3
z = y.mean()
print(z)
>> tensor(14.)
-> 이전 예시와 다르게 grad_fn에 대한 정보가 없는 것 확인
z.backward()
>> RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
'Python' 카테고리의 다른 글
있어보이는 Python: try/except, enumerate (0) | 2020.11.09 |
---|---|
Window Python(Jupyter Notebook)에서 tar.gz 파일로 압축 및 해제하기 (0) | 2020.11.09 |
Pytorch의 tensor 다루기 (0) | 2020.11.07 |
numpy 다루기 3 (0) | 2020.10.30 |
numpy 다루기 2 (0) | 2020.10.23 |