import torch
import torchvision.datasets as datasets
import torchvision.transforms as transforms
필요한 모듈을 가져옵니다.
device = 'cuda' if torch.cuda.is_available() else 'cpu'
# 랜덤 시드 고정
torch.manual_seed(777)
# GPU 사용 가능일 경우 랜덤 시드 고정
if device == 'cuda':
torch.cuda.manual_seed_all(777)
GPU를 사용할 수 있으면 사용합니다.
랜덤 시드를 고정하는 이유는 다음에 다시 돌렸을 경우에도 같은 결과를 얻기 위해서 입니다.
learning_rate = 0.001
training_epochs = 15
batch_size = 100
학습에 관련된 하이퍼 파라미터를 설정합니다.
mnist_train = datasets.MNIST(root='Data/',
train=True,
transform=transforms.ToTensor(),
download=True)
mnist_test = datasets.MNIST(root='Data/',
train=False,
transform=transforms.ToTensor(),
download=True)
root는 다운로드 경로 지정합니다.
train을 True로 설정하면 훈련 데이터로 다운로드합니다.
ToTensor()는 텐서로 만들고 [0 ... 1] 사이의 값으로 변환합니다.
data_loader = torch.utils.data.DataLoader(dataset=mnist_train,
batch_size=batch_size,
shuffle=True,
drop_last=True)
drop_last는 전체 데이터 수에서 batch_size로 나눈 나머지가 있을 경우 버리는 것입니다.
class CNN(torch.nn.Module):
def __init__(self):
super().__init__()
# 첫번째층
# ImgIn shape=(?, 28, 28, 1)
# Conv -> (?, 28, 28, 32)
# Pool -> (?, 14, 14, 32)
self.layer1 = torch.nn.Sequential(
torch.nn.Conv2d(1, 32, kernel_size=3, stride=1, padding=1),
torch.nn.ReLU(),
torch.nn.MaxPool2d(kernel_size=2, stride=2))
# 두번째층
# ImgIn shape=(?, 14, 14, 32)
# Conv ->(?, 14, 14, 64)
# Pool ->(?, 7, 7, 64)
self.layer2 = torch.nn.Sequential(
torch.nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1),
torch.nn.ReLU(),
torch.nn.MaxPool2d(kernel_size=2, stride=2))
# 전결합층 7x7x64 inputs -> 10 outputs
self.fc = torch.nn.Linear(7 * 7 * 64, 10, bias=True)
def forward(self, x):
out = self.layer1(x)
out = self.layer2(out)
out = torch.nn.Flatten()(out) # 전결합층을 위해서 Flatten
out = self.fc(out)
return out
간단한 모델을 구성합니다.
model = CNN().to(device)
CNN 인스턴스를 생성 후 인스턴스의 파라미터들과 버터를 GPU로 옮깁니다.
criterion = torch.nn.CrossEntropyLoss().to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
loss함수로는 CrossEntropy, optimization함수로는 Adam을 사용합니다.
total_batch = len(data_loader)
print('총 배치의 수 : {}'.format(total_batch))
총 배치의 수 : 600
minist_train의 수는 60,000개인데 batch_size가 100이므로 총 배치의 수는 600개입니다.
for epoch in range(training_epochs):
avg_cost = 0
for X, Y in data_loader: # 미니 배치 단위로 꺼내온다. X는 미니 배치, Y느 ㄴ레이블.
# image is already size of (28x28), no reshape
# label is not one-hot encoded
X = X.to(device)
Y = Y.to(device)
optimizer.zero_grad()
hypothesis = model(X)
cost = criterion(hypothesis, Y)
cost.backward()
optimizer.step()
avg_cost += cost / total_batch
print('[Epoch: {:>4}] cost = {:>.9}'.format(epoch + 1, avg_cost))
[Epoch: 1] cost = 0.209929511
[Epoch: 2] cost = 0.0615508817
[Epoch: 3] cost = 0.0456047803
[Epoch: 4] cost = 0.0363934599
[Epoch: 5] cost = 0.0300672501
[Epoch: 6] cost = 0.0253494326
[Epoch: 7] cost = 0.0202930104
[Epoch: 8] cost = 0.018379068
[Epoch: 9] cost = 0.0153796058
[Epoch: 10] cost = 0.0118981814
[Epoch: 11] cost = 0.0107681192
[Epoch: 12] cost = 0.00951414276
[Epoch: 13] cost = 0.0088522248
[Epoch: 14] cost = 0.00605905708
[Epoch: 15] cost = 0.00637460686
optimizer.zero_grad()는 이전 epoch의 미분값을 버립니다.
cost.backward()는 back propagation을 수행합니다.
optimizer.step()은 계산된 미분값에 따라 weight를 업데이트 합니다.
with torch.no_grad():
X_test = mnist_test.data.view(len(mnist_test), 1, 28, 28).float().to(device)
Y_test = mnist_test.targets.to(device)
prediction = model(X_test)
correct_prediction = torch.argmax(prediction, 1) == Y_test
accuracy = correct_prediction.float().mean()
print('Accuracy:', accuracy.item())
Accuracy: 0.9881999492645264
학습을 진행하지 않을 것이므로 torch.no_grad()를 수행합니다.
argmax는 입력 텐서에 있는 모든 요소의 최대값의 인덱스를 반환합니다.