1. 간단한 CNN 모델 만들기
- import
import torch
import torch.nn as nn
import torch.optim as optim
|
- PyTorch의 Tensor를 생성하고 그 형태(shape)를 출력
# 배치크기 * 채널(1: 그레이스케일, 3: 컬러) * 높이 * 너비
inputs= torch.Tensor(1,1,28,28)
print(inputs.shape)
|
torch.Size([1, 1, 28, 28]) ======================== 1x1x28x28인 4차원 텐서
|
- PyTorch를 사용하여 첫 번째 Convolutional Layer를 정의하고 입력 데이터에 대해 적용
# 첫번째 Conv2D
conv1 = nn. Conv2d(in_channels=1, out_channels=32, kernel_size=3,padding='same')
out = conv1(inputs)
print(out.shape)
|
결과 해석이 코드는 입력 이미지에 대해 첫 번째 Convolutional Layer를 정의하고 적용한 결과를 보여줍니다.Conv2d 레이어는 입력 이미지를 필터를 이용해 특징 맵으로 변환하는 역할을 수행하며, 이를 통해 이미지에서의 패턴 인식 및 특징 추출이 가능해집니다. |
torch.Size([1, 32, 28, 28]) : 출력된 out 텐서의 모양입니다.
|
- PyTorch를 사용하여 첫 번째 MaxPooling Layer를 정의하고 이전에 정의한 Convolutional Layer의 출력에 적용
# 첫번째 MaxPool2D
pool = nn.MaxPool2d(kernel_size=2)
out = pool(out)
print(out.shape)
|
결과 해석MaxPooling은 Convolutional Layer를 거친 후 특성 맵의 크기를 줄이는 역할을 합니다.주로 합성곱 신경망(Convolutional Neural Network, CNN)에서 사용되며, 특성 맵의 공간적 크기를 줄이고 계산량을 감소시키며 추출된 특징의 위치 변화에 대한 불변성을 제공합니다. 이 코드에서는 MaxPooling을 적용하여 특성 맵의 크기를 절반으로 줄인 예시를 보여줍니다. |
torch.Size([1, 32, 14, 14])
|
- PyTorch를 사용하여 두 번째 2D 컨볼루션 레이어를 정의하고 적용한 후 출력 텐서의 형태를 출력
# 두번째 Conv2D
conv2 = nn. Conv2d(in_channels=32, out_channels=64, kernel_size=3,padding='same')
out = conv2(out)
print(out.shape)
|
|
|
|
torch.Size([1, 64, 14, 14])
|
- 두 번째 2D 맥스 풀링 레이어를 정의하고 적용한 후 출력 텐서의 형태를 출력
# 두번째 MaxPool2D
pool = nn.MaxPool2d(kernel_size=2)
out = pool(out)
print(out.shape)
|
|
|
|
torch.Size([1, 64, 7, 7])
|
|
- PyTorch에서 3차원 데이터를 1차원으로 펼치는 과정
Convolutional Neural Network (CNN)에서 Convolutional Layer와 MaxPooling Layer를 거친 후에
Fully Connected Layer (Linear Layer)에 입력하기 위해 필요한 작업
# Flatten
# 배치를 제외한 3차원 데이터를 1차원으로 펼침
# 1차원으로 만들어야 nn.LInear() 레이어에 넣을 수 있음
flatten = nn.Flatten()
out = flatten(out)
print(out.shape)
|
결과 해석Flatten 레이어는 CNN에서 Convolutional Layer와 MaxPooling Layer를 거친 후에 사용되며, 다차원의 특성 맵을 1차원의 벡터로 변환합니다. 이 과정은 이미지 처리와 같은 작업에서 추출된 특징을 Fully Connected Layer로 전달하여 분류 등의 작업을 수행할 수 있도록 합니다. 위의 코드에서는 Flatten 레이어를 이용해 64개의 채널을 가진 출력 특성 맵을 1차원으로 변환하는 과정을 보여줍니다. |
torch.Size([1, 3136])
|
- PyTorch에서 Fully Connected Layer (선형 회귀) 레이어에 통과시킨 후 , Flatten된 데이터를 이 레이어에 입력하는 과정
# Dance(Fully Connected)
# 선형 회귀
fc = nn.Linear(3136,10)
out = fc(out)
print(out.shape)
|
결과 해석Fully Connected Layer는 Convolutional Neural Network (CNN)의 마지막 단계로, 이미지 처리에서 추출된 특성을 이용해 최종적으로 클래스를 예측하는 역할을 합니다. 위의 코드에서는 Flatten된 데이터를 입력으로 받아들여 3136개의 입력을 처리하고, 10개의 클래스로 출력하는 Fully Connected Layer를 정의하고 있습니다. 이러한 구조는 주로 이미지 분류 문제에서 사용되며, 출력 레이어로 Softmax를 추가하여 확률 분포를 얻을 수 있습니다. |
torch.Size([1, 10]) 이전 Flatten 레이어 후의 출력 형태가 torch.Size([1, 3136])였습니다. 이를 Fully Connected 레이어에 입력하면:
|
왜 필요한가?
정리이 코드는 3136차원의 입력 텐서를 10차원의 출력 텐서로 변환하는 Fully Connected 레이어를 정의하고 적용하여 출력 텐서의 형태를 확인합니다. 여기서 출력 형태 torch.Size([1, 10])는 배치 크기 1에 대해 10개의 클래스 점수를 나타냅니다. |
2. CNN으로 MNIST 분류하기
- import
import torch
import torchvision.datasets as datasets
import torchvision.transforms as transforms
import matplotlib.pyplot as plt
from torch.utils.data import DataLoader
|
- GPU가 사용 가능하면 device 변수를 'cuda'로 설정
device = 'cuda' if torch.cuda.is_available() else 'cpu'
print(device)
|
cpu ---> cuda |
- PyTorch에서 MNIST 데이터셋을 로드하는 과정
train_data = datasets.MNIST(
root ='data',
train = True,
transform=transforms.ToTensor(),
download=True
)
test_data = datasets.MNIST(
root ='data',
train = False,
transform=transforms.ToTensor(),
download=True
)
|
데이터셋 설명
사용된 전처리
|
Downloading http://yann.lecun.com/exdb/mnist/train-images-idx3-ubyte.gz
Failed to download (trying next): HTTP Error 403: Forbidden Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-images-idx3-ubyte.gz Downloading https://ossci-datasets.s3.amazonaws.com/mnist/train-images-idx3-ubyte.gz to data/MNIST/raw/train-images-idx3-ubyte.gz 100%|██████████| 9912422/9912422 [00:00<00:00, 13769231.05it/s] Extracting data/MNIST/raw/train-images-idx3-ubyte.gz to data/MNIST/raw ...... Downloading http://yann.lecun.com/exdb/mnist/t10k-labels-idx1-ubyte.gz Failed to download (trying next): HTTP Error 403: Forbidden Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz Downloading https://ossci-datasets.s3.amazonaws.com/mnist/t10k-labels-idx1-ubyte.gz to data/MNIST/raw/t10k-labels-idx1-ubyte.gz 100%|██████████| 4542/4542 [00:00<00:00, 6820812.31it/s]Extracting data/MNIST/raw/t10k-labels-idx1-ubyte.gz to data/MNIST/raw |
- 각각 학습 데이터셋과 테스트 데이터셋에 대한 정보를 출력
print(train_data)
print(test_data)
|
Dataset MNIST Number of datapoints: 60000 Root location: data Split: Train StandardTransform Transform: ToTensor() Dataset MNIST Number of datapoints: 10000 Root location: data Split: Test StandardTransform Transform: ToTensor() |
- MNIST 학습 데이터셋을 DataLoader를 사용하여 미니배치로 나눈 후
이미지를 시각화하는 과정
# DataLoader를 사용하여 MNIST 학습 데이터셋을 미니배치로 나누기
loader = DataLoader(
dataset=train_data, # 학습 데이터셋을 DataLoader에 전달
batch_size=64, # 미니배치 크기를 64로 설정
shuffle=True # 데이터를 섞어서 가져올지 여부 (True로 설정하여 데이터를 섞음)
)
# 첫 번째 미니배치 가져오기
imgs, labels = next(iter(loader))
# 시각화를 위한 서브플롯 설정
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') # 이미지를 28x28 크기로 변형하여 흑백으로 표시
ax.set_title(label.item()) # 레이블을 제목으로 설정
ax.axis('off') # 축 숨기기 (눈금을 표시하지 않음)
|
- PyTorch를 사용하여 간단한 컨볼루션 신경망(Convolutional Neural Network, CNN) 모델을 정의
from torch.nn.modules.pooling import MaxPool2d
model = nn.Sequential(
nn.Conv2d(1, 32, kernel_size=3, padding='same'),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2),
nn.Conv2d(32, 64, kernel_size=3, padding='same'),
nn.ReLU(),
nn.MaxPool2d(kernel_size=2),
nn.Flatten(),
nn.Linear(7*7*64, 10)
).to(device)
print(model)
|
모델 설명이 모델은 두 개의 컨볼루션 레이어와 최대 풀링 레이어를 거친 후에 fully connected 레이어로 이어집니다. 각 컨볼루션 레이어 다음에는 ReLU 활성화 함수가 적용됩니다. 마지막으로, 2D 이미지를 1D 벡터로 평탄화한 후 fully connected 레이어에 입력됩니다. 이 모델은 MNIST 손글씨 숫자 분류를 위해 설계되었으며, 이미지를 입력으로 받아 각 클래스(0에서 9까지의 숫자)에 대한 확률을 출력합니다. |
Sequential( (0): Conv2d(1, 32, kernel_size=(3, 3), stride=(1, 1), padding=same) (1): ReLU() (2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (3): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=same) (4): ReLU() (5): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (6): Flatten(start_dim=1, end_dim=-1) (7): Linear(in_features=3136, out_features=10, bias=True) ) ----------------------------------------------------------------------- GPU로 다시 실행 |
- PyTorch를 사용하여 CNN 모델을 MNIST 데이터셋으로 학습하는 과정
# 학습
optimizer = optim.Adam(model.parameters(), lr=0.001)
epochs = 10
for epoch in range(epochs):
sum_losses = 0
sum_accs = 0
for x_batch, y_batch in loader:
x_batch = x_batch.to(device)
y_batch = y_batch.to(device)
y_pred = model(x_batch)
loss = nn.CrossEntropyLoss()(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(loader)
avg_acc = sum_accs / len(loader)
print(f'Epoch {epoch:4d}/{epochs} Loss: {avg_loss:.6f} Accuracy: {avg_acc:.2f}%')
|
요약이 코드는 MNIST 데이터셋을 사용하여 정의한 CNN 모델을 학습하는 과정을 보여줍니다.Adam 옵티마이저를 사용하여 역전파와 파라미터 업데이트를 수행하며, 각 epoch 마다 손실과 정확도를 출력하여 모델의 학습 진행 상황을 확인합니다. |
Epoch 0/10 Loss: 0.009623 Accuracy: 99.66% Epoch 1/10 Loss: 0.006494 Accuracy: 99.80% Epoch 2/10 Loss: 0.006753 Accuracy: 99.80% Epoch 3/10 Loss: 0.005891 Accuracy: 99.80% Epoch 4/10 Loss: 0.004189 Accuracy: 99.87% Epoch 5/10 Loss: 0.003984 Accuracy: 99.87% Epoch 6/10 Loss: 0.003420 Accuracy: 99.88% Epoch 7/10 Loss: 0.003456 Accuracy: 99.89% Epoch 8/10 Loss: 0.003008 Accuracy: 99.88% Epoch 9/10 Loss: 0.004352 Accuracy: 99.85% |
- 테스트 데이터셋(test_data)을 사용하여 DataLoader를 생성하고, 첫 번째 미니배치 데이터를 시각화하는 과정
test_loader= DataLoader(
dataset=test_data,
batch_size=64,
shuffle=True
)
imgs, labels = next(iter(loader))
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(label.item())
ax.axis('off')
|
요약이 코드는 테스트 데이터셋에서 데이터를 로드하고, 첫 번째 미니배치의 이미지를 8x8 격자로 시각화하여 표시합니다. 각 이미지는 흑백으로, 해당 이미지의 레이블 값이 제목으로 설정됩니다. 이를 통해 데이터셋이 제대로 로드되었는지와 이미지가 정확히 시각화되었는지를 확인할 수 있습니다. |
- 테스트 데이터셋을 사용하여 학습된 모델의 정확도를 평가하기
from torchvision.transforms.functional import accimage
model.eval() # 모델을 테스트 모드로 전환
sum_accs=0
for x_batch, y_batch in test_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)
acc = (y_batch == y_pred_index).float().sum() / len(y_batch) * 100
sum_accs = sum_accs + acc
avg_acc = sum_accs / len(test_loader)
print(f'테스트 정확도는 {avg_acc:.2f}%입니다!')
|
요약이 코드는 테스트 데이터셋을 사용하여 학습된 모델의 정확도를 평가합니다. 각 미니배치를 모델에 전달하고 예측을 수행한 후, 정확도를 계산하여 전체 테스트 데이터셋에 대한 평균 정확도를 출력합니다. 이를 통해 모델이 얼마나 잘 동작하는지를 확인할 수 있습니다. |
테스트 정확도는 98.84%입니다! |
3. 과제
○, X,△를 그림판에 여러가지 이미지를 저장 후 CNN으로 학습을 시켜 해당 데이터를 분류하는 모델을 만들어보자
'AI > 딥러닝' 카테고리의 다른 글
10. 포켓몬 분류 (0) | 2024.06.21 |
---|---|
09. 전이학습 (0) | 2024.06.21 |
07. CNN 기초 (0) | 2024.06.20 |
06. 비선형 활성화 함수 (0) | 2024.06.20 |
05. 딥러닝 (0) | 2024.06.20 |