AI

심층신경망-실습2

✿(๑❛ڡ❛๑)✿ 2022. 10. 12. 20:15
728x90
SMALL

 

import torch
import torchvision.datasets as data #torchvision: 유명한 데이터 셋, 전처리 할때 사용하는 것 제공
import torchvision.transforms as transforms
import random 

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

#파이썬의 랜덤시드, torch의 랜덤시드, GPU의 랜덤 시드 고정
random.seed(777)
torch.manual_seed(777)
if device == 'cuda':
  torch.cuda.manual_seed_all(777)
  
  

# 학습 파라미터 설정
learning_rate = 0.001
training_epochs = 15  #같은 데이터를 몇번 풀 것인지
batch_size = 100 #100문제 있을때 100문제 한번에 다 풀것인지 아님 10번씩 나눠서 풀것인지 (지금은 6만개의 데이터가 있으니까 6만개중 100개 풀고 채점하고 100개 풀고 채점하고 반복)


#학습하기 위한 데이터 불러오기
mnist_train = data.MNIST(root='MNIST_data/', #root는 데이터를 받아서 어디에 저장할것인지
                         train=True, #train데이터를 받을거면 train에 true로 설정
                         transform=transforms.ToTensor(), #transform은 toTensor로 데이터를 달라는 의미
                         download=True)#데이터 셋이 만약 없으면 다운로드 받아달라는 의미

mnist_test = data.MNIST(root='MNIST_data/',
                         train=False, #train데이터를 받을게 아니면 train에 False로 설정
                         transform=transforms.ToTensor(),
                         download=True)
                         
                         
                         
                         

data_loader = torch.utils.data.DataLoader(dataset=mnist_train, #데이터 잘라주기
                                          batch_size=batch_size,
                                          shuffle=True, #데이터 섞기
                                          drop_last=True)#배치를 나누다보면 맨 마지막 짝이 안맞는 데이터를 버릴것인지 그래도 학습 할것인지

#실습 1


#모델 정의
linear = torch.nn.Linear(784,10,bias=True)

torch.nn.init.normal_(linear.weight) #linear.weight 초기화

model = torch.nn.Sequential(linear).to(device) # 'cuda'->GPU메모리에 저장

loss = torch.nn.CrossEntropyLoss().to(device)
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate) # 0.49


total_batch = len(data_loader)
for epoch in range(training_epochs):
    avg_cost = 0

    for X, Y in data_loader:

        # (100, 1, 28, 28) 크기의 텐서를 (1000, 784) 크기의 텐서로 변형
        X = X.view(-1, 28 * 28).to(device) #view는 reshape와 비슷.
        # one-hot encoding되어 있지 않음
        Y = Y.to(device)
        #%debug

        # 그래디언트 초기화
        optimizer.zero_grad()
        # Forward 계산
        hypothesis = model(X)
        # Error 계산
        cost = loss(hypothesis, Y)
        # Backparopagation
        cost.backward()
        # 가중치 갱신
        optimizer.step()

        # 평균 Error 계산
        avg_cost += cost / total_batch

    print('Epoch:', '%04d' % (epoch + 1), 'cost =', '{:.9f}'.format(avg_cost))

print('Learning finished')


# Test the model using test sets
with torch.no_grad(): 
    # flaot() : GPU=>CPU로 데이터 내리기
    X_test = mnist_test.test_data.view(-1, 28 * 28).float().to(device) #2D를 1D로 교정하기 위해 view사용
    Y_test = mnist_test.test_labels.to(device)

    prediction = model(X_test) #test데이터를 가지고 성능 얼마나 나오나..
    correct_prediction = torch.argmax(prediction, 1) == Y_test
    accuracy = correct_prediction.float().mean()
    print('Accuracy:', accuracy.item()) #0.421399


# 랜덤 테스트
r = random.randint(0, len(mnist_test) - 1)
X_single_data = mnist_test.test_data[r:r + 1].view(-1, 28 * 28).float().to(device)
Y_single_data = mnist_test.test_labels[r:r + 1].to(device)

print('Label: ', Y_single_data.item())
single_prediction = model(X_single_data)
print('Prediction: ', torch.argmax(single_prediction, 1).item())


# 숫자 눈으로 뿌려보기
import matplotlib.pyplot as plt
plt.imshow(X_single_data.reshape(28,28).cpu())
print(Y_single_data)

 

#실습2 -optimizer를 Adam으로 바뀌기만 함- 0.8955

loss = torch.nn.CrossEntropyLoss().to(device)
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) # 0.89
#optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate) # 0.49

#실습3- layer 3개로 늘림-0.9459

linear1 = torch.nn.Linear(784,256,bias=True)
linear2 = torch.nn.Linear(256,256,bias=True)
linear3 = torch.nn.Linear(256,10,bias=True)
relu = torch.nn.ReLU()


torch.nn.init.normal_(linear1.weight)
torch.nn.init.normal_(linear2.weight)
torch.nn.init.normal_(linear3.weight)

# ======================================
# relu는 맨 마지막 레이어에서 빼는 것이 좋다.
# ======================================
# model = torch.nn.Sequential(linear1,relu,linear2,relu,linear3,relu).to(device) # 주의사항
model = torch.nn.Sequential(linear1,relu,linear2,relu,linear3).to(device)

 

#실습4-  xavier사용 - 0.9778

linear1 = torch.nn.Linear(784,256,bias=True)
linear2 = torch.nn.Linear(256,256,bias=True)
linear3 = torch.nn.Linear(256,10,bias=True)
relu = torch.nn.ReLU()

# Random Init => Xavier Init
# torch.nn.init.xavier_normal_
torch.nn.init.xavier_uniform_(linear1.weight)
torch.nn.init.xavier_uniform_(linear2.weight)
torch.nn.init.xavier_uniform_(linear3.weight)

# ======================================
# relu는 맨 마지막 레이어에서 빼는 것이 좋다.
# ======================================
# model = torch.nn.Sequential(linear1,relu,linear2,relu,linear3,relu).to(device) # 주의사항
model = torch.nn.Sequential(linear1,relu,linear2,relu,linear3).to(device)

 

 

#실습5 -깊게 쌓기

linear1 = torch.nn.Linear(784,512,bias=True) #2의 배수가 좋다
linear2 = torch.nn.Linear(512,512,bias=True)
linear3 = torch.nn.Linear(512,512,bias=True)
linear4 = torch.nn.Linear(512,512,bias=True)
linear5 = torch.nn.Linear(512,10,bias=True)
relu = torch.nn.ReLU()

# Random Init => Xavier Init
torch.nn.init.xavier_uniform_(linear1.weight)
torch.nn.init.xavier_uniform_(linear2.weight)
torch.nn.init.xavier_uniform_(linear3.weight)
torch.nn.init.xavier_uniform_(linear4.weight)
torch.nn.init.xavier_uniform_(linear5.weight)

# ======================================
# relu는 맨 마지막 레이어에서 빼는 것이 좋다.
# ======================================
model = torch.nn.Sequential(linear1,relu,
                            linear2,relu,
                            linear3,relu,
                            linear4,relu,
                            linear5).to(device)

 

 

#실습 6-dropout

# 학습 파라미터 설정
learning_rate = 0.001
training_epochs = 15
batch_size = 100
drop_prob = 0.3 #얼마의 비율로 연결고리를 끊을 것인지에 대한 확률값

linear1 = torch.nn.Linear(784,512,bias=True)
linear2 = torch.nn.Linear(512,512,bias=True)
linear3 = torch.nn.Linear(512,512,bias=True)
linear4 = torch.nn.Linear(512,512,bias=True)
linear5 = torch.nn.Linear(512,10,bias=True)
relu = torch.nn.ReLU()
dropout = torch.nn.Dropout(p=drop_prob)

# Random Init => Xavier Init
torch.nn.init.xavier_uniform_(linear1.weight)
torch.nn.init.xavier_uniform_(linear2.weight)
torch.nn.init.xavier_uniform_(linear3.weight)
torch.nn.init.xavier_uniform_(linear4.weight)
torch.nn.init.xavier_uniform_(linear5.weight)

# ======================================
# relu는 맨 마지막 레이어에서 빼는 것이 좋다.
# ======================================
model = torch.nn.Sequential(linear1,relu,dropout,
                            linear2,relu,dropout,
                            linear3,relu,dropout,
                            linear4,relu,dropout,
                            linear5).to(device)



#dropout쓸때 주의할 점
# Test the model using test sets
with torch.no_grad():
    model.eval()  # 주의사항 (dropout=False) : test할때는 연결관계를 끊지 않아야함
    X_test = mnist_test.test_data.view(-1, 28 * 28).float().to(device)
    Y_test = mnist_test.test_labels.to(device)

    prediction = model(X_test)
    correct_prediction = torch.argmax(prediction, 1) == Y_test
    accuracy = correct_prediction.float().mean()
    print('Accuracy:', accuracy.item())
728x90
LIST