https://www.kaggle.com/competitions/digit-recognizer/overview
Digit Recognizer | Kaggle
www.kaggle.com
오늘은 캐글의 문제 중 하나인 숫자 데이터셋을 이용하여 숫자를 알아 맞추는 Digit Recognizer를 공부해 보겠습니다.
import pandas as pd
train_df = pd.read_csv('train.csv')
test_df = pd.read_csv('test.csv')
print(train_df.head(3))
print(test_df.head(3))
먼저 훈련셋과 테스트셋 데이터를 임포트 해 줍니다.
x_train = train_df.drop(['label'], axis=1).values
y_train = train_df['label'].values
x_test = test_df.values
print(x_train.shape, y_train.shape, x_test.shape)
이후 훈련 데이터와 테스트 데이터의 특성과 레이블을 추출해 줍니다.
import torch
from torch.utils.data import TensorDataset, DataLoader
train_dataset = TensorDataset(torch.tensor(x_train, dtype=torch.float32), \\
torch.tensor(y_train, dtype=torch.long))
test_datset = TensorDataset(torch.tensor(x_test, dtype=torch.float32))
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_datset, batch_size=64, shuffle=False)
이후 PyTorch를 이용하여 훈련 데이터셋과 테스트 데이터셋을 생성해 줍니다.
batch_size 매개변수는 미니 배치의 크기를 조정하고 shuffle 매개변수는 데이터를 섞을지 여부를 나타냅니다.
보통 훈련 데이터는 섞어주지만 테스트 데이터는 섞지 않습니다.
import torch.nn as nn
# Define the CNN architecture
class DigitRecognizer(nn.Module):
def __init__(self):
super(DigitRecognizer, self).__init__()
self.conv_layers = nn.Sequential(
nn.Conv2d(1, 16, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(16, 32, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
nn.Conv2d(32, 64, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(64, 64, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
)
self.fc_layers = nn.Sequential(
nn.Linear(64 * 7 * 7, 256),
nn.ReLU(inplace=True),
nn.Linear(256, 10),
)
def forward(self, x):
x = self.conv_layers(x)
x = x.view(x.size(0), -1)
x = self.fc_layers(x)
return x
위의 코드는 합성곱 신경망(CNN의 아키텍쳐를 정의하는 부분입니다.
self.conv_layers는 합성곱 레이어들을 순차적으로 쌓은 시퀀셜 레이어입니다. 각 합성곱 레이어는 커널 크기와 패딩이 정의되어 있으며, ReLU활성화 함수가 적요됩니다.
self.fc_layers는 완전 연결 레이어들을 순차적으로 쌓은 시퀀셜 레이어입니다.첫 번째 선형 레이어는 64x7x7 크기의 입력을 받아 256개의 출력을 내고, 두 번째 선형 레이어는 256개의 입력을 받아 10개의 출력을 내며, 이는 클래스의 개수에 해당됩니다.
forward 메서드에서는 입력을 합성곱 레이어를 통과시킨 후 1차원으로 평탄화 하고 완전 연결 레이어를 통과시켜 최종 출력을 반환합니다.
import torch.optim as optim
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(device)
# Create the model
model = DigitRecognizer()
model = model.to(device)
# Define the loss function and optimizer
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
위의 코드는 모델을 생성하고 손실 함수와 옵티마이저를 정의하는 부분입니다.
CUDA가 사용가능한 경우 cuda를 실행하고 아닌경우 cpu를 실행합니다.
손실함수로는 크로스 엔트로피 함수를 사용합니다. 이는 다중 클래스 분류 문제에 주로 사용됩니다.
옵티마이저로는 Adam 옵티마이저를 사용합니다.
# Training loop
num_epochs = 50
losses = []
model.train()
for epoch in range(num_epochs):
running_loss = 0.0
for images, labels in train_loader:
images = images.to(device).view(-1, 1, 28, 28)
labels = labels.to(device)
outputs = model(images)
loss = criterion(outputs, labels)
running_loss += loss.item()
optimizer.zero_grad()
loss.backward()
optimizer.step()
losses.append(running_loss/len(train_loader))
print(f'Epoch {epoch+1}/{num_epochs}, Loss: {running_loss/len(train_loader):.8f}')
위의 코드는 모델을 학습하는 반복문입니다.
먼저 에폭수를 지정하고 주어진 에폭 수 만큼 반복을 지냏ㅇ합니다.
입력 데이터를 모델에 입력하여 예측값을 계산하고 손실 함수를 사용하여 손실을 계산합니다.
이후 에폭별 손실을 누적하고 기울기를 초기화하며 역전파를 수행한 뒤 옵티마이저로 파라미터를 업데이트합니다.
import numpy as np
import matplotlib.pyplot as plt
losses = np.array(losses)
plt.plot(losses)
plt.show()
손실의 변화 시각화 해 보았습니다.
# Inference and save predictions to a CSV file
predictions = []
model.eval()
with torch.no_grad():
for images in test_loader:
images = images[0].to(device).view(-1, 1, 28, 28)
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
predictions.extend(predicted.cpu().numpy())
submission_df = pd.DataFrame({'ImageId': range(1, len(predictions)+1), 'Label': predictions})
submission_df.to_csv('submission.csv', index=False)
이후 제출하기위한 submission.csv를 형식에 맞게 생성한 뒤 제출을 해 줍니다.
'Study > AI' 카테고리의 다른 글
Spaceship Titanic (0) | 2024.04.13 |
---|---|
House Prices - Advanced Regression Techniques (0) | 2024.04.11 |
Titanic Survival Prediction (1) | 2024.04.10 |
넘파이(Numpy) - 비교 연산과 데이터 추출 (0) | 2023.04.09 |
넘파이(Numpy) - 배열 연산 (0) | 2023.04.09 |