스터디노트 (DeepLearning 9)

zoe·2023년 6월 30일
0

MNIST

# import

import torch
import torch.nn as nn
import torch.nn.functional as F # 주로 사용하는 function들..
import torch.optim as optim # 최적화
from torchvision import datasets, transforms # 딥러닝에서 주로 사용하는 dataset이 있는 모듈

from matplotlib import pyplot as plt
%matplotlib inline
# cuda가 가능하면 cuda 아니면 cpu 설정

is_cuda = torch.cuda.is_available()
device = torch.device('cuda' if is_cuda else 'cpu')

print('Current cuda device is', device)
# 파라미터 설정

batch_size = 50 # batch_size : 몇 개의 데이터를 모아서 가중치를 업데이트하는 계산을 사용할 것인가?..
learning_rate = 0.0001
epoch_num = 15
# MNIST 데이터 불러오기

train_data = datasets.MNIST(root='./data', train=True,
                            download=True,  # 처음에는 True설정하고 나중에는 이미 받았으니 False 하면 됨
                            transform=transforms.ToTensor())
# 웹에서 데이터 다운, 저장할 곳 지정

test_data = datasets.MNIST(root='./data', train=False,
                           transform= transforms.ToTensor())

print('number of training data : ', len(train_data))
print('number of test data : ', len(test_data))

# vs코드에서는 안됨;;


# image, label = train_data[0]

# plt.imshow(image.squeeze().numpy(), cmap = 'gray')
## squeeze() : torch에서는 채널의 차원이 가장 앞에 옴 ex) [1, 28, 28], 
## 그림을 그릴 수 있도록 2차원으로 바꿔줌 1을 없애버려라..[28, 28] 형태로 만들어라..

# plt.title('label : %s' %label)
# plt.show()
# 미니 배치 구성

train_loader = torch.utils.data.DataLoader(dataset = train_data, 
                                           batch_size = batch_size, shuffle = True)

test_loader = torch.utils.data.DataLoader(dataset = test_data, 
                                          batch_size = batch_size, shuffle = True)
# shuffle =  데이터의 순서를 학습하지 못하게 하려고..?, 데이터의 미니 배치를 잘 구성하기 위해서..?

first_batch = train_loader.__iter__().__next__()
# 출력을 정렬하고자 할 때 이런 방식을 사용
# 15개의 공간을 확보, < : 왼쪽정렬, > : 오른쪽 정렬
# first_batch[1]  :라벨, 50개씩 묶어서 50개 존재
# first_batch[0] : 50 - 데이터의 개수, 1 - 채널, 28,28 - 가로세로의 길이

print('{:15s} | {:<25s} | {}' .format('name', 'type', 'size') )
print('{:15s} | {:<25s} | {}' .format('Num of Batch', '', len(train_loader)) )
print('{:15s} | {:<25s} | {}' .format('first_batch', str(type(first_batch)), len(first_batch)) )
print('{:15s} | {:<25s} | {}' .format('first_batch[0]', str(type(first_batch[0])), 
                                      first_batch[0].shape) )
print('{:15s} | {:<25s} | {}' .format('first_batch[1]', str(type(first_batch[1])), 
                                      first_batch[1].shape) )

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        
        # 사용할 레이어 정의
        self.conv1 = nn.Conv2d(1, 32, 3, 1, padding='same') 
        # 1 : 입력 채널의 수, 32 : 32개의 채널을 가지도록 설정, 3 : 커널 사이즈 3*3, 1 : strides 옵션 , padding : 이미지 사이즈 줄어드는 것을 방지 https://wooono.tistory.com/234
        self.conv2 = nn.Conv2d(32, 64, 3, 1, padding='same')
        self.dropout = nn.Dropout2d(0.25)
        self.fc1 = nn.Linear(3136, 1000) # 7(pooling layer 크기)*7*64(채널의 크기) = 3136 입출력의 개수를 정해주어야함
        self.fc2 = nn.Linear(1000, 10)
        
    def forward(self, x): # 모델 구성
        x = self.conv1(x)
        x = F.relu(x)
        x = F.max_pool2d(x, 2) # 가중치 없음
        x = self.conv2(x)
        x = F.relu(x)
        x = F.max_pool2d(x, 2)
        x = self.dropout(x)
        x = torch.flatten(x, 1) # 차원만 바꿈
        x = self.fc1(x)
        x = F.relu(x)
        x = self.fc2(x)
        output = F.log_softmax(x, dim=1) # log_softmax : 연산속도를 조금 더 높일 수 있음
        return output
        
model = CNN().to(device) # 모델 선언하고, 설정한 장치(device)에 올려주는 것
optimizier = optim.Adam(model.parameters(), lr = learning_rate)
criterion = nn.CrossEntropyLoss()
model.train() # 학습을 하겠다는 선언
i = 1
for epoch in range(epoch_num):
    for data, target in train_loader:
        data = data.to(device)
        target = target.to(device)
        optimizier.zero_grad() # 다음에 갱신한 가중치를 사용하기 위해 초기화?..
        output = model(data)
        loss = criterion(output, target)
        loss.backward() # loss를 가지고 역전파
        optimizier.step() # 가중치 업데이트
        if i % 1000 == 0:
            print('Train Step : {}\tLoss: {:.3f}'.format(i, loss.item()))
        i += 1
model.eval() # 평가모드, dropout은 적용되지 않음..?
correct = 0
for data, target in test_loader:
    # data, target = Variable(data, volatile=True), Variable(target)
    
    data = data.to(device)
    target = target.to(device)
    output = model(data)
    prediction = output.data.max(1)[1]
    correct += prediction.eq(target.data).sum() # 맞는 개수 확인하기 위해
    
print('Test set : Accuracy : {:.2f}%' .format(100 * correct / len(test_loader.dataset)))

어렵다...ㅠㅠ
💻 출처 : 제로베이스 데이터 취업 스쿨

profile
#데이터분석 #퍼포먼스마케팅 #데이터 #디지털마케팅

0개의 댓글