On the journey of
[딥러닝 홀로서기] Standalone DL; Regression with Pytorch 본문
[딥러닝 홀로서기] Standalone DL; Regression with Pytorch
dlrpskdi 2023. 9. 5. 09:46기록에 앞서, 이 포스팅은 강의를 듣고 기록한 것일 뿐이고 코드의 경우 github에 있는 코드를 공부하고자 가져온 것입니다. 때문에 저작권이 제가 아닌 해당 강의 연사분과 github owner(Jaeyoung Jo) 님께 있음을 미리 밝혀둡니다.
먼저 지난 lecture 복습부터 하자. 한 마디로
머신러닝 problem들은 크게
1) Hypothesis & Cost
2) Cost를 줄이기 위해 Hypothesis의 parameter를 바꾸는 Optimization
이렇게 두 가지로 나뉜다는 거였다. 수식과 함께 나타낸다면 아래 이미지와 같이 될 것.
Linear Regression에서, Cost는 H(x)와 y의 차이의 제곱의 평균이며 딥러닝에서는 Cost에서 보여지는 수식을 많이 쓴다. Optimization은 W와 b에 대해서 cost를 편미분을 진행하면서, gradient의 반대 방향으로 W를 update해 나간다
변수가 여러 개일 때는 행렬로 표현하여 같은 방식으로 수식을 표현할 수 있다. 이제 code 실습으로 넘어가보자(교안은 아래 github 주소 참고)
Pytorch Regression (Linear Regression vs MLP)
Pytorch Regression을 검증하기 위해 Linear Regression, MLP 두 가지의 hypothesis로 검증해보자.
1. Data Generation (Preparation)
: Linear Regression이나 MLP를 통해 x가 input일 떄 y가 얼마나 정확히 나오는 지 살펴보자.
2. Hypothesis Define (Model Define
: 데이터 준비가 끝나면 가설을 모델에 define하는 과정을 시작할 건데, 이때 파이토치 상의 이미 짜여진 코드를 이용할 것.
import torch
import torch.nn as nn
class LinearModel(nn.Module):
def __init__(self):
super(LinearModel, self).__init__()
self.linear = nn.Linear(in_features=2, out_features=1, bias=True)
def forward(self, x):
# 인스턴스(샘플) x가 인풋으로 들어왔을 때 모델이 예측하는 y값을 리턴합니다.
return self.linear(x)
class MLPModel(nn.Module):
def __init__(self):
super(MLPModel, self).__init__()
self.linear1 = nn.Linear(in_features=2, out_features=200)
self.linear2 = nn.Linear(in_features=200, out_features=1)
self.relu = nn.ReLU()
def forward(self, x):
# 인스턴스(샘플) x가 인풋으로 들어왔을 때 모델이 예측하는 y값을 리턴합니다.
x = self.linear1(x)
x = self.relu(x)
x = self.linear2(x)
return x
3. Cost Function Define (Loss Function Define)
모델을 define하고나면 cost를 정의해야 한다. 현재 우리가 하려는 task는 Regression이고, Regression 태스크에서는 cost function 중에서도 주로 Min-squared error(그 유명한 MSE)를 많이 쓴다. 때문에 코드 상에서도 MSE를 활용할 예정.
(reg_loss에 예측한 y와 데이터 y를 넣어주면 알아서 loss를 계산해줌)
reg_loss = nn.MSELoss()
"""uncomment for testing Loss Function
test_pred_y = torch.Tensor([0,0,0,0])
test_true_y = torch.Tensor([0,1,0,1])
print(reg_loss(test_pred_y, test_true_y))
print(reg_loss(test_true_y, test_true_y))
"""
4. Train & Evaluation
데이터, hypothesis, post function 을 구했다면 post function을 줄이기 위한 모델 update 진행
import torch.optim as optim
from sklearn.metrics import mean_absolute_error
# ====== Construct Model ====== #
# model = LinearModel()
# print(model.linear.weight)
# print(model.linear.bias)
model = MLPModel() # Model을 생성해줍니다.
print('{} parameters'.format(sum(p.numel() for p in model.parameters() if p.requires_grad))) # 복잡해보이지만 간단히 모델 내에 학습을 당할 파라미터 수를 카운팅하는 코드입니다.
# ===== Construct Optimizer ====== #
lr = 0.005 # Learning Rate를 하나 정해줍니다. (원할한 학습을 위해 손을 많이 탑니다)
optimizer = optim.SGD(model.parameters(), lr=lr) # Optimizer를 생성해줍니다.
# 매 학습 단계에서의 epoch값과 그 때의 loss 값을 저장할 리스트를 만들어줍시다.
list_epoch = []
list_train_loss = []
list_val_loss = []
list_mae = []
list_mae_epoch = []
epoch = 4000 # 학습 횟수(epoch)을 지정해줍시다.
for i in range(epoch):
# ====== Train ====== #
model.train() # model을 train 모드로 세팅합니다. 반대로 향후 모델을 평가할 때는 eval() 모드로 변경할 겁니다 (나중 실습에서 쓸 겁니다)
optimizer.zero_grad() # optimizer에 남아있을 수도 있는 잔여 그라디언트를 0으로 다 초기화해줍니다.
input_x = torch.Tensor(train_X)
true_y = torch.Tensor(train_y)
pred_y = model(input_x)
#print(input_x.shape, true_y.shape, pred_y.shape) # 각 인풋과 아웃풋의 차원을 체크해봅니다.
loss = reg_loss(pred_y.squeeze(), true_y)
loss.backward() # backward()를 통해서 그라디언트를 구해줍니다.
optimizer.step() # step()을 통해서 그라디언틀르 바탕으로 파라미터를 업데이트 해줍니다.
list_epoch.append(i)
list_train_loss.append(loss.detach().numpy())
# ====== Validation ====== #
model.eval()
optimizer.zero_grad()
input_x = torch.Tensor(val_X)
true_y = torch.Tensor(val_y)
pred_y = model(input_x)
loss = reg_loss(pred_y.squeeze(), true_y)
list_val_loss.append(loss.detach().numpy())
# ====== Evaluation ======= #
if i % 200 == 0: # 200회의 학습마다 실제 데이터 분포와 모델이 예측한 분포를 그려봅니다.
# ====== Calculate MAE ====== #
model.eval()
optimizer.zero_grad()
input_x = torch.Tensor(test_X)
true_y = torch.Tensor(test_y)
pred_y = model(input_x).detach().numpy()
mae = mean_absolute_error(true_y, pred_y) # sklearn 쪽 함수들은 true_y 가 먼저, pred_y가 나중에 인자로 들어가는 것에 주의합시다
list_mae.append(mae)
list_mae_epoch.append(i)
fig = plt.figure(figsize=(15,5))
# ====== True Y Scattering ====== #
ax1 = fig.add_subplot(1, 3, 1, projection='3d')
ax1.scatter(test_X[:, 0], test_X[:, 1], test_y, c=test_y, cmap='jet')
ax1.set_xlabel('x1')
ax1.set_ylabel('x2')
ax1.set_zlabel('y')
ax1.set_zlim(-10, 6)
ax1.view_init(40, -40)
ax1.set_title('True test y')
ax1.invert_xaxis()
# ====== Predicted Y Scattering ====== #
ax2 = fig.add_subplot(1, 3, 2, projection='3d')
ax2.scatter(test_X[:, 0], test_X[:, 1], pred_y, c=pred_y[:,0], cmap='jet')
ax2.set_xlabel('x1')
ax2.set_ylabel('x2')
ax2.set_zlabel('y')
ax2.set_zlim(-10, 6)
ax2.view_init(40, -40)
ax2.set_title('Predicted test y')
ax2.invert_xaxis()
# ====== Just for Visualizaing with High Resolution ====== #
input_x = torch.Tensor(train_X)
pred_y = model(input_x).detach().numpy()
ax3 = fig.add_subplot(1, 3, 3, projection='3d')
ax3.scatter(train_X[:, 0], train_X[:, 1], pred_y, c=pred_y[:,0], cmap='jet')
ax3.set_xlabel('x1')
ax3.set_ylabel('x2')
ax3.set_zlabel('y')
ax3.set_zlim(-10, 6)
ax3.view_init(40, -40)
ax3.set_title('Predicted train y')
ax3.invert_xaxis()
plt.show()
print(i, loss)
결과 예시는 아래와 같다. 3차원 공간에 true/predicted , test/train , x/y 이렇게 3개 카테고리에 대한 plot이 epoch별로 나오게 됨.
5. Report Experiment
epoch : 학습 횟수
학습 epoch에 따라서 정의한 loss가 얼마나 줄어드는지, 모델 자체를 평가하는 평가 지표(metric)가 있다. 이를 반영해 최종적인 report를 쓰게 되는데, 여기서는 train_loss , val_loss 를 그려보았다.
fig = plt.figure(figsize=(15,5))
# ====== Loss Fluctuation ====== #
ax1 = fig.add_subplot(1, 2, 1)
ax1.plot(list_epoch, list_train_loss, label='train_loss')
ax1.plot(list_epoch, list_val_loss, '--', label='val_loss')
ax1.set_xlabel('epoch')
ax1.set_ylabel('loss')
ax1.set_ylim(0, 5)
ax1.grid()
ax1.legend()
ax1.set_title('epoch vs loss')
# ====== Metric Fluctuation ====== #
ax2 = fig.add_subplot(1, 2, 2)
ax2.plot(list_mae_epoch, list_mae, marker='x', label='mae metric')
ax2.set_xlabel('epoch')
ax2.set_ylabel('mae')
ax2.grid()
ax2.legend()
ax2.set_title('epoch vs mae')
plt.show()
여기까지. 이번 강의는 그리 길지 않았던 듯 !
'Experiences & Study > 딥러닝 홀로서기' 카테고리의 다른 글
[딥러닝 홀로서기] 4.Binary / Multi-Label Classification (0) | 2023.08.31 |
---|---|
[딥러닝 홀로서기] 3. Linear Regression (0) | 2023.08.27 |
[딥러닝 홀로서기] 2. ML Basic (Eng - Kor) (0) | 2023.08.26 |