본문 바로가기
AI/AI 부트캠프

[AI 부트캠프] DAY 81 - 딥러닝 프로젝트 6

by HOHHOH 2023. 11. 15.

[오늘의 일지]

딥러닝 프로젝트 - 베이스라인 코드 수정

[상세 내용]

베이스라인 코드 수정

LSTM

- 강사님께서 제시해 준 LSTM의 베이스라인 코드에서 몇 가지 수정할 부분이 있었고 또 기능적인 측면에서 추가해면 좋을 거 같은 것들이 있었습니다. 우선 강사님의 코드에서는 모델을 학습을 시킬 때 for문에서 미니배치를 통해 분리된 데이터들이 각각의 학습을 진행한 후에 각 배치마다 loss 값이 나오는데 마지막 배치의 loss값만 출력되는 것 같았습니다. 원래의 loss값은 하나의 루프의 로스 값을 모두 더해서 배치 사이즈로 나눠줘야만 loss값의 평균을 출력하는 게 정상입니다. 그래서 코드를 모두 수정했습니다. 그리고 기존 코드에서는 학습만 할 수 있게 되어있었는데 학습 후에 test를 거쳐서 한 번 더 성능을 파악했습니다. 그리고 loss값이 정체되었을 때를 가정하여 얼리 스탑핑 기능도 추가했고 또 성능이 머무른다고 판단될 때에 러닝레이트를 줄여주는 기능까지 추가했습니다. 그리고 데이터 전처리 부분에서 정규화를 시켜주는 과정도 했습니다. 그런데 아직 캐글에서 제출하는 부분은 해결하지 못했습니다.

# 정규화

x_cols = [c for c in data_interpolated.columns if c not in ['row_id', 'time_id', 'date_id', 'target']]
y_cols = ["target"]

means = data_interpolated[x_cols].mean(0)
stds = data_interpolated[x_cols].std(0)

def normalize_features(x):
    return (x - means) / (stds+1e-8)
    
def get_xy(df):
    x = df[x_cols]
    x = normalize_features(x)

    y = df[y_cols]

    return x.values, y.values

# 데이터 분리 로드(train, test)

def get_dataloaders(df, batch_size=512):
    (x,y) = get_xy(df)

    x_tensor = torch.Tensor(x).to(device)
    y_tensor = torch.Tensor(y).to(device)

    full_dataset = TensorDataset(x_tensor, y_tensor)
    train_dataset, test_dataset = random_split(full_dataset, [0.8,0.2])

    train_dataloader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, drop_last=True)
    test_dataloader = DataLoader(test_dataset, batch_size=min(batch_size*4, len(test_dataset)), drop_last=True)
    return (train_dataloader, test_dataloader)

# early stopping 추가

class EarlyStopper:
    def __init__(self, patience=5, min_delta=0.00001):
        self.best_model = None
        self.patience = patience
        self.min_delta = min_delta
        self.counter = 0
        self.min_validation_loss = float('inf')

    def get_best_model(self):
        return self.best_model

    def early_stop(self, validation_loss, model):
        if validation_loss < self.min_validation_loss:
            print(f"New best loss: {validation_loss:>.4f}")
            self.min_validation_loss = validation_loss
            self.counter = 0
            self.best_model = model
        elif validation_loss > (self.min_validation_loss + self.min_delta):
            self.counter += 1
            if self.counter >= self.patience:
                return True
        return False
        
# 최종 모델 학습

# Move the model to GPU
model = model.to(device)

# Loss and optimizer
criterion = nn.L1Loss()
optimizer = torch.optim.AdamW(model.parameters(), lr=0.0001, weight_decay=0.00001)
early_stopper = EarlyStopper(patience=5, min_delta=0.00001)
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', patience=5, factor=0.5, verbose=True)

# Training loop
num_epochs = 1000
for epoch in range(num_epochs):
    model.train() 
    train_loss = 0
    for X, y in tqdm(train_dataloader):
        # Reshape the data for LSTM (batch_size, sequence_length, input_size)
        X = X.unsqueeze(1).to(device)
        y = y.to(device)

        # Forward pass
        outputs = model(X)
        loss = criterion(outputs, y)
        train_loss += loss.item()

        # Backward pass and optimization
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

    model.eval()
    test_loss = 0
    with torch.no_grad():
        for X, y in test_dataloader:
            X, y = X.unsqueeze(1).to(device), y.to(device)  # Reshape test data
            pred = model(X)
            test_loss += criterion(pred, y).item()  

    train_loss /= len(train_dataloader)
    test_loss /= len(test_dataloader) 

    print(f"Epoch [{epoch+1}/{num_epochs}], Train_Loss: {train_loss:>.5f}, Test_Loss: {test_loss:>.5f}")   

    scheduler.step(test_loss)
    # early stopper
    if early_stopper.early_stop(test_loss, model):
        print("Early stopping triggered.")
        break

print("Training finished.")

 

 

[마무리]

 오늘은 LSTM 모델의 코드를 수정해서 학습이 가능하도록 했습니다. 다른 부분은 다 괜찮았는데 캐글에서 제출을 위한 코드를 짜는 것이 생각보다 어려웠던 거 같습니다. 이제 내일은 아마도 DNN을 위한 코드를 분석해 보고 수정하는 과정을 통해서 학습 효과를 올릴 수 있도록 노력해봐야 할 거 같습니다.

반응형

댓글