PyTorch 기초 - 경사하강법

ingeol·2023년 2월 14일
0

pytorch

목록 보기
3/5

경사하강법

  • 효율적으로 가중치 파라미터를 찾기위함
  • 경사하강법 수식
θ=θ(learningrate)×L(θ)\theta = \theta - (learning-rate) \times \nabla L(\theta)
  • 손실함수를 통해 가중치 파라미터를 찾을 수 있음
  • 파라미터 조절 후 함수의 근사계산을 할 때 활용가능
import torch
import torch.nn.functional as F
target = torch.FloatTensor([[.1,.2,.3],[.4,.5,.6],[.7,.8,.9]])
x = torch.rand_like(target)
x
'''
tensor([[0.4374, 0.3090, 0.8592],
        [0.2560, 0.9136, 0.2861],
        [0.8658, 0.8617, 0.0715]])
'''

텐서의 requires_grad 속성이 True가 되도록 설정 하면 미분 및 경사하강법 수행이 가능해진다.

x.requires_grad = True
print(x)
'''
tensor([[0.4374, 0.3090, 0.8592],
        [0.2560, 0.9136, 0.2861],
        [0.8658, 0.8617, 0.0715]], requires_grad=True)
'''
loss = F.mse_loss(x, target)
loss
# tensor(0.2287, grad_fn=<MseLossBackward0>)

backward() 함수를 이용해 편미분을 진행하며, 이 gradient는 x.grad에 자동으로 저장된다. backward()사용하기위해 텐서의 크기는 scalar이여야 한다.

threshold = 1e-5
learning_rate = 1.
iter_cnt = 0
while loss > threshold:
    iter_cnt += 1
    loss.backward() # 기울기 계산

    x = x - learning_rate * x.grad

    x.detach_()
    x.requires_grad_(True)

    loss = F.mse_loss(x, target)
    
    print(iter_cnt, loss)
    print(x)

아래 출력은 손실값이 점차 줄어드는 모습을 볼 수 있다.

'''
count : 1, loss : 0.08802667260169983
tensor([[0.2943, 0.1191, 0.7827],
        [0.3981, 0.4318, 0.5430],
        [0.5266, 0.1810, 0.5937]], requires_grad=True)
count : 2, loss : 0.053250689059495926
tensor([[0.2511, 0.1371, 0.6754],
        [0.3985, 0.4469, 0.5557],
        [0.5651, 0.3186, 0.6617]], requires_grad=True)
count : 3, loss : 0.032213374972343445
tensor([[0.2176, 0.1511, 0.5920],
        [0.3988, 0.4587, 0.5655],
        [0.5951, 0.4256, 0.7147]], requires_grad=True)
count : 4, loss : 0.019487105309963226
tensor([[0.1914, 0.1619, 0.5271],
        [0.3991, 0.4679, 0.5732],
        [0.6184, 0.5088, 0.7559]], requires_grad=True)
count : 5, loss : 0.011788494884967804
tensor([[0.1711, 0.1704, 0.4766],
        [0.3993, 0.4750, 0.5791],
        [0.6365, 0.5735, 0.7879]], requires_grad=True)

... 생략

count : 16, loss : 4.6803688746877015e-05
tensor([[0.1045, 0.1981, 0.3111],
        [0.4000, 0.4984, 0.5987],
        [0.6960, 0.7857, 0.8929]], requires_grad=True)
count : 17, loss : 2.8313312213867903e-05
tensor([[0.1035, 0.1985, 0.3087],
        [0.4000, 0.4988, 0.5990],
        [0.6969, 0.7889, 0.8945]], requires_grad=True)
count : 18, loss : 1.7127826140495017e-05
tensor([[0.1027, 0.1989, 0.3067],
        [0.4000, 0.4990, 0.5992],
        [0.6976, 0.7914, 0.8957]], requires_grad=True)
count : 19, loss : 1.0361281965742819e-05
tensor([[0.1021, 0.1991, 0.3052],
        [0.4000, 0.4993, 0.5994],
        [0.6981, 0.7933, 0.8967]], requires_grad=True)
count : 20, loss : 6.2678964241058566e-06
tensor([[0.1016, 0.1993, 0.3041],
        [0.4000, 0.4994, 0.5995],
        [0.6985, 0.7948, 0.8974]], requires_grad=True)
'''

AutoGrad - 자동 미분 기능

x = torch.FloatTensor([[1,2],[3,4]]).requires_grad_(True)
x1 = x + 2
print(x1)
#tensor([[3., 4.],
#        [5., 6.]], grad_fn=<AddBackward0>)

x2 = x-2
x2
# tensor([[-1.,  0.],
#        [ 1.,  2.]], grad_fn=<SubBackward0>)

x3 = x1 * x2
print(x3)
# tensor([[-3.,  0.],
#         [ 5., 12.]], grad_fn=<MulBackward0>)

y = x3.sum()
y
# tensor(14., grad_fn=<SumBackward0>)

y.backward()
x.grad
# tensor([[2., 4.],
#        [6., 8.]])

x.grad 값은 각 원소의 편미분된 값이 모두 2x이기 때문에 기존 x값에서 2를 곱한 형태로 출력된다.

0개의 댓글