728x90
반응형
1. 손글씨 도형
그림판으로 그린 손글씨 이미지 총 300개의 이미지를 다운로드 받습니다.
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
from torch.utils.data import Dataset, DataLoader
import matplotlib.pyplot as plt
%cd /content/drive/MyDrive/본인의 구글드라이브 경로/
!unzip -qq "/content/drive/MyDrive/본인의 구글드라이브 경로/shape.zip"
transform = transforms.Compose([
transforms.Resize((28, 28)),
transforms.Grayscale(1),
transforms.ToTensor(),
transforms.RandomInvert(1), # 이미지를 랜덤하게 반전. 1은 항상 반전
transforms.Normalize((0.5), (0.5))
])
train_path = '/content/drive/MyDrive/본인의 구글드라이브 경로/shape/train'
test_path = '/content/drive/MyDrive/본인의 구글드라이브 경로/shape/test'
trainset = torchvision.datasets.ImageFolder(root= train_path, transform=transform)
testset = torchvision.datasets.ImageFolder(root= test_path, transform=transform)
len(trainset), len(testset)
print(trainset.__getitem__(10))
print(trainset.classes, testset.classes)
class_map = {
0: 'cir',
1: 'tri',
2: 'x'
}
loader = DataLoader(
dataset=trainset,
batch_size=64,
shuffle=True,
)
imgs, labels = next(iter(loader))
print(imgs.shape, labels.shape)
fig, axes = plt.subplots(8, 8, figsize=(16, 16))
for ax, img, label in zip(axes.flatten(), imgs, labels):
ax.imshow(img.reshape(28, 28), cmap='gray')
ax.set_title(class_map[label.item()])
ax.axis('off')
# 장치 확인
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(device)
2. CNN 모델 만들기
class ConvNeuralNetwork(nn.Module):
def __init__(self):
super(ConvNeuralNetwork, self).__init__()
self.flatten = nn.Flatten()
self.classifier = nn.Sequential(
nn.Conv2d(1, 28, kernel_size=3, padding='same'),
nn.ReLU(),
nn.Conv2d(28, 28, kernel_size=3, padding='same'),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2),
nn.Dropout(0.25),
nn.Conv2d(28, 56, kernel_size=3, padding='same'),
nn.ReLU(),
nn.Conv2d(56, 56, kernel_size=3, padding='same'),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2),
nn.Dropout(0.25)
)
self.Linear = nn.Linear(56 * 7 * 7, 3)
def forward(self, x):
x = self.classifier(x)
x = self.flatten(x)
output = self.Linear(x)
return output
model = ConvNeuralNetwork().to(device)
print(model)
loss = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
def train_loop(train_loader, model, loss_fn, optimizer):
sum_losses = 0
sum_accs = 0
for x_batch, y_batch in train_loader:
x_batch = x_batch.to(device)
y_batch = y_batch.to(device)
y_pred = model(x_batch)
loss = loss_fn(y_pred, y_batch)
optimizer.zero_grad()
loss.backward()
optimizer.step()
sum_losses = sum_losses + loss
y_prob = nn.Softmax(1)(y_pred)
y_pred_index = torch.argmax(y_prob, axis=1)
acc = (y_batch == y_pred_index).float().sum() / len(y_batch) * 100
sum_accs = sum_accs + acc
avg_loss = sum_losses / len(train_loader)
avg_acc = sum_accs / len(train_loader)
return avg_loss, avg_acc
epochs = 50
for i in range(epochs):
print(f"------------------------------------------------")
avg_loss, avg_acc = train_loop(loader, model, loss, optimizer)
print(f'Epoch {i:4d}/{epochs} Loss: {avg_loss:.6f} Accuracy: {avg_acc:.2f}%')
print("Done!")
# 테스트 데이터 로드
test_loader = DataLoader(
dataset=testset,
batch_size=32,
shuffle=True
)
imgs, labels = next(iter(test_loader))
fig, axes = plt.subplots(4, 8, figsize=(16, 8))
for ax, img, label in zip(axes.flatten(), imgs, labels):
ax.imshow(img.reshape(28, 28), cmap='gray')
ax.set_title(class_map[label.item()])
ax.axis('off')
def test(model, loader):
model.eval()
sum_accs = 0
img_list = torch.Tensor().to(device)
y_pred_list = torch.Tensor().to(device)
y_true_list = torch.Tensor().to(device)
for x_batch, y_batch in loader:
x_batch = x_batch.to(device)
y_batch = y_batch.to(device)
y_pred = model(x_batch)
y_prob = nn.Softmax(1)(y_pred)
y_pred_index = torch.argmax(y_prob, axis=1)
y_pred_list = torch.cat((y_pred_list, y_pred_index), dim=0)
y_true_list = torch.cat((y_true_list, y_batch), dim=0)
img_list = torch.cat((img_list, x_batch), dim=0)
acc = (y_batch == y_pred_index).float().sum() / len(y_batch) * 100
sum_accs += acc
avg_acc = sum_accs / len(loader)
return y_pred_list, y_true_list, img_list, avg_acc
y_pred_list, y_true_list, img_list, avg_acc = test(model, test_loader)
print(f'테스트 정확도는 {avg_acc:.2f}% 입니다.')
fig, axes = plt.subplots(4, 8, figsize=(16, 8))
img_list_cpu = img_list.cpu()
y_pred_list_cpu = y_pred_list.cpu()
y_true_list_cpu = y_true_list.cpu()
for ax, img, y_pred, y_true in zip(axes.flatten(), img_list_cpu, y_pred_list_cpu, y_true_list_cpu):
ax.imshow(img.reshape(28, 28), cmap='gray')
ax.set_title(f'pred: {class_map[y_pred.item()]}, true: {class_map[y_true.item()]}')
ax.axis('off')
plt.show()
3. 모델 저장하고 불러오기
# 모델의 가중치와 매개변수만 저장
# 모델의 구조가 저장되지 않으므로 모델 클래스 정의가 없으면 복원할 수 없음
torch.save(model.state_dict(), 'model_weights.pth')
model2 = ConvNeuralNetwork().to(device)
print(model2)
y_pred_list, y_true_list, img_list, avg_acc = test(model2, test_loader)
print(f'테스트 정확도는 {avg_acc:.2f}% 입니다.')
model2.load_state_dict(torch.load('model_weights.pth'))
y_pred_list, y_true_list, img_list, avg_acc = test(model2)
print(f'테스트 정확도는 {avg_acc:.2f}% 입니다.')
# 모델 전체를 저장
# 모델 클래스와 가중치가 함께 저장되므로, 복원 시 모델 구조를 별도로 정의할 필요 없음
torch.save(model, 'model.pth')
model3 = torch.load('model.pth')
y_pred_list, y_true_list, img_list, avg_acc = test(model3)
print(f'테스트 정확도는 {avg_acc:.2f}% 입니다.')
728x90
반응형
'인공지능 > 딥러닝' 카테고리의 다른 글
Alexnet 구현하기 (0) | 2025.01.17 |
---|---|
손글씨 도형 분류 FastAPI로 서빙 (1) | 2025.01.16 |
CNN (2) | 2025.01.14 |
Multi-class Weather Dataset (0) | 2025.01.13 |
딥러닝: 퍼셉트론과 다층 퍼셉트론 (0) | 2025.01.13 |