1. Scalar
우리가 아는 선형대수에서 배우는 스칼라 즉 상숫값입니다. torch 내 tensor method를 이용해 스칼라 값을 정의할 수 있습니다.
import torch
scalar1 = torch.tensor([1.])
scalar1 = torch.tensor([2.])
print(scalar1)
#tensor([1.])
tensor([1.])가 출력됩니다. 이러한 스칼라값들은 사칙연산 기호 또는 내장 메서드를 이용해 계산할 수 있습니다.
torch.add(scalar1, scalar2) # 덧셈
# scalar1 + scalar2
torch.sub(scalar1, scalar2) # 뺄셈
# scalar1 - scalar2
torch.mul(scalar1, scalar2) # 곱셈
# scalar1 * scalar2
torch.div(scalar1, scalar2) # 나눗셈
#scalar1 / scalar2
2. Vector
벡터는 하나의 값을 2개 이상의 수치로 표현한 것입니다.
vector1 = torch.tensor([1., 2., 3.])
vector2 = torch.tensor([4., 5., 6.])
print(vector1)
# tensor([1., 2., 3.])
스칼라와 마찬가지로 사칙연산과 같은 내장 메서드로 벡터끼리의 계산을 해주면 각 요소별로(element-wise) 연산됩니다.
torch.add(vector1, vector2) # 덧셈
# scalar1 + scalar2
torch.sub(vector1, vector2) # 뺄셈
# vector1 - vector2
torch.mul(vector1, vector2) # 곱셈
# vector1 * vector2
torch.div(vector1, vector2) # 나눗셈
#vector1 / vector2
3. Matrix
행렬은 2개 이상의 벡터 값을 통합해 구성된 값으로, 벡터 값 간 연산 속도를 빠르게 진행할 수 있는 선형 대수의 기본 단위입니다.
matrix1 = torxh.tensor([[1., 2.], [3., 4.]])
matrix = torxh.tensor([[5., 6.], [7., 8.]])
print(matrix1)
#tensor([[1., 2.], [3., 4.]])
행렬도 스칼라와 벡터와 마찬가지로 사칙연산기호와 이에 대응하는 내장 메서드 두 가지 방법으로 사칙연산을 할 수 있습니다. 이 때 행렬 값 간 사칙연산 역시 벡터 연산처럼 각 요소별로 계산됩니다. 또한 행렬 곱 연산을 torch.matmul을 이용해 실행할 수 있습니다.
torch.matmul(matrix1, matrix2)
# tensor([[19., 22.],
# 43., 50.])
4. Tensor
텐서는 2차원 이상의 배열이라 표현할 수 있습니다. 다음은 스칼라부터 텐서를 그림으로 표현한 것입니다.
텐서는 선형대수학에서 n>2일 때 Rn공간에 존재하는 행렬이라고 볼 수 있습니다(저의 의견입니다) 텐서값도 스칼라 벡터, 행렬과 같이 사칙연산기호와 내장 메서드로 사칙연산수행이 가능하고, 텐서 간 내적 연산이 가능합니다.
tensor1 = torch.tensor([[[1., 2.], [3., 4.]], [[5., 6.], [7., 8.]]])
tensor1 = torch.tensor([[[9., 10.], [11., 12.]], [[13., 14.], [15., 16.]]])
#tensor([[[31., 34.],
# [71., 78.]],
# [[155., 166.],
# [211., 226.]]])
텐서 간 텐서곱 연산은 해당하는 인덱스의 행렬들을 행렬곱한 것들이 뒤로 줄 지어있는 직육면체 블록을 생각하면 쉽습니다.
5. Broadcasting
기본적으로 텐서값끼리의 연산은 크기가 동일해야하나 크기가 다를 경우 Broadcasting 자동적으로 shape을 맞춰 계산해준다.
ex)
m1 = torch.tensor([[1, 2]])
m2 = torch.tensor([3]) # -> [[3, 3]]
print(m1 + m2)
# tensor([4, 5])
m3 = torch.tensor([[1, 2]])
m4 = torch.tensor([[3], [4]]) # -> [[3, 3], [4, 4]]
print(m3 + m4)
# tensor([[4, 5], [5, 6]])
6. Multiplication VS Matrix Multiplication
torch의 내장메서드에서 mul은 element-wise 곱셈을, matmul은 행렬곱을 나타내는데, 여기서도 broadcasting이 적용된다.
m1 = torch.tensor([[1, 2], [3, 4]])
m2 = torch.tensor([[1], [2]])
# broadcasting으로 둘 사이 연산 시 m2 -> tensor([[1, 1], [2, 2]])
print(m1.mul(m2)) # m1 * m2
# tensor([[1, 2], [6, 8]])
print(m1.matmul(m2))
# tensor([[5], [11]])
7. Autograd
Autograd를 통해 오차역전파를 이용해 파라미터를 업데이트하는 방법을 쉽게 구현할 수 있습니다.
if torch.cuda.is_available(): # GPU를 이용해 계산할 수 있는지 파악(True, False 반환)
DEVICE = torch.device('cuda') # cuda 장비 사용
else:
DEVICE = torch.device('cpu') # cpu 장비 사용
BATCH_SIZE = 64 # 파라미터를 업데이트할 계산되는 데이터 개수
INPUT_SIZE = 1000 # 입력층 노드의 수
HIDDEN_SIZE = 100 # 은닉층 노드 수
OUTPUT_SIZE = 10 # 최종으로 출력되는 값의 벡터 크기
x = torch.randn(BATCH_SIZE, INPUT_SIZE, # 크기가 input_size인 데이터 batch_size만큼 생성
device = DEVICE,
dtype = torch.float,
requires_grad = False) # 학습을 통해 조절될 매개변수가 아님
y = torch.randn(BATCH_SIZE, OUTPUT_SIZE, # 크기가 output_size인 데이터 batch_size개 생성
device = DEVICE,
dtype = torch.float,
requires_grad = False) #
w1 = torch.randn(INPUT_SIZE, HIDDEN_SIZE, # x와 행렬곱을 통해 (hidden_size, batch_size)를 만들어야 하므로 다음과 같은 형상
device = DEVICE,
dtype = torch.float,
requires_grad = True) # 학습을 통한 매개변수 조절 필요함
w2 = torch.randn(HIDDEN_SIZE, OUTPUT_SIZE,
device = DEVICE,
dtype = torch.float,
requires_grad = True) # 학습을 통한 매개변수 조절 필요함
learning_rate = 1e-6 # 학습률(gradient에 따른 학습 정도) 결정
torch.randn은 평균이 0 표준편차가 1인 정규분포에서 샘플링한 값입니다.
for t in range(1, 501): # 500번 학습(epochs=500)
y_pred = x.mm(w1).clamp(min=0).mm(w2) # torch.mm()을 사용해 가중치와 행렬곱 적용 후, clamp(min=0)로 활성화 함수 적용(ReLU와 같은 역할)
loss = (y_pred - y).pow(2).sum() # 오차 계산
if t % 100 == 0: # 100번째 반복마다
print(f"Iteration: {t}\t Loss: {loss.item()}") # 반복 횟수 및 오차 표시
loss.backward() # 오차역전파법 수행
with torch.no_grad(): # gradient 계산 결과 이용해 파라미터 업데이트할 때는 gradient값 고정
w1 -= learning_rate * w1.grad # 가중치 업데이트
w2 -= learning_rate * w2.grad # 가중치 업데이트
w1.grad.zero_() # gradient를 통해 파라미터 업데이트 했으므로 다시 학습을 위해 graident 0으로 초기화
w2.grad.zero_()
데이터를 랜덤하게 샘플링했음에도 반복이 더해질수록 오차가 줄어드는 것을 알 수 있습니다!
# Auto grad구현 https://colab.research.google.com/drive/1oTpmnggPJZGHGCUG7zTicRslNGf6FWy3
'AI_basic > Pytorch' 카테고리의 다른 글
[Pytorch] 작물 잎 분류 Pre-trained model(resnet50) (1) | 2022.02.07 |
---|---|
[Pytorch] 작물 잎 분류 non Pre_trained model (0) | 2022.02.06 |
[Pytorch Part.5] Augmentation과 CNN (0) | 2022.01.14 |
[Pytorch Part.4] AutoEncoder (0) | 2022.01.14 |
[Pytorch Part.2] AI Background (0) | 2022.01.06 |