본문 바로가기
개인 프로젝트/대학원 수업 정리

[CV] 과제3_문제2

by 응_비 2025. 11. 20.

import torch
import torch.nn as nn
from torch.utils.data import DataLoader
from torch.utils.data.dataset import Subset
from torchvision.datasets import ImageFolder, utils
from torchvision.transforms import transforms
from sklearn.metrics import accuracy_score, confusion_matrix
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt


#EuroSAT 데이터셋 다운로드 코드
def get_EuroSAT(dirname):
    import os
    if os.path.exists(dirname):
        print("Dataset is already exist.")
        return os.path.join(dirname, '2750')

    os.makedirs(dirname, exist_ok=True)
    utils.download_and_extract_archive(
        "http://madm.dfki.de/files/sentinel/EuroSAT.zip",
        download_root=dirname,
        md5="c8fa014336c82ac7804f0398fcb19387",
        remove_finished=True,
    )
    return os.path.join(dirname, '2750')


# GPU/CPU 설정
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(device)

# 데이터 전처리 및 로드
transform = transforms.Compose([
    transforms.Resize((32, 32)),
    transforms.RandomHorizontalFlip(),
    transforms.ColorJitter(brightness=0.1, contrast=0.1),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])
])

dataset = ImageFolder(get_EuroSAT('EuroSAT'), transform=transform)

# 데이터셋 분할
dataset_size = len(dataset)
print('Dataset size:', dataset_size)

indices = list(range(dataset_size))
np.random.shuffle(indices)

split1 = int(np.floor(0.7 * dataset_size))
split2 = int(np.floor(0.85 * dataset_size))

train_indices = indices[:split1]
val_indices = indices[split1:split2]
test_indices = indices[split2:]

train_dataset = Subset(dataset, train_indices)
val_dataset = Subset(dataset, val_indices)
test_dataset = Subset(dataset, test_indices)

train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=64, shuffle=False)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)

print('Train loader size:', len(train_loader.dataset))
print('Val loader size:', len(val_loader.dataset))
print('Test loader size:', len(test_loader.dataset))


# MLP 정의
class MLP(nn.Module):
    def __init__(self):
        super(MLP, self).__init__()
        self.layers = nn.Sequential(
            nn.Linear(3*32*32, 1024),
            nn.ReLU(),
            nn.Dropout(0.3),
            nn.Linear(1024, 256),
            nn.ReLU(),
            nn.Linear(256, 10)
        )

    def forward(self, x):
        x = x.view(x.size(0), -1)
        x = self.layers(x)
        return x


# CNN 정의
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.features = nn.Sequential(
            nn.Conv2d(3, 32, kernel_size=3, padding=1),
            nn.BatchNorm2d(32),
            nn.ReLU(),
            nn.MaxPool2d(2, 2),

            nn.Conv2d(32, 64, kernel_size=3, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(),
            nn.MaxPool2d(2, 2),
        )

        self.classifier = nn.Sequential(
            nn.Flatten(),
            nn.Linear(64 * 8 * 8, 256),
            nn.ReLU(),
            nn.Dropout(0.4),
            nn.Linear(256, 10)
        )

    def forward(self, x):
        x = self.features(x)
        x = self.classifier(x)
        return x


# 모델 선택
model = CNN().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)


# 학습 함수
def train(model, train_loader, optimizer, criterion):
    model.train()
    running_loss = 0.0
    for inputs, labels in train_loader:
        inputs, labels = inputs.to(device), labels.to(device)

        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

        running_loss += loss.item() * inputs.size(0)

    return running_loss / len(train_loader.dataset)


# 검증 함수
def validate(model, loader, criterion):
    model.eval()
    total_loss = 0.0
    preds, trues = [], []

    with torch.no_grad():
        for inputs, labels in loader:
            inputs, labels = inputs.to(device), labels.to(device)
            outputs = model(inputs)
            loss = criterion(outputs, labels)

            total_loss += loss.item() * inputs.size(0)
            _, predicted = torch.max(outputs, 1)

            preds.extend(predicted.cpu().numpy())
            trues.extend(labels.cpu().numpy())

    acc = accuracy_score(trues, preds)
    cm = confusion_matrix(trues, preds)
    return total_loss / len(loader.dataset), acc, cm


# 학습 실행
num_epochs = 100
for epoch in range(num_epochs):
    train_loss = train(model, train_loader, optimizer, criterion)
    val_loss, val_acc, _ = validate(model, val_loader, criterion)
    print(f"Iter {epoch+1}/{num_epochs} | Train Loss: {train_loss:.4f}, Val Loss: {val_loss:.4f}, Val Acc: {val_acc:.4f}")


# 테스트 평가
test_loss, test_acc, test_cm = validate(model, test_loader, criterion)
print(f"\nTest Accuracy: {test_acc:.4f}")


# Confusion Matrix 시각화 (파일 저장 + 화면 출력)
plt.figure(figsize=(8,8))
sns.heatmap(test_cm, annot=True, fmt="d", cmap="Blues")
plt.title("EuroSAT Test Confusion Matrix (CNN)")
plt.xlabel("Predicted")
plt.ylabel("True")
plt.savefig("EuroSAT_confusion_matrix.png")
plt.show()
plt.clf()

1. 2-1. EuroSAT 전처리 요구사항 vs 지금 코드

문제 요구사항

  1. EuroSAT 데이터셋 불러오기
  2. 각 클래스 이미지 확인
  3. 32×32로 변형
  4. train/val/test 분할 후 각 크기 출력

네 코드

dataset = ImageFolder(get_EuroSAT('EuroSAT'), transform=transform)

dataset_size = len(dataset)
indices = list(range(dataset_size))

split1 = int(np.floor(0.7 * dataset_size))
split2 = int(np.floor(0.85 * dataset_size))

np.random.shuffle(indices)
train_indices, val_indices, test_indices = indices[:split1], indices[split1:split2], indices[split2:]

train_dataset = Subset(dataset, train_indices)
val_dataset = Subset(dataset, val_indices)
test_dataset = Subset(dataset, test_indices)

print('Train loader size:', len(train_loader.dataset))
print('Val loader size:', len(val_loader.dataset))
print('Test loader size:', len(test_loader.dataset))
  • ✅ EuroSAT 로드
  • ✅ Resize(32, 32) 포함
  • ✅ train/val/test 분할 + 크기 출력
  • ✅ augmentation까지 사용(RandomHorizontalFlip, ColorJitter) → 리포트에 이유만 적어주면 됨.

딱 하나 더 하면 좋은 것:
“각 클래스의 이미지를 확인”하는 코드가 리포트에 들어가면 좋아.

예를 들어:

import matplotlib.pyplot as plt

class_names = dataset.classes
print("Classes:", class_names)

# 클래스당 1장씩 샘플 보기
fig, axes = plt.subplots(2, 5, figsize=(12, 5))
axes = axes.flatten()

for cls_idx, cls_name in enumerate(class_names):
    # 해당 클래스 인덱스 중 첫 번째 이미지
    for i, (img, label) in enumerate(dataset):
        if label == cls_idx:
            axes[cls_idx].imshow(img.permute(1, 2, 0) * 0.5 + 0.5)  # Normalize 복원
            axes[cls_idx].set_title(cls_name)
            axes[cls_idx].axis("off")
            break

plt.tight_layout()
plt.savefig("EuroSAT_class_samples.png")
plt.close()

2. 2-2. MLP 구현 – 요건 체크

요구사항

  • nn.Linear를 사용한 3개 이상 layer
  • 출력 차원 = 클래스 개수 (EuroSAT = 10)

네 코드

class MLP(nn.Module):
    def __init__(self):
        super(MLP, self).__init__()

        self.layers = nn.Sequential(
            nn.Linear(3*32*32, 1024),
            nn.ReLU(),
            nn.Dropout(0.3),
            nn.Linear(1024, 256),
            nn.ReLU(),
            nn.Linear(256, 10)
        )
        self.activation = nn.Softmax(dim=1)  # 출력을 확률로 변환 (분석용)
  • ✅ Linear layer 3개 (input→1024, 1024→256, 256→10)
  • ✅ 중간에 ReLU, Dropout도 있어서 구조 좋음
  • ✅ 출력 10차원이라 EuroSAT(10 클래스)와도 일치

조금 더 깔끔하게 추천하는 수정

  1. 클래스 수를 하드코딩하지 말고, 데이터셋에서 자동으로 가져오기
num_classes = len(dataset.classes)

class MLP(nn.Module):
    def __init__(self, num_classes):
        super(MLP, self).__init__()
        self.layers = nn.Sequential(
            nn.Linear(3*32*32, 1024),
            nn.ReLU(),
            nn.Dropout(0.3),
            nn.Linear(1024, 256),
            nn.ReLU(),
            nn.Linear(256, num_classes)
        )

    def forward(self, x):
        x = x.view(x.size(0), -1)
        x = self.layers(x)
        return x

# 사용시
mlp_model = MLP(num_classes).to(device)

 

2. self.activation = nn.Softmax(dim=1)는 CrossEntropyLoss 쓸 때는 안 쓰는 게 맞으니

  • 그냥 제거하거나
  • “분석 시 따로 softmax 씌운다” 정도로 리포트에만 언급하면 충분해.

3. 2-3. CNN 구현 – 요건 체크

요구사항

  • nn.Conv2d를 사용한 2개 이상 layer
  • 사전 구현 pretrained resnet은 사용 금지 (넌 안 쓰고 있어서 괜찮음)

네 코드

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()

        self.features = nn.Sequential(
            nn.Conv2d(3, 32, kernel_size=3, padding=1),
            nn.BatchNorm2d(32),
            nn.ReLU(),
            nn.MaxPool2d(2, 2),     # 32x32 → 16x16

            nn.Conv2d(32, 64, kernel_size=3, padding=1),
            nn.BatchNorm2d(64),
            nn.ReLU(),
            nn.MaxPool2d(2, 2),     # 16x16 → 8x8
        )

        self.classifier = nn.Sequential(
            nn.Flatten(),
            nn.Linear(64*8*8, 256),
            nn.ReLU(),
            nn.Dropout(0.4),
            nn.Linear(256, 10)
        )
  • ✅ Conv layer 2개 사용
  • ✅ MaxPool로 공간 차원 줄이기
  • ✅ FC + Dropout 구조
  • 구조도 과제 조건에 충분히 맞음.

여기도 10 대신 num_classes 사용하면 더 일반적인 코드가 됨.

 

class CNN(nn.Module):
    def __init__(self, num_classes):
        super(CNN, self).__init__()
        self.features = ...
        self.classifier = nn.Sequential(
            nn.Flatten(),
            nn.Linear(64*8*8, 256),
            nn.ReLU(),
            nn.Dropout(0.4),
            nn.Linear(256, num_classes)
        )

4. 2-4. 결과 분석 – 지금 상태 vs 채워야 할 부분

요구사항 요약

  1. 두 모델(MLP, CNN)에 대해
    • Train Accuracy
    • Test Accuracy
    • Confusion Matrix
  2. epoch, learning rate, augmentation 변경 등 실험을 통해
    • 성능 개선 시도
    • “왜 이 모델이 더 좋았는지” 글로 분석

네 코드 현재 상태

def validate(model, data_loader, criterion):
    ...
    val_accuracy = accuracy_score(all_labels, all_predictions)
    val_confusion_matrix = confusion_matrix(all_labels, all_predictions)
    return val_loss, val_accuracy, val_confusion_matrix
  • ✅ accuracy, confusion matrix 계산 함수 완성
  • ✅ test set 에 대해:
test_loss, test_accuracy, test_confusion_matrix = validate(model, test_loader, criterion)
print(f"Test Accuracy: {test_accuracy:.4f}")
...
sns.heatmap(test_confusion_matrix, ...)

CNN 하나에 대해서는 2-4의 절반 정도는 이미 충족하고 있어.

4-1. MLP도 같은 방식으로 학습/평가하기

과제에서 “두 모델을 비교”하라고 했으므로,
지금 구조에서 MLP 한 번, CNN 한 번 이렇게 돌려서 결과를 모아야 해.

예를 들어 이렇게 공통 함수를 하나 두고:

def run_experiment(model, train_loader, test_loader, num_epochs=50, lr=0.001, weight_decay=1e-4):
    model = model.to(device)
    criterion = nn.CrossEntropyLoss()
    optimizer = torch.optim.Adam(model.parameters(), lr=lr, weight_decay=weight_decay)

    for epoch in range(num_epochs):
        train_loss = train(model, train_loader, optimizer, criterion)
        test_loss, test_acc, _ = validate(model, test_loader, criterion)
        print(f"[{model.__class__.__name__}] Epoch {epoch+1}/{num_epochs} | "
              f"Train Loss: {train_loss:.4f} | Test Loss: {test_loss:.4f} | Test Acc: {test_acc:.4f}")

    train_loss, train_acc, train_cm = validate(model, train_loader, criterion)
    test_loss, test_acc, test_cm = validate(model, test_loader, criterion)

    print(f"[{model.__class__.__name__}] FINAL | "
          f"Train Acc: {train_acc:.4f} | Test Acc: {test_acc:.4f}")

    return {
        "model": model,
        "train_acc": train_acc,
        "test_acc": test_acc,
        "train_cm": train_cm,
        "test_cm": test_cm,
    }

num_classes = len(dataset.classes)

mlp_result = run_experiment(MLP(num_classes), train_loader, test_loader,
                            num_epochs=50, lr=0.001)
cnn_result = run_experiment(CNN(num_classes), train_loader, test_loader,
                            num_epochs=50, lr=0.001)

이렇게 하면:

  • mlp_result["train_acc"], mlp_result["test_acc"]
  • cnn_result["train_acc"], cnn_result["test_acc"]
  • mlp_result["test_cm"], cnn_result["test_cm"]

을 표/그림으로 리포트에 정리하면 된다.

만약 교수님이 “Validation도 나눠라”라고 강조하셨으면, 위 함수에서 train/val/test 세 개 다 평가해도 됨.
(지금 네 코드처럼 train/val/test 셋 다 분리해 두었으니까 그대로 써도 상관없고.)


4-2. Confusion Matrix 시각화 (두 모델)

이미 CNN용으로는 heatmap을 만들었으니, MLP에도 같은 코드 쓰면 돼.

import matplotlib.pyplot as plt

class_names = dataset.classes

def plot_confusion_matrix(cm, class_names, title, filename):
    hm = sns.heatmap(cm, annot=True, fmt="d", cmap="Blues",
                     xticklabels=class_names, yticklabels=class_names)
    hm.set_xlabel("Predicted")
    hm.set_ylabel("True")
    hm.set_title(title)
    hm.figure.savefig(filename)
    hm.figure.clf()

plot_confusion_matrix(mlp_result["test_cm"], class_names,
                      "EuroSAT Test Confusion Matrix - MLP",
                      "EuroSAT_confusion_matrix_MLP.png")

plot_confusion_matrix(cnn_result["test_cm"], class_names,
                      "EuroSAT Test Confusion Matrix - CNN",
                      "EuroSAT_confusion_matrix_CNN.png")

 

이 두 이미지를 리포트에 나란히 놓고,
“어떤 클래스가 어디에서 더 헷갈리는지” 비교해서 설명해주면 돼.


4-3. epoch / lr / augmentation 변경 실험 아이디어

리포트에서 쓰기 좋은 실험 조합 예시:

  1. 기본 설정
    • epoch: 50
    • lr: 0.001
    • augmentation: RandomHorizontalFlip + ColorJitter
  2. 실험 A: augmentation 제거
    • 같은 epoch, lr에서 augmentation 없이 학습
    • 결과: train acc ↑, test acc ↓라면 → 과적합 설명하기 좋음
  3. 실험 B: epoch 증가
    • epoch: 100
    • test acc 변화 비교 → 수렴/과적합 여부 분석
  4. 실험 C: learning rate 변화
    • lr: 0.0005 vs 0.001 비교
    • 수렴 속도, 최종 acc 비교

이 중 2~3개만 골라서 표로 정리해도 충분해.

리포트 문장 예시(대략적인 틀):

MLP와 CNN 모두 Adam(learning rate = 0.001, weight decay = 1e-4)을 사용하여 50 epoch 동안 학습하였다.
Augmentation을 적용하지 않은 경우 Train Accuracy는 증가했지만 Test Accuracy가 감소하여 과적합 경향을 보였다. 반면, RandomHorizontalFlip과 ColorJitter를 적용한 경우 Test Accuracy가 개선되었으며, 특히 CNN 모델에서 향상이 더 두드러졌다. 이는 CNN이 공간적 패턴을 더 잘 학습하는 특성상, 다양한 시각적 변형을 통해 일반화 성능이 향상된 것으로 해석할 수 있다.


4-4. “왜 CNN이 더 좋은지” 분석 포인트

실제 성능이 어떻게 나올지에 따라 내용은 조금 달라지겠지만, 보통:

  • CNN Test Acc > MLP Test Acc일 가능성이 크니까, 이런 식으로 써주면 좋아:
  1. 공간 구조 학습
    • MLP: 입력을 1D로 flatten해서 픽셀 간 공간 구조 정보 손실
    • CNN: convolution + pooling으로 **지역적인 특징(패턴, 텍스처)**를 활용
  2. 파라미터 효율성
    • 같은 수준의 표현력을 얻기 위해 MLP는 매우 많은 linear weight 필요
    • CNN은 공유된 필터로 파라미터 수를 줄이면서도 복잡한 패턴 학습 가능
  3. Confusion Matrix 기반 해석
    • 예: MLP는 특정 비슷한 토지 클래스끼리 자주 헷갈리는데, CNN에서는 혼동이 줄어든 경우
    • “식생 패턴이나 토양 텍스처 등 지역적 패턴 차이를 CNN이 더 잘 포착한다”라고 연결
cpu
100%|██████████| 94.3M/94.3M [00:13<00:00, 7.18MB/s]
Dataset size: 27000
Train loader size: 18900
Val loader size: 4050
Test loader size: 4050
Iter 1/100 | Train Loss: 1.1574, Val Loss: 1.3121, Val Acc: 0.5916
Iter 2/100 | Train Loss: 0.8618, Val Loss: 0.7891, Val Acc: 0.7210
Iter 3/100 | Train Loss: 0.7659, Val Loss: 0.8980, Val Acc: 0.6909
Iter 4/100 | Train Loss: 0.7183, Val Loss: 0.6236, Val Acc: 0.7664
Iter 5/100 | Train Loss: 0.6573, Val Loss: 0.5613, Val Acc: 0.8074
Iter 6/100 | Train Loss: 0.6239, Val Loss: 0.6951, Val Acc: 0.7647
Iter 7/100 | Train Loss: 0.5874, Val Loss: 0.6233, Val Acc: 0.7654
Iter 8/100 | Train Loss: 0.5630, Val Loss: 0.5001, Val Acc: 0.8222
Iter 9/100 | Train Loss: 0.5278, Val Loss: 0.4473, Val Acc: 0.8417
Iter 10/100 | Train Loss: 0.5081, Val Loss: 0.4830, Val Acc: 0.8249
Iter 11/100 | Train Loss: 0.4825, Val Loss: 0.6129, Val Acc: 0.7975
Iter 12/100 | Train Loss: 0.4640, Val Loss: 0.4656, Val Acc: 0.8316
Iter 13/100 | Train Loss: 0.4375, Val Loss: 0.4409, Val Acc: 0.8368
Iter 14/100 | Train Loss: 0.4210, Val Loss: 0.5552, Val Acc: 0.7975
Iter 15/100 | Train Loss: 0.4072, Val Loss: 0.4285, Val Acc: 0.8459
Iter 16/100 | Train Loss: 0.3936, Val Loss: 0.4282, Val Acc: 0.8457
Iter 17/100 | Train Loss: 0.3786, Val Loss: 0.4016, Val Acc: 0.8585
Iter 18/100 | Train Loss: 0.3665, Val Loss: 0.4862, Val Acc: 0.8301
Iter 19/100 | Train Loss: 0.3620, Val Loss: 0.6321, Val Acc: 0.7798
Iter 20/100 | Train Loss: 0.3425, Val Loss: 0.3592, Val Acc: 0.8751
Iter 21/100 | Train Loss: 0.3273, Val Loss: 0.3876, Val Acc: 0.8733
Iter 22/100 | Train Loss: 0.3226, Val Loss: 0.5315, Val Acc: 0.8074
Iter 23/100 | Train Loss: 0.3036, Val Loss: 1.1252, Val Acc: 0.7244
Iter 24/100 | Train Loss: 0.3086, Val Loss: 0.6023, Val Acc: 0.8104
Iter 25/100 | Train Loss: 0.3101, Val Loss: 0.5070, Val Acc: 0.8257
Iter 26/100 | Train Loss: 0.2851, Val Loss: 0.4469, Val Acc: 0.8407
Iter 27/100 | Train Loss: 0.2857, Val Loss: 0.3410, Val Acc: 0.8872
Iter 28/100 | Train Loss: 0.2687, Val Loss: 0.5297, Val Acc: 0.8240
Iter 29/100 | Train Loss: 0.2636, Val Loss: 0.7486, Val Acc: 0.7960
Iter 30/100 | Train Loss: 0.2489, Val Loss: 0.6071, Val Acc: 0.7800
Iter 31/100 | Train Loss: 0.2604, Val Loss: 0.3316, Val Acc: 0.8916
Iter 32/100 | Train Loss: 0.2409, Val Loss: 0.3248, Val Acc: 0.8933
Iter 33/100 | Train Loss: 0.2459, Val Loss: 0.3625, Val Acc: 0.8793
Iter 34/100 | Train Loss: 0.2239, Val Loss: 0.3846, Val Acc: 0.8679
Iter 35/100 | Train Loss: 0.2193, Val Loss: 0.3980, Val Acc: 0.8716
Iter 36/100 | Train Loss: 0.2096, Val Loss: 0.3347, Val Acc: 0.8919
Iter 37/100 | Train Loss: 0.2104, Val Loss: 0.4770, Val Acc: 0.8333
Iter 38/100 | Train Loss: 0.2173, Val Loss: 0.5457, Val Acc: 0.8430
Iter 39/100 | Train Loss: 0.2122, Val Loss: 0.3298, Val Acc: 0.8906
Iter 40/100 | Train Loss: 0.2012, Val Loss: 0.3143, Val Acc: 0.8978
Iter 41/100 | Train Loss: 0.2001, Val Loss: 0.5331, Val Acc: 0.8296
Iter 42/100 | Train Loss: 0.2017, Val Loss: 0.3942, Val Acc: 0.8746
Iter 43/100 | Train Loss: 0.1840, Val Loss: 0.7336, Val Acc: 0.7790
Iter 44/100 | Train Loss: 0.1828, Val Loss: 0.3568, Val Acc: 0.8867
Iter 45/100 | Train Loss: 0.1807, Val Loss: 0.4294, Val Acc: 0.8635
Iter 46/100 | Train Loss: 0.1851, Val Loss: 0.5678, Val Acc: 0.8351
Iter 47/100 | Train Loss: 0.1716, Val Loss: 0.4054, Val Acc: 0.8667
Iter 48/100 | Train Loss: 0.1841, Val Loss: 0.4352, Val Acc: 0.8664
Iter 49/100 | Train Loss: 0.1749, Val Loss: 0.4068, Val Acc: 0.8686
Iter 50/100 | Train Loss: 0.1618, Val Loss: 0.3890, Val Acc: 0.8820
Iter 51/100 | Train Loss: 0.1675, Val Loss: 0.3622, Val Acc: 0.8911
Iter 52/100 | Train Loss: 0.1599, Val Loss: 0.3926, Val Acc: 0.8825
Iter 53/100 | Train Loss: 0.1607, Val Loss: 0.4057, Val Acc: 0.8726
Iter 54/100 | Train Loss: 0.1576, Val Loss: 0.3819, Val Acc: 0.8854
Iter 55/100 | Train Loss: 0.1535, Val Loss: 0.3238, Val Acc: 0.8990
Iter 56/100 | Train Loss: 0.1513, Val Loss: 0.4554, Val Acc: 0.8615
Iter 57/100 | Train Loss: 0.1506, Val Loss: 0.5139, Val Acc: 0.8284
Iter 58/100 | Train Loss: 0.1440, Val Loss: 0.3244, Val Acc: 0.9064
Iter 59/100 | Train Loss: 0.1447, Val Loss: 0.4046, Val Acc: 0.8758
Iter 60/100 | Train Loss: 0.1385, Val Loss: 0.4777, Val Acc: 0.8649
Iter 61/100 | Train Loss: 0.1469, Val Loss: 0.5753, Val Acc: 0.8346
Iter 62/100 | Train Loss: 0.1396, Val Loss: 0.3865, Val Acc: 0.8901
Iter 63/100 | Train Loss: 0.1480, Val Loss: 0.3790, Val Acc: 0.8911
Iter 64/100 | Train Loss: 0.1387, Val Loss: 0.3309, Val Acc: 0.9020
Iter 65/100 | Train Loss: 0.1359, Val Loss: 0.7523, Val Acc: 0.7842
Iter 66/100 | Train Loss: 0.1331, Val Loss: 0.5552, Val Acc: 0.8435
Iter 67/100 | Train Loss: 0.1309, Val Loss: 0.4437, Val Acc: 0.8728
Iter 68/100 | Train Loss: 0.1254, Val Loss: 0.5102, Val Acc: 0.8484
Iter 69/100 | Train Loss: 0.1244, Val Loss: 0.3554, Val Acc: 0.9022
Iter 70/100 | Train Loss: 0.1262, Val Loss: 0.3538, Val Acc: 0.8975
Iter 71/100 | Train Loss: 0.1344, Val Loss: 0.3825, Val Acc: 0.8832
Iter 72/100 | Train Loss: 0.1285, Val Loss: 0.5789, Val Acc: 0.8457
Iter 73/100 | Train Loss: 0.1187, Val Loss: 0.3362, Val Acc: 0.8983
Iter 74/100 | Train Loss: 0.1247, Val Loss: 0.3818, Val Acc: 0.8844
Iter 75/100 | Train Loss: 0.1289, Val Loss: 0.3736, Val Acc: 0.8926
Iter 76/100 | Train Loss: 0.1274, Val Loss: 0.4280, Val Acc: 0.8738
Iter 77/100 | Train Loss: 0.1132, Val Loss: 0.3598, Val Acc: 0.9005
Iter 78/100 | Train Loss: 0.1138, Val Loss: 0.5023, Val Acc: 0.8519
Iter 79/100 | Train Loss: 0.1210, Val Loss: 0.4170, Val Acc: 0.8748
Iter 80/100 | Train Loss: 0.1209, Val Loss: 0.3458, Val Acc: 0.8973
Iter 81/100 | Train Loss: 0.1148, Val Loss: 0.4364, Val Acc: 0.8758
Iter 82/100 | Train Loss: 0.1254, Val Loss: 0.3985, Val Acc: 0.8825
Iter 83/100 | Train Loss: 0.1135, Val Loss: 0.5341, Val Acc: 0.8454
Iter 84/100 | Train Loss: 0.1145, Val Loss: 0.3979, Val Acc: 0.8864
Iter 85/100 | Train Loss: 0.1149, Val Loss: 0.3699, Val Acc: 0.8914
Iter 86/100 | Train Loss: 0.1137, Val Loss: 0.4282, Val Acc: 0.8867
Iter 87/100 | Train Loss: 0.1149, Val Loss: 0.3833, Val Acc: 0.8956
Iter 88/100 | Train Loss: 0.1140, Val Loss: 0.4421, Val Acc: 0.8763
Iter 89/100 | Train Loss: 0.1150, Val Loss: 0.4744, Val Acc: 0.8610
Iter 90/100 | Train Loss: 0.1141, Val Loss: 0.3854, Val Acc: 0.8753
Iter 91/100 | Train Loss: 0.1032, Val Loss: 0.3560, Val Acc: 0.8921
Iter 92/100 | Train Loss: 0.1047, Val Loss: 0.3240, Val Acc: 0.9059
Iter 93/100 | Train Loss: 0.1034, Val Loss: 0.6194, Val Acc: 0.8425
Iter 94/100 | Train Loss: 0.1044, Val Loss: 0.5045, Val Acc: 0.8578
Iter 95/100 | Train Loss: 0.1066, Val Loss: 0.4747, Val Acc: 0.8647
Iter 96/100 | Train Loss: 0.1052, Val Loss: 0.5532, Val Acc: 0.8689
Iter 97/100 | Train Loss: 0.1031, Val Loss: 0.4675, Val Acc: 0.8637
Iter 98/100 | Train Loss: 0.1044, Val Loss: 0.3890, Val Acc: 0.8970
Iter 99/100 | Train Loss: 0.1081, Val Loss: 0.4733, Val Acc: 0.8617
Iter 100/100 | Train Loss: 0.0967, Val Loss: 0.4028, Val Acc: 0.8889

Test Accuracy: 0.8953
 

'개인 프로젝트 > 대학원 수업 정리' 카테고리의 다른 글

[CV] Classification, Segmentation  (0) 2025.12.02
[CV] 과제3_3번  (0) 2025.11.20
[논문리뷰] CharGrid OCR 중요 원리  (0) 2025.11.19
[CV] 과제 3 최종코드  (0) 2025.11.16
[CV] 과제 3  (0) 2025.11.12

댓글