※ html파일 링크 : http://www.datamarket.kr/xe/?module=file&act=procFileDownload&file_srl=63462&sid=b20955b1ef5715549e5b6bbf22c8adcc
# 1번 과제
1 2 | #!/usr/bin/env python # coding: utf-8 # In[ ]: import numpy as np import pandas as pd from PIL import Image import matplotlib.pyplot as plt from sklearn.metrics import accuracy_score # In[3]: from google.colab import drive drive.mount('/content/drive') # In[4]: train_data = pd.read_csv('/content/drive/My Drive/data/fashionmnist/fashion-mnist_train.csv') test_data = pd.read_csv('/content/drive/My Drive/data/fashionmnist/fashion-mnist_test.csv') train_data.head() # In[5]: # 이미지 데이터와 라벨 데이터 분리 train_x = np.array(train_data.iloc[:,1:]) train_y = np.array(train_data['label']) test_x = np.array(test_data.iloc[:,1:]) test_y = np.array(test_data['label']) print(train_x.shape) print(train_y.shape) print(test_x.shape) print(test_y.shape) # 시각화 # 임의로 3번사진을 가져옵니다. image_array = np.array(train_x[3]).reshape(28,28) pic = Image.fromarray(image_array.astype('uint8')) plt.imshow(pic) # In[6]: from torch.utils.data import DataLoader import torch.nn.functional as F import torch from torch import nn if torch.cuda.is_available(): device = torch.device('cuda') else: device = torch.device('cpu') print('Using PyTorch version:', torch.__version__, ' Device:', device) # In[ ]: # 파라미터 선택 random_seed = 0 learning_rate = 0.0001 num_epochs = 40 batch_size = 32 input_size = 784 h1_size = 512 h2_size = 512 output_size = 10 # In[8]: # 데이터셋을 클래스로 만들고 파이토치의 dataloader로 만들어주면 손쉽게 훈련에서 사용할 수 있습니다. # 함수들은 dataloader로 데이터를 끌고올 때 사용됩니다. class FashionDataset(torch.utils.data.Dataset): def __init__(self, X, Y): # import and initialize dataset self.X = X self.Y = Y def __getitem__(self, idx): return self.X[idx], self.Y[idx] def __len__(self): # returns length of data return len(self.X) dataset = FashionDataset(train_x, train_y) testset = FashionDataset(test_x, test_y) print(type(dataset)) print(len(dataset)) dataloader = torch.utils.data.DataLoader(dataset, batch_size = batch_size, shuffle = True) test_loader = torch.utils.data.DataLoader(testset, batch_size = batch_size, shuffle = True) dataloader # In[ ]: # 다층 신경망 클래스 정의 class MLP(nn.Module): def __init__(self, input_size, output_size, h1_size, h2_size): super(MLP, self).__init__() # 파라미터 정의 self.input_size = input_size self.output_size = output_size self.h1_size = h1_size self.h2_size = h2_size # 신경망 정의 # Sequential로 한꺼번에 묶어서 처리 할 수 있습니다. self.layers = nn.Sequential( nn.Linear(self.input_size, self.h1_size, bias=True), nn.ReLU(), nn.Linear(self.h1_size, self.h2_size, bias=True), nn.ReLU(), nn.Linear(self.h2_size, self.output_size, bias=True) ) def forward(self, x): # 학습을 위해 텐서 shape을 바꿔줌 x = x.view(-1, 784) x = self.layers(x.float()) return x # In[10]: my_mlp = MLP(input_size, output_size, h1_size, h2_size).to(device) print(my_mlp) # In[ ]: optimizer = torch.optim.Adam(my_mlp.parameters(), lr=0.0001) criterion = nn.CrossEntropyLoss() # In[68]: # 성능 측정 데이터를 쌓을 dictionary performance = {'test_acc': [],'test_loss': []} for epoch in range(num_epochs): # train my_mlp.train() # iter, image, label 반복문 for i, (x, y) in enumerate(dataloader): # 모델에 데이터를 흘려 넣어줍니다. x, y = x.to(device), y.to(device) outputs = my_mlp(x) loss = criterion(outputs, y) # optimizer의 변화도 버퍼(gradient buffer)를 0으로 설정하고, 무작위 값으로 역전파를 합니다. optimizer.zero_grad() loss.backward() # 가중치 업데이트 optimizer.step() # eval y_pred, y_true = [], [] test_acc = 0 test_loss = 0 my_mlp.eval() with torch.no_grad(): for x, y in test_loader: x, y = x.to(device), y.to(device) # Loss outputs = my_mlp(x) # 예측 label loss = criterion(outputs, y) test_loss += loss.item() # Accuracy y_true += list(y.cpu()) # 정답 label y_pred += list(np.argmax(F.softmax(outputs).cpu(), axis=1)) # 소프트맥스 확률값에서 argmax로 제일 높은 인덱스를 뽑자 # sklearn의 정확도 측정 모듈 accuracy_score acc = accuracy_score(y_true, y_pred) test_acc += acc # 누적된 통계치들에 batch를 반복한 횟수로 나누자 # 반복 횟수 = batch size 32로 잡았으면 testset size가 1만이니까 10k / 32 해서 313 test_acc = test_acc / len(test_loader.batch_sampler) test_loss = test_loss / len(test_loader.batch_sampler) performance["test_acc"].append(test_acc) performance["test_loss"].append(test_loss) # 성능 출력 if epoch % 5 == 0: print(f"Epoch: {epoch}, Test Loss: {test_loss:.5f}, Test Acc: {test_acc:.5f}") # ### 참고자료 # * https://medium.com/biaslyai/pytorch-introduction-to-neural-network-feedforward-neural-network-model-e7231cff47cb # * https://www.kaggle.com/pinocookie/pytorch-simple-mlp # * https://tutorials.pytorch.kr/beginner/pytorch_with_examples.html | cs |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | #!/usr/bin/env python # coding: utf-8 # In[6]: import torch import numpy as np import torch.nn as nn import torch.nn.functional as F if torch.cuda.is_available(): device = torch.device('cuda:0') else: device = torch.device('cpu') print('Using PyTorch version:', torch.__version__, ' Device:', device) # In[ ]: input_size = 32 * 32 * 3 hidden_size = 128 output_size = 10 epoch_size = 50 batch_size = 32 learning_rate = 0.0001 # In[8]: import torchvision import torchvision.transforms as transforms import torchvision.models as models import torch.optim as optim # CIFAR 10 dataload # torchvision에서 여러 데이터를 제공한다. 만약 여기에 없으면 어쩔 수 없이 전처리를 다 해줘야 한다... transform = transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size, shuffle=True, num_workers=2) testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform) testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size, shuffle=False, num_workers=2) # In[9]: trainloader.dataset # ## Batch Normalization # * 기존의 신경망 성능을 높이려는 시도들이 있어왔다. 대표적으로 input과 weight을 표준화시킨는 것. # * 그러나 문제는 hidden layer가 학습을 진행하면서 input distribution이 불안정해지게 된다.이를 Internal Covariate Shift # 라고 한다. 예를 들자면 가족오락관에서 귀마개를 끼고서하는 게임에서 사람을 거칠 수록 이상한 정답이 나오는 이치와 비슷하다고 함. 두 번째 가중치 값이 있다면 이 가중치는 이전 가중치 W1와 입력값에 따라 분포가 달라진다. 즉 W2가 불안정해진다. # # 1단계 # * hidden input -> Batch Normalization -> Activation Funciton 의 구조를 가지면 된다. # * 보통 신경망은 mini batch로 학습하니 각 batch마다 표준화를 시킨다. # * batch_size = m일 때 # * $ {\ μ_β} = {1 \over m} * {\sum_i}X_iW_i $ (배치 평균) # * $ {\ σ_β} = {1 \over m} * {\sum_i}(X_iW_i - μ_β$)2 (배치 표준편차) # * Activation $ a = f({\ XW_i - μ_β \over \ σ_β})$ # # 2단계 # * 그러나 이 상태라면 grdient update에서 bias가 무시된다. sigmoid의 경우 활성화 결과값들이 sigmoid의 중간 선형부분에 위치하게 된다. 이런식으로 나쁜 Normalization을 고칠 감마와 베타라는 파라미터가 추가된다. # * $ {\ a} = γ*({\ XW_i - μ_β \over \ σ_β}) + β $ (이 친구도 마치 또 다른 신경망 같다. 얘네도 학습이 된다는 것) # * 이 값을 실제 신경망의 활성화 함수 입력으로 넣어주면 된다. # # Test단계 # * 평가 시에는 학습 때 썼던 Batch별 통계값의 평균을 사용하거나 move average를 사용한다. # * $ \hat{\mu} \gets \alpha \hat{\mu} + (1-\alpha) \mu_{\mathcal{B}}^{(i)}$ (알파는 momentum값으로 누구는 0.9를 사용하라고 하고, 파이토치에서는 default가 0.1이다.) # * $ \hat{\sigma} \gets \alpha \hat{\sigma} + (1-\alpha) \sigma_{\mathcal{B}}^{(i)}$ # # # 장점 # # # 1. bias 무시 X # 2. hidden input 표준화 # 3. vanishing gradient 방지(actiation값을 적당한 크기로 유지) # 4. interval covariate shift 방지 # 5. Dropout 안해도 됨. 같은 효과를 내기 떄문이라고 함 # 6. Learning Rate 크게 해도 됨 -> 시간단축 # # # 텐서플로나 파이토치에서 쉽게 신경망에 추가할 수 있는 클래스를 제공한다. # ## 드롭아웃 # * 과적합을 막는 방법 중 하나 # * 뉴런의 연결을 임의로 삭제 # * 단, 테스트 시 모든 노드 사용함. # * 일정 확률로 강력한 뉴런이 무시될 수도 있다. 강력한 뉴런은 학습 데이터에 확신을 가지고 있다는 뜻이고, 그러한 뉴런이 많으면 일반화 능력이 떨어질 수 있다. # In[10]: class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.fc1 = nn.Linear(input_size, hidden_size) # input, output self.fc2 = nn.Linear(hidden_size, output_size) def forward(self, x): x = x.view(-1, self.num_flat_features(x)) x = F.relu(self.fc1(x)) x = self.fc2(x) return x def num_flat_features(self, x): size = x.size()[1:] num_features = 1 for s in size: num_features *= s return num_features # Dropout class DropoutNet(nn.Module): def __init__(self): super(DropoutNet, self).__init__() self.fc1 = nn.Linear(input_size, hidden_size) # input, output self.fc2 = nn.Linear(hidden_size, output_size) self.dropout = nn.Dropout(p=0.5) def forward(self, x): x = x.view(-1, self.num_flat_features(x)) x = self.dropout(F.relu(self.fc1(x))) x = self.fc2(x) return x def num_flat_features(self, x): size = x.size()[1:] num_features = 1 for s in size: num_features *= s return num_features # Batch Normalization class BNNet(nn.Module): def __init__(self): super(BNNet, self).__init__() self.linear1 = nn.Linear(input_size, hidden_size) self.bn1 = nn.BatchNorm1d(hidden_size) self.linear2 = nn.Linear(hidden_size, output_size) def forward(self, x): x = x.view(-1, self.num_flat_features(x)) x = F.relu(self.bn1(self.linear1(x))) x = self.linear2(x) return x def num_flat_features(self, x): size = x.size()[1:] num_features = 1 for s in size: num_features *= s return num_features # 골라서 해보자 # net = Net().to(device) # net = DropoutNet().to(device) net = BNNet().to(device) print(net) # In[ ]: import torch.optim as optim criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(net.parameters(), lr=learning_rate) # In[12]: performance = {'test_acc': [],'test_loss': []} for epoch in range(epoch_size): net.train() for i, (x, y) in enumerate(trainloader): inputs, labels = x.to(device), y.to(device) optimizer.zero_grad() outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() total_label = 0 correct = 0 test_loss = 0 net.eval() with torch.no_grad(): for x, y in testloader: images, labels = x.to(device), y.to(device) outputs = net(images) loss = criterion(outputs, labels) test_loss += loss.item() _, predicted = torch.max(outputs, 1) correct += (predicted == labels).sum().item() total_label += labels.size(0) test_acc = 100*correct/total_label test_loss = test_loss / len(testloader.batch_sampler) performance["test_acc"].append(test_acc) performance["test_loss"].append(test_loss) if epoch % 5 == 0: print(f"Epoch: {epoch}, loss: {test_loss:.5f}, acc: {test_acc:.5f}") # In[ ]: # 시각화 # 갓대웅님의 시각화 코드 참조 했습니다. fig = plt.figure() ax_acc = fig.add_subplot() ax_acc.plot(range(epoch_size), performance['test_acc'], label='acc', color='darkred') ax_acc.grid(linestyle='--', color='lavender') plt.xlabel('epochs') plt.ylabel('Validation Accuracy(%)') ax_loss = ax_acc.twinx() ax_loss.plot(range(epoch_size), performance['test_loss'], label='loss', color='darkblue') ax_loss.grid(linestyle='--', color='lavender') plt.ylabel('Validation Error') ax_loss.yaxis.tick_right() plt.show() # * Basic NN # * hidden_size = 128, LR = 0.0001 # # * 빠르게 과적합하는 모습을 확인할 수 있었습니다. #  # # * Dropout #  # # * Batch Normalize #  # * 60까지 찍어주고 있습니다 | cs |
Designed by sketchbooks.co.kr / sketchbook5 board skin
Sketchbook5, 스케치북5
Sketchbook5, 스케치북5
Sketchbook5, 스케치북5
Sketchbook5, 스케치북5