인공지능/공부

딥러닝 과제 1 - 순방향 신경망 약물 안전성 예측 pytorch

이게될까 2024. 4. 3. 23:47
728x90
728x90
import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import torch.nn.init as init


def load_data(filename):
    data = np.loadtxt(filename, delimiter=',', dtype=np.float32)
    x = data[:, 0:-2]
    y = data[:, [-1]]  # after 3 months (-2) and 6 months (-1) 
    return torch.tensor(x, dtype=torch.float32), torch.tensor(y, dtype=torch.float32)

이번에는 함수로 해서 model을 만들어서 한번 잘게 잘게 보겠습니다.

저는 함수형은 처음이네요

class FNN(nn.Module):
    def __init__(self, input_size, hidden_size, output_size):
        super(FNN, self).__init__()
        self.layer1 = nn.Sequential(
            nn.Linear(input_size, hidden_size),
            nn.BatchNorm1d(hidden_size),  # 배치 정규화 추가
            nn.Sigmoid(),
            nn.Dropout(0.3))
        self.layer2 = nn.Sequential(
            nn.Linear(hidden_size, hidden_size),
            nn.BatchNorm1d(hidden_size),  # 배치 정규화 추가
            nn.Sigmoid(),
            nn.Dropout(0.3))
        
        self.layer3 = nn.Sequential(
            nn.Linear(hidden_size, hidden_size),
            nn.BatchNorm1d(hidden_size),  # 배치 정규화 추가
            nn.Sigmoid(),
            nn.Dropout(0.3))
        self.layer4 = nn.Sequential(
            nn.Linear(hidden_size, hidden_size),
            nn.BatchNorm1d(hidden_size),  # 배치 정규화 추가
            nn.Sigmoid(),
            nn.Dropout(0.3))
        self.layer5 = nn.Sequential(
            nn.Linear(hidden_size, hidden_size),
            nn.BatchNorm1d(hidden_size),  # 배치 정규화 추가
            nn.Sigmoid(),
            nn.Dropout(0.3))
        
        self.layer6 = nn.Sequential(nn.Linear(hidden_size, output_size),
            nn.BatchNorm1d(output_size),  # 배치 정규화 추가
            nn.Sigmoid())

    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        x = self.layer5(x)
        x = self.layer6(x)

        return x

배치 정규화도 추가해서 제발 잘 되길 빌었습니다......

데이터의 양이 적어서 오버피팅이 쉽게 해결되지 않더라고요,,

x_train, y_train= load_data('hw1_training_dataset.csv')
x_val = x_train[:18,:]
y_val = y_train[:18,:]
x_train= x_train[18:,:]
y_train = y_train[18:,:]
x_test, y_test= load_data('hw1_test_dataset.csv')
model = FNN(input_size=15, hidden_size=80, output_size=1)
criterion = nn.BCELoss()
optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-3)# weight_decay가 L2 정규화를 의미
best_val_loss = float('inf')

데이터를 불러와서 validation과 train 데이터를 나눠줬습니다.

그리고 이전에 class를 불러와서 model을 정의해주고 lossfunction, optimizer를 결정해줍니다.

모델 저장을 위해 loss도 무한으로 지정해줍니다.

num_epochs= 20001
loss_graph=[]
val_loss=[]
for epoch in range(num_epochs):
    model.train()  # 훈련 모드 설정
    outputs = model(x_train)
    loss = criterion(outputs, y_train)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    train_loss = loss.item()
    
    model.eval()  # 평가 모드 설정
    with torch.no_grad():
        loss = criterion(model(x_val),y_val)
        total_val_loss = loss.item()

    if epoch % 10 == 0:
        loss_graph.append(train_loss)
        val_loss.append(total_val_loss)

    if epoch % 200 == 0:
        print(f'Epoch[{epoch}/{num_epochs}], Loss: {train_loss:.4f}, Val_Loss: {total_val_loss:.4f}')
    if total_val_loss < best_val_loss:
        best_val_loss = total_val_loss
        torch.save(model.state_dict(), 'best_model.pth')
        #print(f'upload complete : best_loss: {best_val_loss}')
        
with torch.no_grad():
    train_accuracy= (model(x_train).gt(0.5).float() == y_train).float().mean().item()
    test_accuracy= (model(x_test).gt(0.5).float() == y_test).float().mean().item()
print(f'\nTrainAccuracy: {train_accuracy:.4f}')
print(f'TestAccuracy: {test_accuracy:.4f}')

validation을 위한 평가모드, 학습모드 둘 다 있고, 모델 저장하는 부분까지 있스비낟.

import matplotlib.pyplot as plt

plt.figure()
plt.plot( loss_graph, label='Training loss')
plt.plot( val_loss, label='Validation loss')
plt.title('Training and Validation Loss')

plt.xlabel('Number of iterations')
plt.ylabel('loss_graph')
plt.legend()

plt.show()

그래프는 이렇게 됩니다.

model.load_state_dict(torch.load('best_model.pth'))

모델 불러오기

with torch.no_grad():
    train_accuracy= (model(x_train).gt(0.5).float() == y_train).float().mean().item()
    test_accuracy= (model(x_test).gt(0.5).float() == y_test).float().mean().item()
print(f'\nTrainAccuracy: {train_accuracy:.4f}')
print(f'TestAccuracy: {test_accuracy:.4f}')

불러온 모델 평가!

728x90