일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- unstack
- type hints
- boolean & fancy index
- BOXPLOT
- Python 유래
- Numpy
- seaborn
- dtype
- Operation function
- Array operations
- 부스트캠프 AI테크
- Comparisons
- 정규분포 MLE
- VSCode
- groupby
- namedtuple
- Python
- pivot table
- ndarray
- Numpy data I/O
- 가능도
- 카테고리분포 MLE
- scatter
- subplot
- Python 특징
- python 문법
- 표집분포
- 최대가능도 추정법
- linalg
- 딥러닝
- Today
- Total
또르르's 개발 Story
[13-1] CNN using PyTorch 본문
1️⃣ 설정
1) device 설정 : GPU 사용 or CPU 사용
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
2) Dataset 가지고 오기
PyTorch에서는 기본적으로 datasets를 지원합니다.
from torchvision import datasets,transforms
train 시킬 데이터를 tensor형태로 불러옵니다.
mnist_train = datasets.MNIST(root='./data/',train=True,transform=transforms.ToTensor(),download=True)
test 할 데이터를 tensor형태로 불러옵니다.
mnist_test = datasets.MNIST(root='./data/',train=False,transform=transforms.ToTensor(),download=True)
3) DataLoader : 데이터를 가지고와 generator 형태로 저장
DataLoader을 사용해서 mnist_train data를 BATCH_SIZE만큼 섞어서 불러옵니다.
train_iter = torch.utils.data.DataLoader(mnist_train,batch_size=BATCH_SIZE,shuffle=True,num_workers=1) #num_workers는 멀티프로세스 몇개 사용할 것인지
DataLoader을 사용해서 mnist_test data를 BATCH_SIZE만큼 섞어서 불러옵니다.
test_iter = torch.utils.data.DataLoader(mnist_test,batch_size=BATCH_SIZE,shuffle=True,num_workers=1)
2️⃣ CNN 모델
1) CNN Model
class ConvolutionalNeuralNetworkClass(nn.Module):
def __init__(self,name='cnn',xdim=[1,28,28],
ksize=3,cdims=[32,64],hdims=[1024,128],ydim=10,
USE_BATCHNORM=False):
super(ConvolutionalNeuralNetworkClass,self).__init__()
self.name = name
self.xdim = xdim
self.ksize = ksize
self.cdims = cdims
self.hdims = hdims
self.ydim = ydim
self.USE_BATCHNORM = USE_BATCHNORM
# Convolutional layers - 이 부분이 변경
self.layers = []
prev_cdim = self.xdim[0]
for cdim in self.cdims: # for each hidden layer
self.layers.append(
nn.Conv2d(
in_channels = prev_cdim, # previous channel dimensions (현재는 1)
out_channels= cdim, # 현재 내가 가고자하는 channel dimensions (32채널로 감)
kernel_size = self.ksize, # kernel size
stride=(1,1),
padding=self.ksize//2
)) # convlution
if self.USE_BATCHNORM: # batch norm을 사용할지 말지 결정
self.layers.append(nn.BatchNorm2d(cdim)) # batch-norm
self.layers.append(nn.ReLU(True)) # activation
self.layers.append(nn.MaxPool2d(kernel_size=(2,2), stride=(2,2))) # max-pooling
# kernel_size=(2,2), stride=(2,2) => 절반씩 줄어감
self.layers.append(nn.Dropout2d(p=0.5)) # dropout
prev_cdim = cdim
# Dense layers
self.layers.append(nn.Flatten()) # 한줄로 핌
# 한줄로 폈을 때 몇개의 dimensions가 될지를 prev_hdim이 가지고 있음
# 아래 수식이 어떻게 나오는지 알아보기
prev_hdim = prev_cdim*(self.xdim[1]//(2**len(self.cdims)))*(self.xdim[2]//(2**len(self.cdims)))
for hdim in self.hdims: # prev_hdims -> 1024 -> ReLU -> 128 -> ReLu
self.layers.append(nn.Linear(prev_hdim, hdim, bias=True))
self.layers.append(nn.ReLU(True)) # activation 통과
prev_hdim = hdim
# Final layer (without activation)
# 마지막 나온 output을 layer에 집어넣어줌
self.layers.append(nn.Linear(prev_hdim,self.ydim,bias=True))
# Concatenate all layers
# layer는 list이므로 list에 있는 layer들을 하나씩 쌓게됨
self.net = nn.Sequential() # net은 sequencial로 정의
for l_idx,layer in enumerate(self.layers):
layer_name = "%s_%02d"%(type(layer).__name__.lower(),l_idx)
self.net.add_module(layer_name,layer) # net의 module에 layer을 쌓음, module의 장점은 layer_name을 정할 수 있음
self.init_param() # initialize parameters
def init_param(self):
# parameter는 엄청나게 많아짐
for m in self.modules():
if isinstance(m,nn.Conv2d): # init conv
nn.init.kaiming_normal_(m.weight)
nn.init.zeros_(m.bias)
elif isinstance(m,nn.BatchNorm2d): # init BN
nn.init.constant_(m.weight,1)
nn.init.constant_(m.bias,0)
elif isinstance(m,nn.Linear): # lnit dense
nn.init.kaiming_normal_(m.weight)
nn.init.zeros_(m.bias)
def forward(self,x):
return self.net(x)
PyTorch에서는 convolution 계산도 알아서 해줍니다.
입력 channel (in_channels)와 출력 channel (out_channels)를 넣고 kernel_size, stride, padding option을 넣으면 됩니다.
nn.Conv2d(
in_channels = prev_cdim, # previous channel dimensions (현재는 1)
out_channels= cdim, # 현재 내가 가고자하는 channel dimensions (32채널로 감)
kernel_size = self.ksize, # kernel size
stride=(1,1),
padding=self.ksize//2
)) # convlution
Convolution 후, ReLU -> MaxPooling -> Dropout을 수행합니다.
self.layers.append(nn.ReLU(True)) # activation
self.layers.append(nn.MaxPool2d(kernel_size=(2,2), stride=(2,2))) # max-pooling
# kernel_size=(2,2), stride=(2,2) => 절반씩 줄어감
self.layers.append(nn.Dropout2d(p=0.5)) # dropout
Dense에서는 Flatten을 해서 마지막 convolution parameter를 flat 합니다.
(한 줄로 폈을 때 몇 개의 dimensions이 될지를 prev_hdim이 가지고 있음)
self.layers.append(nn.Flatten()) # 한줄로 핌
prev_hdim = prev_cdim*(self.xdim[1]//(2**len(self.cdims)))*(self.xdim[2]//(2**len(self.cdims)))
for hdim in self.hdims: # prev_hdims -> 1024 -> ReLU -> 128 -> ReLu
self.layers.append(nn.Linear(prev_hdim, hdim, bias=True))
self.layers.append(nn.ReLU(True)) # activation 통과
prev_hdim = hdim
2) loss & optimizer
Class를 선언하고 device (cuda)에 올려줍니다.
이때, x 입력 차원을 [1,28,28], kernel size는 3, convolution dimensions 차원을 14*14*32와 7*7*64, hidden diemensions를 256 -> 128, y 출력 차원을 10으로 선언합니다.
C = ConvolutionalNeuralNetworkClass(
name='cnn',xdim=[1,28,28],ksize=3,cdims=[32,64], # 28*28을 14*14*32로 바꾸고 7*7*64로 변경
hdims=[256, 128],ydim=10).to(device) # hdims는 dense로 256 -> 128 -> 10으로 변경
Loss는 CrossEntroyLoss를 사용합니다. (PyTorch에서 제공)
loss = nn.CrossEntropyLoss()
Optimizer는 Adam을 사용합니다. learn rate를 설정해주어야 합니다.
optm = optim.Adam(M.parameters(),lr=1e-3)
3) Model Parameter 확인
np.set_printoptions(precision=3) # numpy float 출력옵션 변경
n_param = 0
for p_idx,(param_name,param) in enumerate(C.named_parameters()):
param_numpy = param.detach().cpu().numpy() # detach() : 기존 Tensor에서 gradient 전파가 안되는 텐서 생성
n_param += len(param_numpy.reshape(-1)) # 한줄로 만들어줌
print ("[%d] name:[%s] shape:[%s]."%(p_idx,param_name,param_numpy.shape))
print (" val:%s"%(param_numpy.reshape(-1)[:5]))
print ("Total number of parameters:[%s]."%(format(n_param,',d'))) # 총 parameter 수
[0] name:[net.conv2d_00.weight] shape:[(32, 1, 3, 3)].
val:[[[[ 0.128 -0.141 0.979]
[-0.078 0.943 0.342]
[ 0.715 0.312 -0.558]]]
[[[ 0.935 -0.753 0.017]
[-0.075 0.43 -0.476]
[ 0.412 -0.211 0.118]]]
...
[[[ 0.064 -0.504 -0.854]
[ 0.499 -0.435 0.555]
[-0.069 0.214 0.296]]]
[[[-0.066 0.256 -0.065]
[ 1.172 -0.035 -0.331]
[ 0.381 0.172 -0.16 ]]]]
[1] name:[net.conv2d_00.bias] shape:[(32,)].
val:[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0.]
[2] name:[net.conv2d_04.weight] shape:[(64, 32, 3, 3)].
val:[[[[ 0.119 -0.011 0.038]
[ 0.176 0.03 0.06 ]
[ 0.095 0.043 0.026]]
[[ 0.141 -0.081 -0.006]
[ 0.016 0.04 0.039]
[-0.008 -0.132 0.053]]
[[ 0.152 0.138 -0.012]
[-0.08 -0.023 -0.002]
[-0.023 0.04 -0.058]]
...
[[ 0.167 -0.204 -0.099]
[ 0.063 -0.12 0.169]
[-0.061 0.016 -0.121]]
[[ 0.309 0.117 -0.097]
[ 0.012 -0.147 0.037]
[ 0.005 -0.01 0.117]]
[[-0.064 -0.055 0.175]
[-0.115 0.053 0.087]
[ 0.028 -0.051 -0.176]]]
[[[-0.029 0.145 -0.141]
[-0.047 0.027 0.105]
[-0.008 0.033 -0.025]]
[[ 0.039 -0.014 -0.011]
[ 0.034 -0.082 -0.005]
[-0.001 0.062 0.162]]
[[ 0.074 0.016 -0.06 ]
[-0.028 0.114 0.091]
[-0.053 0.125 -0.03 ]]
...
[[ 0.002 -0.052 0. ]
[ 0.066 0.065 0.01 ]
[-0.057 0.082 0.067]]
[[ 0.032 -0.035 0.216]
[-0.136 0.022 -0.057]
[ 0.021 0.24 -0.005]]
[[ 0.088 0.046 0.073]
[ 0.047 -0.026 0.151]
[ 0.066 -0.022 -0.082]]]
[[[-0.087 -0.171 -0.064]
[ 0.024 -0.05 -0.036]
[-0.003 0.007 -0.007]]
[[ 0.001 -0.112 -0.048]
[-0.047 -0.14 0.019]
[-0.051 -0.036 -0.117]]
[[-0.115 0.001 -0.035]
[-0.009 0.104 0.041]
[-0.134 -0.003 -0.063]]
...
[[ 0.158 -0.08 -0.03 ]
[ 0.078 -0.101 0.17 ]
[-0.018 -0.019 -0.137]]
[[-0.039 -0.058 -0.1 ]
[-0.067 0.149 -0.131]
[ 0.009 -0.123 -0.032]]
[[-0.031 -0.067 0.02 ]
[-0.066 -0.031 0.034]
[ 0.119 -0.197 0.169]]]
...
[[[-0.103 -0.041 -0.15 ]
[-0.033 -0.037 0.031]
[-0.044 0.051 -0.092]]
[[-0.015 -0.013 -0.058]
[ 0.067 -0.037 0.073]
[ 0.044 0.118 0.045]]
[[ 0.032 0.005 0.042]
[ 0.113 0.031 -0.023]
[-0.067 -0.044 -0.107]]
...
[[-0.055 -0.002 0.106]
[ 0.004 -0.075 -0.075]
[ 0.011 -0.037 0.047]]
[[-0.03 0.016 0.106]
[ 0.143 -0.093 -0.031]
[ 0.03 -0.148 0.07 ]]
[[ 0.06 -0.041 -0.119]
[-0.01 -0.097 0.138]
[-0.099 -0.02 0.041]]]
[[[-0.015 0.047 -0.028]
[-0.007 0.016 0.002]
[ 0.077 0.009 0.142]]
[[ 0.05 -0.131 0.163]
[-0.015 0.112 0.079]
[-0.025 0.098 0.035]]
[[-0.037 -0.07 -0.067]
[-0.023 -0.093 0.067]
[ 0.088 0.003 0.085]]
...
[[-0.043 0.058 0.002]
[ 0.031 -0.136 -0.171]
[ 0.021 -0.077 0.031]]
[[ 0.051 -0.029 -0.074]
[-0.067 0.148 -0.007]
[-0.023 0.004 -0.1 ]]
[[-0.091 0.024 -0.026]
[-0.159 0.068 -0.131]
[ 0.02 0.066 0.098]]]
[[[ 0.019 0.028 0.06 ]
[-0.007 -0.054 0.042]
[-0.105 -0.069 0.008]]
[[ 0.037 -0.084 -0.002]
[-0.071 0.043 0.145]
[ 0.007 -0.052 0.106]]
[[ 0.01 -0.052 -0.07 ]
[-0.025 -0.101 0.007]
[ 0.082 0.001 -0.06 ]]
...
[[ 0.016 -0.028 0.037]
[ 0.154 -0.077 0.043]
[-0.031 -0.119 -0.019]]
[[-0.052 -0.002 0.016]
[ 0.158 0.067 0.02 ]
[-0.064 0.043 -0.065]]
[[-0.024 0.138 -0.036]
[-0.11 -0.003 0.06 ]
[ 0.089 0.078 -0.001]]]]
[3] name:[net.conv2d_04.bias] shape:[(64,)].
val:[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[4] name:[net.linear_09.weight] shape:[(256, 3136)].
val:[[-0.028 0.011 0.062 ... -0.004 0.026 0.03 ]
[ 0.091 0.002 0.006 ... 0.023 0.016 -0.012]
[ 0.031 -0.025 -0.016 ... 0.016 0.074 0.025]
...
[ 0.027 -0.032 -0.015 ... 0.015 -0.031 -0.014]
[ 0.058 -0.025 0.031 ... -0.013 0.03 0.036]
[ 0.026 0.007 0.021 ... -0.025 0.001 0.001]]
[5] name:[net.linear_09.bias] shape:[(256,)].
val:[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[6] name:[net.linear_11.weight] shape:[(128, 256)].
val:[[ 0.088 -0.026 0.03 ... 0.097 0.09 -0.056]
[ 0.02 0.046 -0.055 ... -0.065 -0.08 0.013]
[-0.227 0.113 0.043 ... -0.124 0.031 -0.048]
...
[ 0.097 -0.056 0.031 ... 0.059 0.031 -0.008]
[-0.103 0.036 -0.135 ... -0.236 0.043 0.028]
[-0.132 0.016 -0.164 ... -0.009 -0.072 0.032]]
[7] name:[net.linear_11.bias] shape:[(128,)].
val:[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0.]
[8] name:[net.linear_13.weight] shape:[(10, 128)].
val:[[-0.058 -0.055 0.058 ... 0.21 -0.063 0.023]
[-0.102 -0.027 -0.039 ... 0.144 -0.132 0.089]
[-0.205 -0.012 0.125 ... -0.287 -0.101 -0.139]
...
[ 0.123 0.142 -0.086 ... 0.054 0.057 0.123]
[-0.206 -0.056 0.063 ... -0.047 -0.098 0.125]
[ 0.098 -0.038 0.272 ... -0.007 -0.278 -0.126]]
[9] name:[net.linear_13.bias] shape:[(10,)].
val:[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
Total number of parameters:[856,074].
detach() : 기존 Tensor에서 gradient 전파가 안 되는 텐서 생성
(단, storage를 공유하기에 detach로 생성한 Tensor가 변경되면 원본 Tensor도 똑같이 변함)
param_numpy = param.detach().cpu().numpy() # detach() : 기존 Tensor에서 gradient 전파가 안되는 텐서 생성
3️⃣ Evaluation Function
1) Evaluation Function
def func_eval(model,data_iter,device):
with torch.no_grad(): # gradients를 업데이트X
model.eval() # evaluate (affects DropOut을 안하고, and BN은 학습되어있는 것을 사용)
n_total,n_correct = 0,0
for batch_in,batch_out in data_iter: # batch_in=data, batch_out=label
y_trgt = batch_out.to(device)
model_pred = model(batch_in.view(-1, 28*28).to(device))
_,y_pred = torch.max(model_pred.data,1)
n_correct += (
(y_pred==y_trgt) # y와 y hat 값을 비교 후, sum
).sum().item()
n_total += batch_in.size(0)
val_accr = (n_correct/n_total)
model.train() # back to train mode
return val_accr
print ("Done")
torch.no_grad()는 Gradients를 업데이트하지 않습니다.
with torch.no_grad(): # gradients를 업데이트X
Evaluation Function에서는 model.eval()과 model.train() 모드를 바꿔주는 것이 중요합니다.
model.eval() # evaluate (affects DropOut and BN)
...
model.train() # back to train mode
DataLoader에서 가지고 온 data_iter이며, train_iter와 test_iter가 존재합니다.
MNIST에서 batch_in은 data (28 x 28 x 256의 tensor)와 batch_out은 label (1 x 256 tensor)로 되어있습니다.
for batch_in,batch_out in data_iter: # batch_in=data, batch_out=label
batch_out은 정답 label이기 때문에 y_trgt 변수에 저장합니다.
y_trgt = batch_out.to(device)
Linear에서 X input이 28*28 = 784로 고정되어있기 때문에 일자로 펴서 넣어줍니다.
model_pred = model(batch_in.view(-1, 28*28).to(device))
n_correct는 y_pred와 y_trgt 값이 같을 때만 sum을 해서 더해줍니다.
item()을 사용하면 숫자 값을 얻을 수 있습니다.
n_correct += (
y_pred==y_trgt # y와 y hat 값을 비교 후, sum
).sum().item()
n_total에다가 batch_in의 첫 번째 dimension 256을 더해줍니다.
n_total += batch_in.size(0)
val_accr는 전체 데이터에서 몇 개가 맞았는지를 나타냅니다.
val_accr = (n_correct/n_total)
2) Initial Evaluation
초반 init을 해주는 과정이며, 초반에는 train_accr와 test_accr의 비율이 떨어지는 것을 알 수 있습니다.
M.init_param() # initialize parameters
train_accr = func_eval(C,train_iter,device)
test_accr = func_eval(C,test_iter,device)
>>> print ("train_accr:[%.3f] test_accr:[%.3f]."%(train_accr,test_accr))
train_accr:[0.101] test_accr:[0.099].
4️⃣ Train
print ("Start training.")
C.init_param() # initialize parameters
C.train() # train mode로 바꿔주는게 중요한게 batch_normalization과 dropout은 inference와 실제 실행에서는 다르기 때문
EPOCHS,print_every = 10,1
for epoch in range(EPOCHS):
loss_val_sum = 0
for batch_in,batch_out in train_iter:
# Forward path
y_pred = C.forward(batch_in.view(-1,1,28,28).to(device)) # 2D로 넣어줌
loss_out = loss(y_pred,batch_out.to(device))
# Update
optm.zero_grad() # reset gradient
loss_out.backward() # backpropagate
optm.step() # optimizer update
loss_val_sum += loss_out
loss_val_avg = loss_val_sum/len(train_iter)
# Print
if ((epoch%print_every)==0) or (epoch==(EPOCHS-1)):
train_accr = func_eval(C,train_iter,device)
test_accr = func_eval(C,test_iter,device)
print ("epoch:[%d] loss:[%.3f] train_accr:[%.3f] test_accr:[%.3f]."%
(epoch,loss_val_avg,train_accr,test_accr))
print ("Done")
Start training.
epoch:[0] loss:[0.378] train_accr:[0.973] test_accr:[0.973].
epoch:[1] loss:[0.125] train_accr:[0.981] test_accr:[0.983].
epoch:[2] loss:[0.089] train_accr:[0.987] test_accr:[0.985].
epoch:[3] loss:[0.073] train_accr:[0.989] test_accr:[0.986].
epoch:[4] loss:[0.062] train_accr:[0.993] test_accr:[0.989].
epoch:[5] loss:[0.053] train_accr:[0.993] test_accr:[0.990].
epoch:[6] loss:[0.045] train_accr:[0.995] test_accr:[0.990].
epoch:[7] loss:[0.040] train_accr:[0.996] test_accr:[0.991].
epoch:[8] loss:[0.039] train_accr:[0.996] test_accr:[0.991].
epoch:[9] loss:[0.037] train_accr:[0.997] test_accr:[0.992].
Done
loss는 y_predict값과 실제 y label값의 차이를 구합니다.
loss_out = loss(y_pred,batch_out.to(device))
optimizer를 사용해서 gradient를 update 합니다.
이때, backward()는 loss만 계산해주고 가중치 업데이트는 하지 않기 때문에, optm.step()을 통해 업데이트해주어야 합니다. optm.zero_grad()는 gradient를 reset 하기 위해 사용되며, 한 번의 mini batch의 backpropagation이 끝나면, 업데이트를 해주고 reset 해서 다시 사용(시작점을 동일하게 하기 위해서)합니다.
# Update
optm.zero_grad() # reset gradient
loss_out.backward() # backpropagate
optm.step() # optimizer update
5️⃣ Test
n_sample = 25
sample_indices = np.random.choice(len(mnist_test.targets), n_sample, replace=False)
test_x = mnist_test.data[sample_indices]
test_y = mnist_test.targets[sample_indices]
with torch.no_grad():
C.eval() # to evaluation mode
y_pred = C.forward(test_x.view(-1,1,28,28).type(torch.float).to(device)/255.)
y_pred = y_pred.argmax(axis=1)
plt.figure(figsize=(10,10))
for idx in range(n_sample):
plt.subplot(5, 5, idx+1)
plt.imshow(test_x[idx], cmap='gray')
plt.axis('off')
plt.title("Pred:%d, Label:%d"%(y_pred[idx],test_y[idx]))
plt.show()
print ("Done")
Sample의 idx를 고르는 작업입니다.
sample_indices = np.random.choice(len(mnist_test.targets), n_sample, replace=False)
Model에 forward 후 나온 predict값의 argmax(index를 구함)를 출력합니다.
with torch.no_grad():
C.eval() # to evaluation mode
y_pred = C.forward(test_x.view(-1,1,28,28).type(torch.float).to(device)/255.)
y_pred = y_pred.argmax(axis=1)
Plt를 사용하여 image를 show 합니다.
plt.figure(figsize=(10,10))
for idx in range(n_sample):
plt.subplot(5, 5, idx+1)
plt.imshow(test_x[idx], cmap='gray')
plt.axis('off')
plt.title("Pred:%d, Label:%d"%(y_pred[idx],test_y[idx]))
plt.show()
'부스트캠프 AI 테크 U stage > 실습' 카테고리의 다른 글
[13-3] Google Image Data 다운로드 (0) | 2021.02.04 |
---|---|
[13-2] Colab에서 DataSet 다루기 (강아지 DataSet) (0) | 2021.02.04 |
[12-2] Optimizers using PyTorch (0) | 2021.02.03 |
[11-3] MLP using PyTorch (0) | 2021.02.02 |
[02-1] Git 사용법 (0) | 2021.01.20 |