model_kmnist_frame = function(x){ x = self$conv1(x) x = nnf_relu(x) x = self$conv2(x) x = nnf_relu(x) x = nnf_max_pool2d(x, 2) x = self$dropout1(x) x = torch_flatten(x, start_dim = 2) x = self$fc1(x) x = nnf_relu(x) x = self$dropout2(x) x = self$fc2(x) output = nnf_log_softmax(x, dim = 1) return(output) }
net = nn_module(classname = "cnn_kmnist", initialize = model_kmnist_init, forward = model_kmnist_frame) model = net()
하이퍼파라미터 설정
모델 학습은 cpu로 하며 Adam Optimizer(Adaptive Moment estimation)를 사용하고 학습율은 0.01로 지정하였다.
1 2
model$to(device = "cpu") optimizer = optim_adam(model$parameters, lr = 0.01)
학습
학습 결과물의 기록을 위해 df_loss를 만들고 학습 진행상황을 잘 파악하기 위해 중간중간 cat() 함수로 Loss가 출력되도록 하였다. 그렇게 총 5 epoch를 학습하는 코드와 그 출력은 다음과 같다.
for(epoch in1:5){ loss_vec = c() for(batch in enumerate(dl)){ # 1875 optimizer$zero_grad() # initialize output = model(batch[[1]]$to(device = "cpu")) # get model predictions loss = nnf_cross_entropy(input = output, target = batch[[2]]$to(device = "cpu")) # calculate loss loss$backward() # calculate gradient optimizer$step() # apply weight updates loss_vec = c(loss_vec, loss$item()) cat(sprintf("\rLoss mean: %3f", mean(loss_vec))) } cat(sprintf("\rLoss at epoch %d: %3f\n\n", epoch, mean(loss_vec))) df_loss[df_loss$epoch == epoch, "loss"] = loss_vec } ## ## Loss at epoch 1: 2.039157 ## ## Loss at epoch 2: 1.874734 ## ## Loss at epoch 3: 1.837059 ## ## Loss at epoch 4: 1.826195 ## ## Loss at epoch 5: 1.812667
모델 저장
torch 패키지에서는 torch_save() 함수로 모델 객체를 별도의 파일로 저장하고 torch_load() 함수로 이를 불러오는데 아직 torch 패키지에서는 “This function is experimental, don’t use for long term storage.” 라며 조심스러운 메세지를 torch_save() 함수의 도움말에 적어놓았다.
여기서 모델의 출력값을 정제할 때 각 row의 최대값의 위치를 얻기위해 which.max() 함수를 사용했다. 좀 더 자세하게 확인하고자 한다면 모델의 구조를 다시 보자. 말단에 nnf_log_softmax() 함수로 softmax를 정의한 것을 알 수 있다. 그래서 각 class별 확률 값이 log로 출력되는데 이 부분은 tensor_pred 객체에서 확인할 수 있다.
아무튼 첫 32개 데이터만 확인했지만 만족할만한 정확도가 아니라… 좀 더 학습해야 하지 않을까 한다.