import numpy as np import torch import torch.nn as nn # layer들을 호출하기 위해서 import torch.optim as optim # optimization method를 사용하기 위해서 import torch.nn.init as init # weight initialization 해주기 위해서 import torchvision.datasets as dset # toy data들을 이용하기 위해서 import torchvision.transforms as transforms # pytorch 모델을 위한 데이터 변환을 위해 from torch.utils.data import DataLoader # train,test 데이터를 loader객체로 만들어주기 위해서
batch_size = 256
learning_rate = 0.0002
num_epoch = 30
mnist_train = dset.CIFAR10("./", train=True, transform=transforms.ToTensor(), # torch안에서 연산을 해주기 위한 형태로 변환 target_transform=None, download=True) mnist_test = dset.CIFAR10("./", train=False, transform=transforms.ToTensor(), # torch안에서 연산을 해주기 위한 형태로 변환 target_transform=None, download=True)
# row데이터가 아닌 torch 객체가 나옴 print(mnist_train) >Dataset CIFAR10 Number of datapoints: 50000 Root location: ./ Split: Train StandardTransform Transform: ToTensor() # row데이터 조회 print(mnist_train.__getitem__(0)) >(tensor([[[0.2314, 0.1686, 0.1961, ..., 0.6196, 0.5961, 0.5804], [0.0627, 0.0000, 0.0706, ..., 0.4824, 0.4667, 0.4784], [0.0980, 0.0627, 0.1922, ..., 0.4627, 0.4706, 0.4275], ..., [0.8157, 0.7882, 0.7765, ..., 0.6275, 0.2196, 0.2078], [0.7059, 0.6784, 0.7294, ..., 0.7216, 0.3804, 0.3255], [0.6941, 0.6588, 0.7020, ..., 0.8471, 0.5922, 0.4824]], ... # train data[0] shape 및 데이터 크기 확인 print(mnist_train.__getitem__(0)[0].size(),mnist_train.__len__()) >torch.Size([3, 32, 32]) 50000 # test data[0] shape 및 데이터 크기 확인 print(mnist_test.__getitem__(0)[0].size(),mnist_test.__len__()) >torch.Size([3, 32, 32]) 10000
# Data loader 객체 생성 # 데이터 batch로 나눠주고 shuffle해주는 데이터 loader 객체 생성 train_loader = DataLoader(mnist_train, batch_size=batch_size, shuffle=True, num_workers=2, drop_last=True) test_loader = DataLoader(mnist_test, batch_size=batch_size, shuffle=False, num_workers=2, drop_last=True)
class CNN(nn.Module): def __init__(self): super(CNN,self).__init__() self.layer = nn.Sequential( nn.Conv2d(3,16,3,padding=1), # in channel:3, out channel:16, kernel_size=3 nn.ReLU(), nn.Conv2d(16,32,3,padding=1), # in channel:16, out channel:32, kernel_size=3 nn.ReLU(), nn.MaxPool2d(2,2), # 32x16x16 nn.Dropout(0.5), nn.Conv2d(32,64,3,padding=1), # in channel:32, out channel:64, kernel_size=3 nn.ReLU(), nn.Conv2d(64,128,3,padding=1), # in channel:64, out channel:128, kernel_size=3 nn.ReLU(), nn.MaxPool2d(2,2), # 128x8x8 nn.Dropout(0.5), nn.Conv2d(128,256,3,padding=1), # in channel:128, out channel:256, kernel_size=3 nn.ReLU(), nn.Conv2d(256,256,3,padding=1), # in channel:256, out channel:256, kernel_size=3 nn.ReLU(), nn.MaxPool2d(2,2), # 256x4x4 nn.Dropout(0.5) ) self.fc_layer = nn.Sequential( nn.Linear(256*4*4,200), # input node : 256*4*4, output node : 200 nn.ReLU(), nn.Dropout(0.5), nn.Linear(200,10) ) def forward(self,x): out = self.layer(x) # out = (256 , 4 , 4) # .view는 reshape과 같은 역할 out = out.view(batch_size,-1) # (256 , 4 , 4) => (batch, 256 x 4 x 4) out = self.fc_layer(out) return out model = CNN().cuda()
loss_func = nn.CrossEntropyLoss() # 크로스엔트로피 loss 객체, softmax를 포함함 optimizer = optim.Adam(model.parameters(), # 만든 모델의 파라미터를 넣어줘야 함 lr=learning_rate)
for epoch in range(num_epoch): for idx,(image,label) in enumerate(train_loader): x = image.to(torch.device('cuda')) y_ = label.to(torch.device('cuda')) # train데이터 셋 feedforwd 과정 output = model.forward(x) # loss 계산 loss = loss_func(output,y_) # optimizer 초기화 및 weight 업데이트 optimizer.zero_grad() # 그래디언트 제로로 만들어주는 과정 loss.backward() # backpropagation optimizer.step() if idx % 100 == 0: print('epoch : ',epoch) print('loss : ',loss.data) print('-----------------') >epoch : 0 loss : tensor(2.3026, device='cuda:0') ----------------- epoch : 0 loss : tensor(2.0643, device='cuda:0') ----------------- epoch : 1 loss : tensor(1.9147, device='cuda:0') ----------------- epoch : 1 loss : tensor(1.7581, device='cuda:0') ----------------- epoch : 2 loss : tensor(1.6416, device='cuda:0') ----------------- epoch : 2 loss : tensor(1.6185, device='cuda:0') ... ... ...
# 모델이 가지고 있는 weight구조를 보여줌 param_list = list(model.children()) print(param_list) >[Sequential( (0): Conv2d(3, 16, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): ReLU() (2): Conv2d(16, 32, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (3): ReLU() (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (5): Dropout(p=0.5, inplace=False) (6): Conv2d(32, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (7): ReLU() (8): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (9): ReLU() (10): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (11): Dropout(p=0.5, inplace=False) (12): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (13): ReLU() (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (15): ReLU() (16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (17): Dropout(p=0.5, inplace=False) ), Sequential( (0): Linear(in_features=4096, out_features=200, bias=True) (1): ReLU() (2): Dropout(p=0.5, inplace=False) (3): Linear(in_features=200, out_features=10, bias=True) )]
model.eval() # test시에는 dropout을 꺼준다. correct = 0 total = 0 for image, label in test_loader: x = image.to(torch.device('cuda')) y_ = label.to(torch.device('cuda')) output = model.forward(x) _, output_index = torch.max(output,1) # output을 인덱스 1방향으로 최고를 뽑아줌 total += label.size(0) correct += (output_index == y_).sum().float() print('Acc : {}'.format(100*correct/total)) >Acc : 74.00841522216797