Pytorch
- numpy
numpy 기반 - autograd
자동미분 지원 - function
다양한 형태의 함수와 모델 지원
Tensor
다차원 arrays를 표현하는 pytorch 클래스
python의 list = numpy 의 ndarray = pytorch 의 tensor = tensorflow의 tensor
import numpy as np
import torch
arr=list(range(10))
print(arr)
np_array=np.array(arr)
print(f"type : {type(np_array)}, ndim : {np_array.ndim}, shape : {np_array.shape}")
torch_tensor=torch.tensor(arr)
print(f"type : {type(torch_tensor)}, ndim : {torch_tensor.ndim}, shape : {torch_tensor.shape}")
torch_ftensor=torch.FloatTensor(arr)
print(f"type : {type(torch_ftensor)}, ndim : {torch_ftensor.ndim}, shape : {torch_ftensor.shape}")
torch_fnp=torch.from_numpy(np_array)
print(f"type : {type(torch_fnp)}, ndim : {torch_fnp.ndim}, shape : {torch_fnp.shape}")
>>>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
type : <class 'numpy.ndarray'>, ndim : 1, shape : (10,)
type : <class 'torch.Tensor'>, ndim : 1, shape : torch.Size([10])
type : <class 'torch.Tensor'>, ndim : 1, shape : torch.Size([10])
type : <class 'torch.Tensor'>, ndim : 1, shape : torch.Size([10])
tensor, FloatTensor, from_numpy등 으로 tensor을 만들 수 있다.
Tensor data types
https://pytorch.org/docs/stable/tensors.html
각 data type에 대응하는 tensor 타입을 페이지에서 볼 수 있다.
특이한 점은 GPU를 사용할 때 쓰는 tensor타입이 다르다는 것이다
torch_tensor.device
>>>device(type='cpu')
그래서 지금 사용중인 텐서가 메모리(=cpu)에 올라가 있는지 GPU에 올라가 있는지 확인하고 변경할 수 있는 속성이다.
현재는 메모리에 올라가 있다.
GPU에 올리기 위해서는 GPU가 필요한데 노트북이나 데스크탑에 없다면
colab>런타임>런타임 유형변경>GPU를 통해서 GPU를 사용해 볼 수 있다
if torch.cuda.is_available():
torch_cuda=torch_tensor.to('cuda')
torch_cuda.device
>>>device(type='cuda', index=0)
이렇게 type='cuda'이면 GPU에 올라가 있는 것이다.
Tensor handling
텐서 모양을 다루어보고 크기를 변경해보자
tensor=torch.rand(size=(1,3,2))
tensor
>>>tensor([[[0.4723, 0.2442],
[0.9367, 0.0366],
[0.9045, 0.4830]]])
- view(=reshape)
reshape과 view는 copy방식에서만 차이가 난다.tensor.view([-1,6]) >>>tensor([[0.4723, 0.2442, 0.9367, 0.0366, 0.9045, 0.4830]]) tensor.reshape([-1,6]) >>>tensor([[0.4723, 0.2442, 0.9367, 0.0366, 0.9045, 0.4830]])
view는 기존의 값(메모리 주소)만 가져와서 보여주는 형태만 바꾸어 준 것이다.
하지만 reshape은 메모리 할당을 할 때, 값이 바뀌게 되면 주소를 가져오는 것이 아니라 copy를 해서 가져온다.
복잡하다면 view를 주로 사용하면 좋다. - squeeze
차원 삭제
tensor의 shape이 1인 것을 모두 삭제한다
(1,3,2)->(3,2)로 1인 차원이 삭제 되었다tensor1=tensor.squeeze() print(tensor1.shape) tensor1 >>>torch.Size([3, 2]) tensor([[0.4723, 0.2442], [0.9367, 0.0366], [0.9045, 0.4830]])
- unsqueeze
차원 추가
안에서부터 밖으로 숫자가 작아진다tensor.unsqueeze(dim=3) >>>tensor([[[[0.4723], [0.2442]], [[0.9367], [0.0366]], [[0.9045], [0.4830]]]])
가장 바깥에 추가하고싶으면 dim=0을 넣으면 된다
현재에서는 가장 안의 dim으로 3을 넣었더니 각 숫자마다[]가 생기는 것으로 차원이 추가된 것을 확인할 수 있다
Tensor Operations
t1=torch.tensor(np.arange(0,10).reshape(2,5))
t2=torch.tensor(np.arange(10,101,10).reshape(2,5))
print(t1)
print(t2)
>>>tensor([[0, 1, 2, 3, 4],
[5, 6, 7, 8, 9]], dtype=torch.int32)
tensor([[ 10, 20, 30, 40, 50],
[ 60, 70, 80, 90, 100]], dtype=torch.int32)
- +
t1+t2 >>>tensor([[ 10, 21, 32, 43, 54], [ 65, 76, 87, 98, 109]], dtype=torch.int32)
- -
t1-t2 >>>tensor([[-10, -19, -28, -37, -46], [-55, -64, -73, -82, -91]], dtype=torch.int32)
- 스칼라 덧셈
t1+10 >>>tensor([[10, 11, 12, 13, 14], [15, 16, 17, 18, 19]], dtype=torch.int32)
- 스칼라 곱셈
t1*10 >>>tensor([[ 0, 10, 20, 30, 40], [50, 60, 70, 80, 90]], dtype=torch.int32)
- 벡터 곱셈 (내적)
1차원 * 1차원
t1=torch.tensor(np.arange(5)) print(t1) t1.dot(t1) >>>tensor([0, 1, 2, 3, 4], dtype=torch.int32) tensor(30, dtype=torch.int32)
- 행렬 곱셈
다차원 * 다차원
t1=torch.tensor(np.arange(10).reshape(2,5)) t2=torch.tensor(np.arange(10,20).reshape(5,-1)) t1.mm(t2) >>>tensor([[160, 170], [510, 545]], dtype=torch.int32)
- 행렬 곱셈(broadcasting)
위의 mm 과 같지만 matmul은 broadcasting이 가능하다.
행렬 사이즈가 모자르면 늘려주는 것으로 broadcasting을 간단하게 이해할 수 있다
하지만 자칫하면 잘못된 식이지만 계산은 되는 것 처럼 보이기 때문에 헷갈릴 수 있다.
t1=torch.tensor(np.arange(24).reshape(2,3,4)) print(t1) t2=torch.tensor(np.arange(4).reshape(4)) print(t2) t1.matmul(t2) >>>ensor([[[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]], [[12, 13, 14, 15], [16, 17, 18, 19], [20, 21, 22, 23]]], dtype=torch.int32) tensor([0, 1, 2, 3], dtype=torch.int32) tensor([[ 14, 38, 62], [ 86, 110, 134]], dtype=torch.int32)
ML/DL formula
- softmax
import torch.nn.functional as F tensor=torch.rand(3) print('tensor : ',tensor) soft_tensor=F.softmax(tensor,dim=0) soft_tensor >>>tensor : tensor([0.2970, 0.1430, 0.1812]) tensor([0.3639, 0.3120, 0.3241])
- argmax
tensor=torch.randint(5,(3,5)) print(tensor) tensor1=tensor.argmax(dim=0) print('axis=0',tensor1) tensor2=tensor.argmax(dim=1) print('axis=1',tensor2) >>>tensor([[0, 0, 3, 3, 1], [3, 2, 4, 3, 3], [2, 2, 3, 3, 2]]) axis=0 tensor([1, 2, 1, 2, 1]) axis=1 tensor([3, 2, 3])
- one_hot
위의 agrmax 예제에서 값의 최대가 4가 아닌 3이어서 열 생성이 5개가 아닌 4개만 되었다고 추측할 수 있다F.one_hot(tensor2) >>>tensor([[0, 0, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]])
- cartesian_prod
python의 intertoold처럼 모든 경우의 수를 구해주는 카르테지안 곱이 있다
t1=torch.tensor([1,2,3]) t2=torch.tensor([4,5,6]) torch.cartesian_prod(t1,t2) >>>tensor([[1, 4], [1, 5], [1, 6], [2, 4], [2, 5], [2, 6], [3, 4], [3, 5], [3, 6]])
Autograd
자동미분
backward 함수를 사용해서 구현할 수 있다
미분을 해주는 대상이 되는 것은 requires_grad 속성을 True로 해준다
w=torch.tensor(3.0, requires_grad=True)
y=w**2
z=y+5
z.backward()
w.grad
>>>tensor(6.)
$$ y= w^2$$
$$z=y+5$$
$$ \frac{\partial{z}}{\partial{w}}=\frac{\partial{z}}{\partial{y}}\frac{\partial{y}}{\partial{w}} = 2w $$
$$2\times3=6$$
a=torch.tensor([5.0,6.0], requires_grad=True)
b=torch.tensor([2.0,3.0], requires_grad=True)
y= 2*a**3 +b**4
external_grad=torch.tensor([1,1])
y.backward(gradient=external_grad)
print(external_grad)
print(a.grad)
print(b.grad)
>>>tensor([1, 1])
tensor([150., 216.])
tensor([ 32., 108.])
backward에서 미분이 일어난다
$$y=2a^3+b^4$$
$$\frac{\partial{y}}{\partial{a}}=6a^2$$
$$\frac{\partial{y}}{\partial{b}}=4b^3$$
$$6\times 5 \times 5=150$$
'부스트캠프 AI Tech 3기 > 이론 : U-stage' 카테고리의 다른 글
[Day7] Pytorch 4. AutoGrad & Optimizer : Module, Parameter (0) | 2022.01.25 |
---|---|
[Day6] Pytorch 3. PyTorch 프로젝트 구조 이해하기 : template, ngrok (0) | 2022.01.24 |
[Day5] AI math 8. 베이즈 통계학 맛보기 (0) | 2022.01.22 |
[Day4] AI math 7. 통계학 맛보기 : 모수, 확률분포, 정규분포,최대가능도 추정법, MLE, 로그가능도, 확률분포 거리, 쿨백라이블러 발산 (0) | 2022.01.22 |
[Day4] AI math 6. 확률론 맛보기 : 확률분포, 확률변수, 결합분포, 주변확률분포, 조건부 확률분포, 조건부 확률, 기대값, 몬테카를로 샘플링 (0) | 2022.01.21 |