✓ pytorch 에서는 Train 과 Validation 과정을 코드를 통해 수행한다.
✓ 이를 위해 스크래치 코드를 작성해보았다. (분류 문제임)
✓ 회귀는 train에서 loss, accuracy 처리법이 상이함.
❏ 분류 문제 Train, Evaluation 함수
→ 주의사항. 분류문제에서 cross entropy를 계산을 위해서는 y값이 LongTensor 여야 함.
(Float으로 했다가 고생했던 기억이.. 까먹지 말자)
→ 유용한 팁. 만약 학습이 잘되는지 확인을 하고싶다면 tqdm을 사용하면 최소 2번이상은 되어야 학습이 잘되는지 loss값 감소를 통해 확인 할 수 있다. (물론 wandb 사용 안할때) 초반에 학습이 잘되는지 확인하고 싶다면 아래코드에서 tqdm을 빼버리고 주석처리된 부분을 살리면, 설정한 log_interval 간격으로 배치 사이즈 마다 출력이 실시간으로 출력된다. 그렇다보니. 미니배치 마다 loss값이 줄어들고 있다면 알맞게 코드를 작성했다고 1epoch가 끝나기 전에 확인이 가능하다.
(Figure 1. 아래 코드를 그대로 실행시 나오는 화면. )
(Figure 2 . tqdm을 제거하고, 주석처리된 부분을 살렸을때 출력되는 모습)
## 분류 문제 Train, Evaluation 함수
from tqdm import tqdm
# 에폭마다 손실과 정확도를 저장할 리스트
training_loss_hist = [] # tuple() 로 해도됨
training_acc_hist = []
def train(model_name, train_loader,device,optimizer,loss_func,log_interval=10):
Train_total_loss=0
Train_correct_predictions=0
# train mode로 설정
model_name.train()
for batch_idx,(x_train, y_train) in enumerate(tqdm(train_loader)):
# cross entropy의 y는 LongTensor형이어야 함.
y_train=y_train.type(torch.LongTensor)
x_train=x_train.to(device)
y_train=y_train.to(device)
y_predict=model_name(x_train)
# loss 계산
loss=loss_func(y_predict,y_train.squeeze(dim=-1))
Train_total_loss+=loss.item()
# 정확도 계산
values, indices = torch.max(y_predict.data, dim=1,keepdim=True)
Train_correct_predictions += (indices == y_train).sum().item() # 정확하게 분류한 샘플 수
# 그라디언트 0으로 설정후 -> 파라미터 업데이트
optimizer.zero_grad()
loss.backward()
optimizer.step()
# 한 epoch에서 'log_interval'번의 미니배치마다 loss 출력
# if batch_idx % log_interval==0:
# print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
# 1+epoch,batch_idx*len(x_train),len(train_dataloader.dataset),
# 100.*batch_idx/len(train_dataloader.dataset),loss.item()
# ))
avg_train_loss=Train_total_loss/len(train_loader)
Train_accuracy = 100. * Train_correct_predictions / len(train_loader.dataset)
print('Train Epoch: {} Average loss: {:.6f}, Accuracy: {:.2f}%'
.format(1+epoch, avg_train_loss, Train_accuracy))
# 학습데이터에서 loss, accuracy 저장
training_loss_hist.append(avg_train_loss)
training_acc_hist.append(Train_accuracy)
val_loss_hist = []
val_acc_hist = []
def evaluate(model_name,test_loader,device,loss_func):
correct=0
val_loss=0
# evaluation mode로 설정
model_name.eval()
with torch.no_grad():
for idx,(x_test,y_test) in enumerate(tqdm(test_loader)):
y_test=y_test.type(torch.LongTensor)
x_test=x_test.to(device)
y_test=y_test.to(device) # torch.Size([64, 1])
y_pred=model_name(x_test)
loss=loss_func(y_pred,y_test.squeeze(dim=-1)).item()
val_loss+=loss
# 정확하게 분류한 샘플 수 계산
values, indices = torch.max(y_pred.data, dim=1,keepdim=True)
correct += (indices == y_test).sum().item()
avg_val_loss=val_loss/len(test_loader)
accuracy = 100 * correct / len(test_loader.dataset) # 정확도 계산
print('Validation set: Average loss: {:.4f}, Accuracy: {:.2f}%'
.format(avg_val_loss, accuracy))
print()
# 검증데이터에서 loss, accuracy 저장
val_loss_hist.append(avg_val_loss)
val_acc_hist.append(accuracy)


❏ 코드 적용 예시.
→ 위에 코드에서 연결됨.
device = torch.device('cuda:2')
# 모델 호출
CNN_LSTM_model=CNN_LSTM(
input_size=99,
output_size=64,
units=32).to(device)
# optimizer 설정
optimizer = optim.Adam(CNN_LSTM_model.parameters(), lr=0.0001)
# loss 함수
criterion = nn.CrossEntropyLoss()
# epoch 설정
epochs = 5
for epoch in range(epochs):
train(
model_name=CNN_LSTM_model,
train_loader=train_dataloader,
optimizer=optimizer,
loss_func=criterion,
log_interval=1,
device=device,)
evaluate(
model_name=CNN_LSTM_model,
test_loader=val_dataloader,
loss_func=criterion,
device=device)
❏ Train, Evaluation plot 출력.
→ 꿀팁 : 범례의 위치를 알아서 최적으로 설정하려면 loc='best' 하면됨.. (처음알았음...)
→ 결과 : figure3,4 참고
import matplotlib.pyplot as plt
# Accuracy history
plt.plot(training_acc_hist)
plt.plot(val_acc_hist)
plt.title("Model Accuracy")
plt.ylabel("Accuracy")
plt.xlabel("Epochs")
plt.legend(["Train", "Validation"], loc="best")
plt.grid()
plt.show()
# loss history
plt.plot(training_loss_hist)
plt.plot(val_loss_hist)
plt.title("Model Loss")
plt.ylabel("Loss")
plt.xlabel("Epochs")
plt.legend(["Train", "Validation"], loc="best")
plt.grid()
plt.show()


'인공지능 (기본 딥러닝) > 딥러닝 스크래치 코드' 카테고리의 다른 글
[Pytorch 스크래치 코드] Evaluation 코드 (0) | 2023.12.28 |
---|---|
[Pytorch 스크래치 코드] 회귀문제 Train, Validation 함수 (1) | 2023.12.17 |
[Pytorch 스크래치 코드] Train Test split (1) | 2023.12.10 |
[Pytorch 스크래치 코드] 실험 재현을 위한 Seed 고정 (0) | 2023.12.09 |
[Pytorch 스크래치 코드] Early Stopping (0) | 2023.12.09 |