1. 단순선형회귀 구현


import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

torch.manual_seed(1)
# 데이터
x_train = torch.FloatTensor([[1], [2], [3]])
y_train = torch.FloatTensor([[2], [4], [6]])

위 데이터는 y=2x를 가정한 상태로 만들어진 데이터로, 우리는 이미 정답이 W=2, b=0임을 알고있는 상태로, 모델이 이 2개의 값을 정확히 찾는지 확인하고자 한다.

# 모델을 선언 및 초기화, 단순 선형 회귀이므로 input_dim=1, output_dim=1
model = nn.Linear(1,1)

# 첫 번째 param은 W, 두 번째 param은 b를 의미
print(list(model.parameters()))
[Parameter containing:
tensor([[0.5153]], requires_grad=True), Parameter containing:
tensor([-0.4414], requires_grad=True)]

nn.Linear()를 이용하여 모델을 선언하고 초기화해주었다.

  • nn.Linear()는 입력의 차원, 출력의 차원을 param으로 받음

  • 위에서는 하나의 입력 x에 대하여 하나의 출력 y를 가지므로 param으로 (1, 1)을 줌

  • model에는 model의 parameter인 W와 b가 존재하고, 그 값을 출력한 결과가 위에 있음

# optimizer 설정
optimizer = optim.SGD(model.parameters(), lr=0.01)

이제 optimizer를 설정하고, model.parameters()를 이용하여 W와 b를 전달한다.

# 전체 훈련 데이터에 경사하강법을 2000회 반복
nb_epochs = 2000
for epoch in range(nb_epochs + 1):

    # H(x) 계산
    prediction = model(x_train)

    # cost 계산
    cost = F.mse_loss(prediction, y_train) # <== 파이토치에서 제공하는 mse 함수

    #최적화
    optimizer.zero_grad()
    cost.backward()
    optimizer.step()

    if epoch % 100 == 0:
        print('Epoch {:4d}/{} Cost: {:.6f}'.format(
          epoch, nb_epochs, cost.item()
      ))
Epoch    0/2000 Cost: 13.103541
Epoch  100/2000 Cost: 0.002791
Epoch  200/2000 Cost: 0.001724
Epoch  300/2000 Cost: 0.001066
Epoch  400/2000 Cost: 0.000658
Epoch  500/2000 Cost: 0.000407
Epoch  600/2000 Cost: 0.000251
Epoch  700/2000 Cost: 0.000155
Epoch  800/2000 Cost: 0.000096
Epoch  900/2000 Cost: 0.000059
Epoch 1000/2000 Cost: 0.000037
Epoch 1100/2000 Cost: 0.000023
Epoch 1200/2000 Cost: 0.000014
Epoch 1300/2000 Cost: 0.000009
Epoch 1400/2000 Cost: 0.000005
Epoch 1500/2000 Cost: 0.000003
Epoch 1600/2000 Cost: 0.000002
Epoch 1700/2000 Cost: 0.000001
Epoch 1800/2000 Cost: 0.000001
Epoch 1900/2000 Cost: 0.000000
Epoch 2000/2000 Cost: 0.000000

Cost가 매우 작은 것을 보아 학습이 잘 되었음을 확인 가능하다.

x에 임의의 값 4를 넣어 모델이 예측하는 y값을 한 번 검증해보자.

# 임의의 입력 4 선언
new_var = torch.FloatTensor([[4]])

# 입력한 값에 대해서 예측값 y를 받아서 pred_y에 저장
pred_y = model(new_var)

# y=2x이므로 결과는 8이 나와야함
print("훈련 후 입력이 4일 때의 예측값 :", pred_y)
훈련 후 입력이 4일 때의 예측값 : tensor([[7.9989]], grad_fn=<AddmmBackward0>)

이 문제의 모델은 y=2x가 정답이므로 y값이 8에 가까우면 W와 b의 값이 어느정도 잘 최적화 되었다고 판단할 수 있다.

print(list(model.parameters()))
[Parameter containing:
tensor([[1.9994]], requires_grad=True), Parameter containing:
tensor([0.0014], requires_grad=True)]

실제로 model.parameters()를 이용하여 학습된 model의 parameter를 확인해도 W는 2에 가깝게, b는 0에 가깝게 나온 것을 알 수 있다.

2. 다중선형회귀 구현


이제 nn.Linear()nn.functional.mse_loss()를 이용하여 다중선형회귀를 구현해보자.

코드 자체는 거의 비슷하고, nn.Linear()의 paramter와 optim.SGD() 에서의 lr(learning rate)만 조절해주었다.

# 데이터
x_train = torch.FloatTensor([[73, 80, 75],
                             [93, 88, 93],
                             [89, 91, 90],
                             [96, 98, 100],
                             [73, 66, 70]])
y_train = torch.FloatTensor([[152], [185], [180], [196], [142]])

# 모델 선언 및 초기화
model = nn.Linear(3,1)

# optimizer 설정
optimizer = optim.SGD(model.parameters(), lr=1e-5)

nb_epochs = 8000
for epoch in range(nb_epochs + 1):

    # H(x) 계산
    prediction = model(x_train)

    # cost 계산
    cost = F.mse_loss(prediction, y_train)

    # 최적화
    optimizer.zero_grad()
    cost.backward()
    optimizer.step()

    if epoch % 400 == 0:
        print('Epoch {:4d}/{} Cost: {:.6f}'.format(
          epoch, nb_epochs, cost.item()
      ))
Epoch    0/8000 Cost: 42134.707031
Epoch  400/8000 Cost: 5.091429
Epoch  800/8000 Cost: 4.132426
Epoch 1200/8000 Cost: 3.360339
Epoch 1600/8000 Cost: 2.738666
Epoch 2000/8000 Cost: 2.238115
Epoch 2400/8000 Cost: 1.835095
Epoch 2800/8000 Cost: 1.510549
Epoch 3200/8000 Cost: 1.249218
Epoch 3600/8000 Cost: 1.038766
Epoch 4000/8000 Cost: 0.869314
Epoch 4400/8000 Cost: 0.732821
Epoch 4800/8000 Cost: 0.622899
Epoch 5200/8000 Cost: 0.534348
Epoch 5600/8000 Cost: 0.463017
Epoch 6000/8000 Cost: 0.405559
Epoch 6400/8000 Cost: 0.359250
Epoch 6800/8000 Cost: 0.321932
Epoch 7200/8000 Cost: 0.291842
Epoch 7600/8000 Cost: 0.267582
Epoch 8000/8000 Cost: 0.248009

학습을 완료한 후, Cost의 값이 매우 작음을 알 수 있다.
임의의 x값에 대한 모델 예측값도 잘 나오는지 확인해보자

# 임의의 입력 [73, 80, 75]를 선언
new_var =  torch.FloatTensor([[73, 80, 75]]) 
# 입력한 값 [73, 80, 75]에 대해서 예측값 y를 리턴받아서 pred_y에 저장
pred_y = model(new_var) 
print("훈련 후 입력이 73, 80, 75일 때의 예측값 :", pred_y) 
훈련 후 입력이 73, 80, 75일 때의 예측값 : tensor([[151.2305]], grad_fn=<AddmmBackward>)

임의의 데이터 new_var은 사실 훈련 데이터로 사용했던 데이터이다. 실제 y값은 152인데, 예측값이 151이 나온 것으로 보아 어느 정도는 최적화 되었음을 알 수 있다.

print(list(model.parameters()))
[Parameter containing:
tensor([[1.0391, 0.6011, 0.3700]], requires_grad=True), Parameter containing:
tensor([0.3583], requires_grad=True)]

model의 paramter를 확인해보았다.

profile
예비대학원생

0개의 댓글