또르르's 개발 Story

[11-2] PyTorch 기본문법 본문

부스트캠프 AI 테크 U stage/이론

[11-2] PyTorch 기본문법

또르르21 2021. 2. 2. 02:16

PyTorch는 Python을 위한 오픈소스 머신러닝 라이브러리입니다.

페이스북에서 개발했고, 다양한 Deep Learning 함수와 모델을 지원합니다.

 

1️⃣ PyTorch 개요

 

PyTorch는 머신러닝 라이브러리로써, 3가지의 장점을 가지고 있습니다.

 

Numpy + AutoGrad + Function

 

  • Numpy : Numpy 구조를 가지는 Tensor 객체로 array 연산이 가능

  • AutoGrad : 자동 미분을 지원하여 Deep Learning 연산을 지원

  • Function : 다양한 형태의 Deep Learning을 지원하는 함수와 모델 지원

 

그렇다면 PyTorch는 다른 프레임워크와 다른 점은 무엇일까요?

가장 큰 특징은 맨 마지막에 있는 Computational graphs used입니다.
딥러닝을 하려면 연쇄법칙(연속적으로 미분)을 적용해야 하는데 tensorflow(Keras)는 static graph를 선언해줘서 값을 주입하는 방식을 사용합니다. 
하지만 PyTorch는 그냥 불러오는 게 가능합니다.

 

2️⃣ PyTorch 기본 문법

 

PyTorch를 사용하려면 모듈을 import해야합니다.

import torch

 

  • FloatTensor() : array를 Tensor 객체로 변경
n_array = np.arange(10).reshape(2,5)

>>> t_array = torch.FloatTensor(n_array)

tensor([[0., 1., 2., 3., 4.],
        [5., 6., 7., 8., 9.]])

 

  • ndim : 차원 출력
>>> t_array.ndim

2			# 2차원 matrix

 

  • shape : 형태 출력
>>> t_array.shape

torch.Size([3, 5])

 

  • size() : 형태 출력(shape과 같음)
>>> t_array.size()

torch.Size([3, 5])

 

  • matmul() : maxtrix 곱셈
t1 = torch.FloatTensor(n1)

t2 = torch.FloatTensor(n2)

>>> t1.matmul(t2)

tensor([[ 60.,  70.],
        [160., 195.]])

 

  • t1 * t2 : element-wise operation (같은 행, 열끼리만 곱)
>>> t1 * t2

tensor([[0., 1.],
        [4., 9.]])

 

  • dim : 축 (numpy의 axis)
>>> t1

tensor([[0., 1.],
        [2., 3.]])


>>> t1.mean(dim=1)		# 열로 덧셈

tensor([0.5000, 2.5000])

 

  • view() : 형태 재정의 (numpy의 reshape)
n1 = np.arange(10)

t1 = torch.FloatTensor(n1)


>>> t1.view(-1, 2)

tensor([[0., 1.],
        [2., 3.],
        [4., 5.],
        [6., 7.],
        [8., 9.]])

 

  • squeeze() : Rank 하나 줄이기
>>> t1

tensor([[0., 1.],
        [2., 3.],
        [4., 5.],
        [6., 7.],
        [8., 9.]])



>>> t1.view(-1, 10).squeeze()

tensor([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])

 

  • unsqueeze() : Rank 하나 늘리기(dim으로 방향 지정)
>>> t1.view(-1, 10).squeeze().unsqueeze(dim=0)

tensor([[0., 1., 2., 3., 4., 5., 6., 7., 8., 9.]])

 

 

3️⃣ PyTorch ML/DL formula

 

PyTorch ML/DL function을 사용하려면 torch.nn.functional 모듈을 import 합니다.

import torch.nn.functional as F

 

  • softmax() : softmax 연산
tensor = torch.FloatTensor([0.5, 0.7, 0.1])

h_tensor = F.softmax(tensor, dim=0)

>>> h_tensor

tensor([0.3458, 0.4224, 0.2318])

 

  • argmax() : max의 index값
y = torch.randint(5, (10,5))

y_label = y.argmax(dim=1)

>>> y_label

tensor([1, 0, 3, 4, 0, 4, 1, 0, 1, 0])

 

  • one_hot() : one_hot encoding을 해줌
>>> torch.nn.functional.one_hot(y_label)

tensor([[0, 1, 0, 0, 0],
        [1, 0, 0, 0, 0],
        [0, 0, 0, 1, 0],
        [0, 0, 0, 0, 1],
        [1, 0, 0, 0, 0],
        [0, 0, 0, 0, 1],
        [0, 1, 0, 0, 0],
        [1, 0, 0, 0, 0],
        [0, 1, 0, 0, 0],
        [1, 0, 0, 0, 0]])

 

 

4️⃣ PyTorch autograd


PyTorch는 자동 미분을 지원합니다.

 

1) y=w2z=2y+5z=2w2+5

 

w = torch.tensor(2.0, requires_grad=True)		

# tensor에 scalar 2를 넣음, requires_grad는 그레디언트를 할 것인가

y = w**2

z = 2*y + 5
z.backward()			# backward(역전파)를 통해 자동 미분
>>> w.grad			# grad를 통해 미분값 표시

tensor(8.)

 

2) Q=3a3b2

 

a = torch.tensor([2., 3.], requires_grad=True)

# tensor에 vector [2, 3]을 넣음, requires_grad는 그레디언트를 할 것인가

b = torch.tensor([6., 4.], requires_grad=True)
Q = 3*a**3 - b**2
external_grad = torch.tensor([1., 1.])		# external_grad는 dQ = 1/da =1로 해준다는 뜻

Q.backward(gradient=external_grad)		# backward를 하면 미분이 일어남
>>> a.grad

tensor([36., 81.])

>>> b.grad

tensor([-12.,  -8.])



5️⃣ PyTorch Linear Regression

 

y=2x+1

import numpy as np

# create dummy data for training

x_values = [i for i in range(11)]

x_train = np.array(x_values, dtype=np.float32)

x_train = x_train.reshape(-1, 1)


y_values = [2*i + 1 for i in x_values]

y_train = np.array(y_values, dtype=np.float32)

y_train = y_train.reshape(-1, 1)
import torch

from torch.autograd import Variable

class linearRegression(torch.nn.Module):

    def __init__(self, inputSize, outputSize):
    
        super(linearRegression, self).__init__()
        
        self.linear = torch.nn.Linear(inputSize, outputSize)


    def forward(self, x):
    
        out = self.linear(x)
        
        return out
inputDim = 1        # takes variable 'x' 

outputDim = 1       # takes variable 'y'

learningRate = 0.01 

epochs = 100


model = linearRegression(inputDim, outputDim)

##### For GPU #######

if torch.cuda.is_available():

    model.cuda()
criterion = torch.nn.MSELoss() 

optimizer = torch.optim.SGD(model.parameters(), lr=learningRate)
for epoch in range(epochs):

    # Converting inputs and labels to Variable
    
    if torch.cuda.is_available():
    
        inputs = Variable(torch.from_numpy(x_train).cuda())
        
        labels = Variable(torch.from_numpy(y_train).cuda())
        
    else:
    
        inputs = Variable(torch.from_numpy(x_train))
        
        labels = Variable(torch.from_numpy(y_train))
        
        

    # Clear gradient buffers because we don't want any gradient from previous epoch to carry forward, dont want to cummulate gradients
    
    optimizer.zero_grad()


    # get output from the model, given the inputs
    
    outputs = model(inputs)


    # get loss for the predicted output
    
    loss = criterion(outputs, labels)
    
    print(loss)
    
    
    # get gradients w.r.t to parameters
    
    loss.backward()


    # update parameters
    
    optimizer.step()

    
    print('epoch {}, loss {}'.format(epoch, loss.item()))
tensor(230.4760, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 0, loss 230.47596740722656
tensor(19.4424, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 1, loss 19.442428588867188
tensor(2.2219, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 2, loss 2.221906900405884
tensor(0.8102, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 3, loss 0.8101815581321716
tensor(0.6880, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 4, loss 0.6880084276199341
tensor(0.6711, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 5, loss 0.6710980534553528
tensor(0.6629, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 6, loss 0.6628516316413879
tensor(0.6554, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 7, loss 0.655388355255127
tensor(0.6481, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 8, loss 0.6480644345283508
tensor(0.6408, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 9, loss 0.6408273577690125
tensor(0.6337, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 10, loss 0.633671224117279
tensor(0.6266, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 11, loss 0.626595139503479
tensor(0.6196, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 12, loss 0.6195980906486511
tensor(0.6127, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 13, loss 0.6126788258552551
tensor(0.6058, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 14, loss 0.6058374643325806
tensor(0.5991, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 15, loss 0.5990719795227051
tensor(0.5924, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 16, loss 0.5923821926116943
tensor(0.5858, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 17, loss 0.585767388343811
tensor(0.5792, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 18, loss 0.579226016998291
tensor(0.5728, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 19, loss 0.5727581977844238
tensor(0.5664, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 20, loss 0.566362202167511
tensor(0.5600, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 21, loss 0.5600376725196838
tensor(0.5538, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 22, loss 0.5537838935852051
tensor(0.5476, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 23, loss 0.5475997924804688
tensor(0.5415, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 24, loss 0.5414849519729614
tensor(0.5354, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 25, loss 0.5354381799697876
tensor(0.5295, device='cuda:0', grad_fn=<MseLossBackward>)
epoch 26, loss 0.5294590592384338
.....
with torch.no_grad(): # we don't need gradients in the testing phase

    if torch.cuda.is_available():
    
        predicted = model(Variable(torch.from_numpy(x_train).cuda())).cpu().data.numpy()
        
    else:
    
        predicted = model(Variable(torch.from_numpy(x_train))).data.numpy()
        
    print(predicted)
    
    
    
[[ 0.10160638]
 [ 2.2309833 ]
 [ 4.36036   ]
 [ 6.489737  ]
 [ 8.619114  ]
 [10.748491  ]
 [12.877868  ]
 [15.007245  ]
 [17.136621  ]
 [19.265999  ]
 [21.395376  ]]
Comments