이론 파트는 다 수강한 상태!
딥러닝을 공부할 개발환경에서 아래의 커멘드를 입력
conda install -c pytorch pytorch
Python 환경에서 아래의 커멘드를 입력 후 True를 확인하기
import torch
device = torch.device('mps:0' if torch.backends.mps.is_available() else 'cpu')
print (f"PyTorch version:{torch.__version__}") # 1.12.1 이상
print(f"MPS 장치를 지원하도록 build 되었는지: {torch.backends.mps.is_built()}") # True 여야 합니다.
print(f"MPS 장치가 사용 가능한지: {torch.backends.mps.is_available()}") # True 여야 합니다.
!python -c 'import platform;print(platform.platform())'
필자의 경우 아래와 같이 출력
PyTorch version:1.12.1
MPS 장치를 지원하도록 build 되었는지: True
MPS 장치가 사용 가능한지: True
macOS-13.0-arm64-arm-64bit
설치가 잘 됐는지는 이후 학습과정을 통해서 확인할 수 있어서 패스~
ls1 = [1,2]
ls2 = [3,4]
tor1 = torch.tensor([1,2])
tor2 = torch.tensor([3,4])
print(ls1 + ls2)
print(tor1 + tor2)
print(tor1 * tor2)
[1, 2, 3, 4]
tensor([4, 6])
tensor([3, 8])
리스트 형태의 값의 연산과 텐서 형태의 값의 연산은 다른 형태로 진행된다
print(sum(tor1 + tor2))
print(tor1.dot(tor2))
print(torch.dot(tor1, tor2))
print(torch.matmul(tor1, tor2))
print(torch.matmul(tor1.view(1,-1), tor2)[0])
matmul
은 shape을 맞추고 행렬 곱을 계산하기 위한 함수
view
는 matmul
을 하기 위해 맞춰주는 함수. 최근에는 업글되서 위에 처럼 진행한다고 함.
행렬 곱은 스칼라 곱과 다르다는 점만 안다면 이해가 쉽다
data = torch.randn(4,3)
print(data)
print(torch.where(data>0, torch.ones(data.shape), torch.zeros(data.shape)))
data > 0이라는 조건을 넣어줬을 때 텐서의 각 원소마다 그 값이 참이면 텐서의 원소 위치에 torch.ones를 반환하고 그렇지 않으면 data의 그 위치에 torch.zeros를 보여주는 함수
tensor([[-1.2605, 1.2107, -0.7283],
[-1.6908, 0.4007, -2.2820],
[-1.7402, 0.5828, -0.9733],
[-0.4130, -0.4026, 0.2520]])
tensor([[0., 1., 0.],
[0., 1., 0.],
[0., 1., 0.],
[0., 0., 1.]])
numpy
를 배우다보면 딥러닝에서 자주 쓰인다고 했는데 직접 써보니 torch
와 호환성이 좋아보임
a = torch.ones(5)
print(a)
b = a.numpy()
print(b)
a = torch.from_numpy(b)
print(a)
텐서를 넘파이로, 넘파이를 텐서로 바꾸는 함수가 존재
M1 GPU를 쓸 수 있도록 지원해준 mps를 어떻게 쓸까?
x = torch.tensor([1,1]).cuda()
print(x)
위 방식대로 M1 로컬환경에서 실행하면 당연히 오류가 뜬다. 우리는 cuda가 동작하지 않아서
x = torch.tensor([1,1]).to("mps")
print(x)
x = x.cpu()
print(x)
그래서 cuda()
대신에 to("mps")
를 사용한다!
cpu()
함수는 GPU 연산이 필요없는 계산에서 활용
여기서 주의해야 할 점은 GPU로 계산한 객체와 CPU로 계산한 객체는 서로 연산이 불가능하다는 점이다.
x = torch.tensor([1,1]).to("mps")
y = torch.tensor([0.5, 0.1])
print(x + y)
RuntimeError: Expected all tensors to be on the same device, but found at least two devices, mps:0 and cpu!
x는 mps로 계산하고 y는 cpu로 계산한 값이기 때문에 서로 연산이 불가능
이론상으로 노드에서 노드로 이어지는 계산을 수행한 후 예측값을 수정하기 위해 진행하는 오차역전파에서 gradient를 얻기 위해서 torch
에서는 설정해줘야 하는 것이 있다
a = torch.tensor([2.], requires_grad=True)
b = torch.tensor([1.], requires_grad=True)
함수에서 볼 수 있는 requires_grad
를 True로 설정해야 한다는 것
a = torch.tensor([2.], requires_grad=True)
b = torch.tensor([1.], requires_grad=True)
c = a + b
d = b + 1
e = c * d
c.retain_grad() # gradient를 계산할 수 있는 자격(?)을 주고
d.retain_grad()
e.retain_grad()
e.backward(retain_graph=True) # gradient를 계산하면
print(a.grad)
print(b.grad)
print(c.grad)
print(d.grad)
print(e.grad) # grad를 구할 수 있다
retain_grad()
가 없이 c, d, e 값을 확인해보면 grad를 적용할 수 없는 None값이 출력될 것
따라서, retain_grad()
를 부여하고 역전파를 실행하여 grdient를 계산하면 grad를 얻을 수 있다.
여기서 주의해야 할 점은 역전파를 계속 수행하게 되면 grad값이 너무 커지는 현상이 발생하여 좋은 학습에 방해가 된다! 따라서 grad 값을 0으로 초기화하는 작업이 필요
a.grad.zero_()
항상 backward()
가 끝나면 넣어주도록 하자
이제 grad가 필요없어진 상황에선 아래와 같이 변수에 grad 성질을 제거한다
a.requires_grad = False
a = a.detach()
2가지 방법 중 아무거나 활용해도 된다