
: 코드 레벨 설명
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)력하세요
class SimpleCNN(nn.Module):
def __init__(self):
super(SimpleCNN, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.fc1 = nn.Linear(64 * 28 * 28, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = torch.relu(self.conv1(x)) # 첫 번째 Convolution + Activation
x = torch.relu(self.conv2(x)) # 두 번째 Convolution + Activation
x = x.view(x.size(0), -1) # Flatten 연산
x = torch.relu(self.fc1(x)) # 첫 번째 Fully Connected + Activation
x = self.fc2(x) # 두 번째 Fully Connected (출력 레이어)
return x
: device 설정시 mac 용에 최적화된 mps 사용
device = torch.device("mps" if torch.backends.mps.is_available() else "cpu")
model = SimpleCNN().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
def train(model, train_loader, criterion, optimizer, num_epochs=10):
model.train()
for epoch in range(num_epochs):
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()
print(f'Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}')
def evaluate(model, test_loader, criterion):
model.eval()
correct = 0
total = 0
loss = 0.0
with torch.no_grad():
for inputs, labels in test_loader:
inputs, labels = inputs.to(device), labels.to(device)
outputs = model(inputs)
loss += criterion(outputs, labels).item()
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
accuracy = 100 * correct / total
print(f'Loss: {loss/len(test_loader)}, Accuracy: {accuracy}%')
return loss / len(test_loader), accuracy
train(model, train_loader, criterion, optimizer)
evaluate(model, test_loader, criterion)
Max Pooling이나 Average Pooling은 고정된 커널 크기와 스트라이드를 사용하여 입력 텐서의 크기를 줄이면서 계산
class CNNWithPooling(nn.Module):
def __init__(self):
super(CNNWithPooling, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.pool = nn.MaxPool2d(2, 2) # Max Pooling 레이어 추가
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.fc1 = nn.Linear(64 * 7 * 7, 128) # Max Pooling으로 인해 크기 변경
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = self.pool(torch.relu(self.conv1(x))) # Convolution + Activation + Max Pooling
x = self.pool(torch.relu(self.conv2(x))) # Convolution + Activation + Max Pooling
x = x.view(x.size(0), -1) # Flatten 연산
x = torch.relu(self.fc1(x)) # 첫 번째 Fully Connected + Activation
x = self.fc2(x) # 두 번째 Fully Connected (출력 레이어)
return x
device = torch.device("mps" if torch.backends.mps.is_available() else "cpu")
model = CNNWithPooling().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
def train(model, train_loader, criterion, optimizer, num_epochs=10):
model.train()
for epoch in range(num_epochs):
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()
print(f'Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}')
def evaluate(model, test_loader, criterion):
model.eval()
correct = 0
total = 0
loss = 0.0
with torch.no_grad():
for inputs, labels in test_loader:
inputs, labels = inputs.to(device), labels.to(device)
outputs = model(inputs)
loss += criterion(outputs, labels).item()
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
accuracy = 100 * correct / total
print(f'Loss: {loss/len(test_loader)}, Accuracy: {accuracy}%')
return loss / len(test_loader), accuracy
train(model, train_loader, criterion, optimizer)
evaluate(model, test_loader, criterion)
daptive Pooling은 출력 텐서의 크기를 미리 정의하고, 그 크기에 맞게 입력 텐서를 유동적으로 변환
1. Adaptive Max Pooling: 각 출력 위치에 대해 입력 텐서의 특정 영역에서 최대값을 선택합니다.
2. Adaptive Average Pooling: 각 출력 위치에 대해 입력 텐서의 특정 영역에서 평균값을 계산합니다.
class CNNWithAdaptivePooling(nn.Module):
def __init__(self):
super(CNNWithAdaptivePooling, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.adaptive_pool = nn.AdaptiveAvgPool2d((7, 7)) # Adaptive Pooling 레이어 추가
self.fc1 = nn.Linear(64 * 7 * 7, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = torch.relu(self.conv1(x)) # 첫 번째 Convolution + Activation
x = torch.relu(self.conv2(x)) # 두 번째 Convolution + Activation
x = self.adaptive_pool(x) # Adaptive Pooling
x = x.view(x.size(0), -1) # Flatten 연산
x = torch.relu(self.fc1(x)) # 첫 번째 Fully Connected + Activation
x = self.fc2(x) # 두 번째 Fully Connected (출력 레이어)
return x
model = CNNWithAdaptivePooling().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
def train(model, train_loader, criterion, optimizer, num_epochs=10):
model.train()
for epoch in range(num_epochs):
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()
print(f'Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}')
def evaluate(model, test_loader, criterion):
model.eval()
correct = 0
total = 0
loss = 0.0
with torch.no_grad():
for inputs, labels in test_loader:
inputs, labels = inputs.to(device), labels.to(device)
outputs = model(inputs)
loss += criterion(outputs, labels).item()
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
accuracy = 100 * correct / total
print(f'Loss: {loss/len(test_loader)}, Accuracy: {accuracy}%')
return loss / len(test_loader), accuracy
train(model, train_loader, criterion, optimizer)
evaluate(model, test_loader, criterion)
: accuracy -> 99프로
Flattern 연산 및 Fully Connected 레이어 없이 Convolution과 Activation 레이어만 가지고 MNIST 분류기 만들기
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
batch_size = 64
epochs = 10
learning_rate = 0.001
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,))
])
train_dataset = datasets.MNIST(root='./data', train=True, transform=transform, download=True)
test_dataset = datasets.MNIST(root='./data', train=False, transform=transform, download=True)
train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=False)
class ConvNet(nn.Module):
def __init__(self):
super(ConvNet, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.conv3 = nn.Conv2d(64, 10, kernel_size=3, padding=1)
self.relu = nn.ReLU()
self.pool = nn.AdaptiveAvgPool2d((1, 1))
def forward(self, x):
x = self.relu(self.conv1(x)) # 첫 번째 Conv 레이어 + ReLU
x = self.pool(x) # Adaptive Average Pooling
x = self.relu(self.conv2(x)) # 두 번째 Conv 레이어 + ReLU
x = self.pool(x) # Adaptive Average Pooling
x = self.conv3(x) # 세 번째 Conv 레이어 (출력: 10채널)
x = self.pool(x) # Adaptive Average Pooling
return x.squeeze() # 차원 축소 (batch_size, 10)
model = ConvNet()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)
for epoch in range(epochs):
model.train()
for images, labels in train_loader:
images, labels = images.to(device), labels.to(device)
outputs = model(images)
loss = criterion(outputs, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
print(f'Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}')
model.eval()
with torch.no_grad():
correct = 0
total = 0
for images, labels in test_loader:
images, labels = images.to(device), labels.to(device)
outputs = model(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f'Test Accuracy: {100 * correct / total:.2f}%')
: 실제 이 모델의 경우 정확도가 50프로 이하로 매우 낮음