05-02 06:32
Notice
Recent Posts
Recent Comments
관리 메뉴

Scientific Computing & Data Science

[Artificial Intelligence / TensorFlow] R-TensorFlow 예제 - Multilayer Perceptron을 이용한 MNIST 손글씨 숫자 인식 본문

Artificial Intelligence/TensorFlow

[Artificial Intelligence / TensorFlow] R-TensorFlow 예제 - Multilayer Perceptron을 이용한 MNIST 손글씨 숫자 인식

cinema4dr12 2017. 7. 31. 19:50

Written by Geol Choi | 



이번 포스팅에서는 MNIST 손글씨 숫자(Hand-written Digits) 데이터세트를 활용하여 TensorFlow에서 Multilayer Perceptron(MLP) 또는 Feedforward Neural Networks를 구현하는 방법에 대해 알아보도록 하겠습니다. MLP에 대한 이론을 소개하는 포스팅은 아니므로 이론적으로 궁금하신 분은 이 링크를 통해 자세한 정보를 얻으실 수 있습니다.


내용의 진행은 R-TensorFlow를 기준으로 하였으나, Python-TensorFlow의 경우에도 동일한 함수이름으로 유사하게 적용이 가능합니다.

진행 순서는 작성한 코드의 순서를 따르며, 중간중간 핵심적인 개념과 전체 흐름을 파악하는데 있어 도움이 될 만한 그림을 첨부하였습니다.

1. 필요한 패키지 로딩

본 포스팅에서 필요로 하는 R의 패키지 라이브러리는 tensorflow와 결과를 그래프로 시각화하기 위한 plotly입니다. 물론, 시각화를 반드시 plotly로 할 필요는 없으며 R의 Built-in 패키지인 graph를 사용하거나 ggplot을 사용해도 무방합니다.


상기 패키지 라이브러리를 로딩하는 코드는 다음과 같습니다:


1
2
3
4
5
6
## import libraries
if (! ("tensorflow" %in% rownames(installed.packages()))) { install.packages("tensorflow") }
base::library(tensorflow)
 
if (! ("plotly" %in% rownames(installed.packages()))) { install.packages("plotly") }
library(plotly)
cs


2. MNIST 데이터세트 임포트

TensorFlow를 통해 MNIST 데이터세트를 임포트할 수 있습니다:


1
2
3
## import MNIST data
datasets <- tensorflow::tf$contrib$learn$datasets
mnist <- datasets$mnist$read_data_sets("MNIST-data", one_hot = TRUE)
cs


임포트한 MNIST 데이터세트에 대한 좀 더 자세한 내용은 이 링크를 참고하시기 바랍니다.

3. 학습 파라미터 정의

학습에서 요구하는 몇 가지 파라미터를 정의합니다:


1
2
3
4
5
## parameters
learning_rate <- 0.001
training_epochs <- 15
batch_size <- 100L
display_step <- 1
cs


learning_rate, training_epochs, batch_size, display_step은 각각 학습률, 학습에 대한 반복 계산 횟수, 한 번에 학습시킬 배치 크기, 학습 과정에서 중간중간의 결과를 표시할 주기를 의미합니다. 아마도 본 포스팅은 MLP를 R-TensorFlow에서 어떻게 구현하느냐에 초점을 맞춘 것이며 MLP의 이론에 관한 것은 아니므로 각 파라미터의 자세한 의미를 설명하지는 않습니다.

4. 네트워크 파라미터 정의

MLP 네트워크 구성을 정의하는 파라미터들을 설정합니다. 이에 앞서 포스팅에서 정의하는 MLP 네트워크 구성은 다음 이미지와 같습니다:





우선, Input \(x_{i} \ (i=1,...,784)\)은 MNIST의 각 28×28 사이즈의 이미지에 대한 전체 픽셀 수로 총 784개입니다. Hidden Layer 1 \(h_{1,j} \ (j=1,...,256)\)과 Hidden Layer 2 \(h_{2,k} \ (k=1,...,256)\)로 각각 256개 노드를 가지고 있으며, Output \(y_{i} \ (i=1,...,10)\)는 숫자 0~9의 10개의 Class를 가지고 있습니다.


따라서, 네트워크를 구성하는 파라미터 변수를 다음 코드와 같이 정의하였습니다:


1
2
3
4
5
## network parameters
n_hidden_1 <- 256L # 1st layer number of features
n_hidden_2 <- 256L # 2nd layer number of features
n_input <- 784L # MNIST data input (img shape: 28*28)
n_classes <- 10L # MNIST total classes (0-9 digits)
cs

5. placeholder 변수 설정

학습을 진행하는 동안 Input(x)과 Output(y)으로 공급할 변수인 placeholder 변수를 설정합니다:


1
2
3
## tf Graph input
<- tensorflow::tf$placeholder(tensorflow::tf$float32, tensorflow::shape(NULL, n_input))
<- tensorflow::tf$placeholder(tensorflow::tf$float32, tensorflow::shape(NULL, n_classes))
cs


tensorflow::shape()의 첫번째 파라미터를 NULL로 설정한 이유는, 학습할 배치 사이즈에 따라 이 파라미터가 정해지기 때문입니다. 예를 들어, 각 학습 Epoch 마다 배치 사이즈 100으로 주어지면, x의 Dimension은 100-by-784이며, y의 Dimension은 100-by-10이 됩니다.

6. 네트워크 변수 정의 및 초기화

네트워크 변수라 함은, Weights(W)와 Biases(b)를 의미합니다. 네트워크 변수를 정의 및 초기화한다는 것은, 이들 Weights와 Biases의 Dimension과 초기값으로 정규분포를 이용하여 난수를 발생시켜 이 값을 초기값으로 설정한다는 의미입니다.


빠르게 이해할 수 있도록 먼저 코드를 살펴 보겠습니다:


1
2
3
4
5
6
7
8
9
10
## store layers weight & bias
weights <- base::list(
  'h1'= tensorflow::tf$Variable(tf$random_normal(base::c(n_input, n_hidden_1)), dtype=tf$float32),
  'h2'= tensorflow::tf$Variable(tf$random_normal(base::c(n_hidden_1, n_hidden_2)), dtype=tf$float32),
  'out'= tensorflow::tf$Variable(tf$random_normal(base::c(n_hidden_2, n_classes)), dtype=tf$float32))
 
biases <- base::list(
  'b1'= tensorflow::tf$Variable(stats::rnorm(n=n_hidden_1), dtype=tf$float32),
  'b2'= tensorflow::tf$Variable(stats::rnorm(n=n_hidden_2), dtype=tf$float32),
  'out'= tensorflow::tf$Variable(stats::rnorm(n=n_classes), dtype=tf$float32))
cs


위의 코드에서 볼 수 있는 바와 같이, weightsbiases는 R의 List 변수입니다. 각각에 대한 설명은 다음과 같습니다:


  • weights$h1 : Input과 Hidden Layer 1을 연결하는 각 네트워크에 대한 가중치입니다. Dimension은 Input의 개수(n_input(=784)) × Hidden Layer 1의 노드 개수(n_hidden_1(=256))입니다.

  • weights$h2 Hidden Layer 1과 Hidden Layer 2를 연결하는 각 네트워크에 대한 가중치입니다. Dimension은 Hidden Layer 1의 노드 개수(n_hidden_1(=256)) × Hidden Layer 2의 노드 개수(n_hidden_2(=256))입니다.

  • weights$out Hidden Layer 2와 Output을 연결하는 각 네트워크에 대한 가중치입니다. Dimension은 Hidden Layer 2의 노드 개수(n_hidden_2(=256)) × Output의 노드 개수(n_classes(=10))입니다.

  • biases$b1 : Hidden Layer 1의 각 노드에 더해지는 Bias 값입니다. 벡터 형태로 주어지면 벡터 길이는 Hidden Layer 1의 노드 개수(n_hidden_1(=256))입니다.

  • biases$b2 : Hidden Layer 2의 각 노드에 더해지는 Bias 값입니다. 벡터 형태로 주어지면 벡터 길이는 Hidden Layer 2의 노드 개수(n_hidden_2(=256))입니다.

  • biases$out : Output의 각 노드에 더해지는 Bias 값입니다. 벡터 형태로 주어지면 벡터 길이는 Output의 노드 개수(n_output(=10))입니다.

7. 네트워크 모델 구성

네트워크 모델은 다음 이미지와 같습니다:



다소 복잡해 보일지 모르겠지만, 두 개의 행렬을 곱한 후 이 결과와 벡터를 더하고 활성화 함수를 통해 출력시키는 연산이 계속 반복되는 것을 알 수 있습니다.


그림에서 ⓧ는 두 행렬 간의 행렬곱을, \(\sum\)은 행렬과 벡터의 덧셈을(사실 행렬의 각 행에 벡터를 더하는 것), f는 활성화 함수(Activation Function, 여기서는 ReLU가 사용됨)를 나타냅니다.


또한, 각 변수에 대한 Dimension을 표시하였는데 이들 중 "?"는 배치 사이즈(Batch Size)로 교체할 수 있습니다.


이 구조를 코드로 옮기면 다음과 같습니다:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
## create model
multilayer_perceptron <- function(x, weights, biases) {
  # hidden layer with RELU activation
  layer_1 <- tensorflow::tf$add(tensorflow::tf$matmul(x, weights$h1), biases$b1)
  layer_1 <- tensorflow::tf$nn$relu(layer_1)
 
  # hidden layer with RELU activation
  layer_2 <- tensorflow::tf$add(tensorflow::tf$matmul(layer_1, weights$h2), biases$b2)
  layer_2 <- tensorflow::tf$nn$relu(layer_2)
  
  # output layer with linear activation
  out_layer <- tensorflow::tf$add(tensorflow::tf$matmul(layer_2, weights$out), biases$out)
  return(out_layer)
}
cs


그리고 예측 모델(pred)에서 이를 호출합니다:


1
2
## construct model
pred <- multilayer_perceptron(x, weights, biases)
cs

8. 손실함수(Loss Function)와 옵티마이저(Optimizer) 정의

손실함수로 TensorFlow가 제공하는 함수인 tensorflow::tf$nn$softmax_cross_entropy_with_logits()를 사용하는데 Softmax의 Cross Entropy를 계산하는 함수입니다. 즉, 이 함수의 파라미터인 logitslabels 간의 Cross Entropy를 계산하는데 이 결과를 tensorflow::tf$reduce_mean() 함수를 이용하여 배치(Batch) 간의평균을 계산한 결과가 손실값이 됩니다.


TensorFlow가 제공하는 Optimizer는 Adadelta, AdagradDAAdagrad, Adam 등이 있는데 이 중 Adam을 Optimizer로 선택하였습니다. Adam Optimizer에 대해 수학적으로 어떻게 구현되어 있는지 자세하게 알고 싶으시면 이 링크를 통해 관련 논문을 보실 수 있습니다. 이 논문에서 Adam Optimizer는 기본적으로는 1차 미분값을 이용하는 Newton 방법을 근간으로 하나 적응형(Adaptive) 저차수(Low-Order) 모멘트(Moment)를 이용하여 기존의 Newton 방법에 비해 적은 메모리를 차지하면서도 보다 효율적으로 최적화를 계산하는 방법이라고 설명되어 있습니다. Adam Optimizer의 TensorFlow 함수는 tensorflow::tf$train$AdamOptimizer()입니다.


손실값(또는 Cost)와 Optimizer를 정의한 코드는 다음과 같습니다:


1
2
3
## define loss and optimizer
cost <- tensorflow::tf$reduce_mean(tensorflow::tf$nn$softmax_cross_entropy_with_logits(logits=pred, labels=y))
optimizer <- tensorflow::tf$train$AdamOptimizer(learning_rate=learning_rate)$minimize(cost)
cs

9. 변수 및 세션 초기화

Epoch의 진행에 따라 Cost가 어떻게 수렴되어 가는지를 그래프로 시각화 하기 위해 이를 담을 Data Frame의 크기를 정의하고 이름을 정하였습니다:


1
2
3
4
## initialize variable for plotting
learning_val <- base::matrix(data=0.0, nrow=training_epochs, ncol=2)
learning_val <- base::as.data.frame(learning_val)
base::names(learning_val) <- base::c("Epoch""Cost")
cs


그리고, 글로벌 변수를 초기화 하고:


1
2
## initialize the variables
init <- tensorflow::tf$global_variables_initializer()
cs


TensorFlow 세션을 정의하고 이를 초기화 하였습니다:


1
2
3
## create session and initialize  variables
sess <- tensorflow::tf$Session()
sess$run(init)
cs

10. 학습

학습을 하는 코드는 다음과 같은데, :


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
## train
# training cycle
total_batch <- base::as.integer(mnist$train$num_examples / batch_size)
 
for(epoch in 1:training_epochs) {
  avg_cost <- 0.0
  
  # loop over all batches
  for(i in 1:total_batch) {
    # load batch_size training examples in each training iteration
    batches <- mnist$train$next_batch(base::as.integer(batch_size))
    batch_xs <- batches[[1]]
    batch_ys <- batches[[2]]
    
    # Run optimization op (backprop) and cost op (to get loss value)
    sess$run(optimizer, feed_dict = dict(x = batch_xs, y = batch_ys))
    
    # Compute average loss
    avg_cost <- avg_cost + sess$run(cost, feed_dict = dict(x = batch_xs, y = batch_ys)) / total_batch
  }
  
  learning_val[epoch,] <- c(epoch, avg_cost)
  
  # Display logs per epoch step
  if((epoch %% display_step) == 0) {
    base::print(base::sprintf("Epoch: %04d, cost: %.9f", epoch, avg_cost))
  }
}
cs


이전 포스팅의 학습과 방식이 거의 동일하기 때문에 따로 설명을 하지는 않겠습니다.


다만, Line 9에 보시면 각 Epoch 마다 전체 데이터세트를 미니-배치(Mini-Batch)로 쪼개어 학습시키는 Nested Loop가 있다는 것을 주목하시기 바랍니다.


Epoch가 진행됨에 따라 Cost값의 결과는 다음과 같았습니다:


[1] "Epoch: 0001, cost: 151.473264916"
[1] "Epoch: 0002, cost: 38.744829778"
[1] "Epoch: 0003, cost: 24.402429838"
[1] "Epoch: 0004, cost: 16.837283052"
[1] "Epoch: 0005, cost: 12.207336739"
[1] "Epoch: 0006, cost: 8.795428428"
[1] "Epoch: 0007, cost: 6.467744220"
[1] "Epoch: 0008, cost: 4.797851075"
[1] "Epoch: 0009, cost: 3.517698495"
[1] "Epoch: 0010, cost: 2.575255539"
[1] "Epoch: 0011, cost: 1.912107631"
[1] "Epoch: 0012, cost: 1.346243353"
[1] "Epoch: 0013, cost: 0.958282848"
[1] "Epoch: 0014, cost: 0.736839636"
[1] "Epoch: 0015, cost: 0.505149304"
[1] "Optimization Finished!"

11. 학습된 모델 평가

학습된 모델 평가는 예측 모델(변수 pred로 저장되어 있음)과 실제 분류되어 있는 라벨을 비교하는 것입니다. 즉, 학습을 통해 결정된 Weights와 Biases로 얻어진 pred의 값 중 최대값의 인덱스와 라벨링 되어 있는 Output(y)의 최대값 인덱스를 비교하는 것입니다. y는 One Hot Vector로 속한 Class의 위치에서만 1이며 나머지는 0임을 기억하시기 바랍니다.


상기 언급한 내용을 토대로 작성된 코드는 다음과 같습니다:


1
2
## test trained model
correct_prediction <- tensorflow::tf$equal(tensorflow::tf$argmax(pred, 1L), tensorflow::tf$argmax(y, 1L))
cs


tensorflow::tf$argmax()는 주어진 벡터의 최대값이 존재하는 인덱스를 찾는 함수이며, tensorflow::tf$equal()은 파라미터로 주어진 두 값이 일치하는지 판단하는 함수입니다.

12. 정확도 계산

학습을 통해 얻어진 예측 모델이 얼마나 정확도를 갖는지 계산하려면 테스트 데이터세트에 대하여 예측 모델을 통해 얻어진 결과와 실제 결과(이를 Ground Truth Label이라고 합니다)를 비교하여 전체 데이터 개수에 대하여 몇 개나 일치하는지 알아보는 것입니다. 다음 코드를 살펴보겠습니다:


1
2
3
4
## calculate accuracy
accuracy <- tensorflow::tf$reduce_mean(tensorflow::tf$cast(correct_prediction, tensorflow::tf$float32))
res <- base::sprintf("Accuracy: %.5f", sess$run(accuracy, feed_dict = dict(x = mnist$test$images, y = mnist$test$labels)))
base::print(res)
cs


Line 2에서 accuracy라는 모델을 정의하였는데, 섹션 11에서 정의한 correct_prediction 모델에 대하여 tensorflow::tf$reduce_mean() 함수를 통해 평균을 구합니다. 평균을 구한다는 것은, correct_prediction 모델이 갖고 있는 값이 0 또는 1이므로 결국 전체 테스트 데이터 개수에 대하여 예측 모델 결과값과 Ground Truth Label 값이 일치하는 개수의 비율을 얻을 수 있는 것입니다.


따라서, Line 3에서 accuracy 모델에 테스트 데이터세트를 공급하여 값을 얻고 Line 4에서 이 결과를 출력하였습니다. 출력 결과는 다음과 같았습니다(이 결과는 랜덤 초기화를 통해 실행되므로 실행 시기마다 약간씩 다르게 나옵니다):


[1] "Accuracy: 0.94440"


MLP의 결과는 지난 포스팅의 회선신경망(Convolutional Neural Networks; CNN)의 결과(0.976562)에 비하면 다소 정확도가 떨어지는 것을 확인할 수 있습니다. 정확한 이유는 알기 어렵지만 CNN의 좀 더 Deep하게 학습을 하기 때문에 분류에 대한 결과가 더 좋은 것이 아닐까 추측해 봅니다.

13. 결과 그래프 출력

Epoch의 진행에 따라 Cost값이 어떻게 수렴되는지 그래프를 통해 한 눈에 확인할 수 있습니다. Epoch 15번째에서 거의 0에 가깝게(즉, Loss가 거의 0에 가깝게) 수렴되는 것을 확인하였습니다.


14. 전체 코드

본 포스팅의 마지막 순서로 언급된 전체 코드를 첨부합니다:


MLP.R

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
#############################################################################
# A Multilayer Perceptron implementation example using TensorFlow library.
#############################################################################
# @Author: Geol Choi, phD.(cinema4dr12@gmail.com)
# @Date: July 16, 2017
#############################################################################
 
## remove existing variables
base::rm(list = ls())
 
## import libraries
if (! ("tensorflow" %in% rownames(installed.packages()))) { install.packages("tensorflow") }
base::library(tensorflow)
 
if (! ("plotly" %in% rownames(installed.packages()))) { install.packages("plotly") }
library(plotly)
 
## import MNIST data
datasets <- tensorflow::tf$contrib$learn$datasets
mnist <- datasets$mnist$read_data_sets("MNIST-data", one_hot = TRUE)
 
## parameters
learning_rate <- 0.001
training_epochs <- 15
batch_size <- 100L
display_step <- 1
 
## network parameters
n_hidden_1 <- 256L # 1st layer number of features
n_hidden_2 <- 256L # 2nd layer number of features
n_input <- 784L # MNIST data input (img shape: 28*28)
n_classes <- 10L # MNIST total classes (0-9 digits)
 
## tf Graph input
<- tensorflow::tf$placeholder(tensorflow::tf$float32, tensorflow::shape(NULL, n_input))
<- tensorflow::tf$placeholder(tensorflow::tf$float32, tensorflow::shape(NULL, n_classes))
 
## create model
multilayer_perceptron <- function(x, weights, biases) {
  # hidden layer with RELU activation
  layer_1 <- tensorflow::tf$add(tensorflow::tf$matmul(x, weights$h1), biases$b1)
  layer_1 <- tensorflow::tf$nn$relu(layer_1)
 
  # hidden layer with RELU activation
  layer_2 <- tensorflow::tf$add(tensorflow::tf$matmul(layer_1, weights$h2), biases$b2)
  layer_2 <- tensorflow::tf$nn$relu(layer_2)
  
  # output layer with linear activation
  out_layer <- tensorflow::tf$add(tensorflow::tf$matmul(layer_2, weights$out), biases$out)
  return(out_layer)
}
 
## store layers weight & bias
weights <- base::list(
  'h1'= tensorflow::tf$Variable(tf$random_normal(base::c(n_input, n_hidden_1)), dtype=tf$float32),
  'h2'= tensorflow::tf$Variable(tf$random_normal(base::c(n_hidden_1, n_hidden_2)), dtype=tf$float32),
  'out'= tensorflow::tf$Variable(tf$random_normal(base::c(n_hidden_2, n_classes)), dtype=tf$float32))
 
biases <- base::list(
  'b1'= tensorflow::tf$Variable(stats::rnorm(n=n_hidden_1), dtype=tf$float32),
  'b2'= tensorflow::tf$Variable(stats::rnorm(n=n_hidden_2), dtype=tf$float32),
  'out'= tensorflow::tf$Variable(stats::rnorm(n=n_classes), dtype=tf$float32))
 
## construct model
pred <- multilayer_perceptron(x, weights, biases)
 
## define loss and optimizer
cost <- tensorflow::tf$reduce_mean(tensorflow::tf$nn$softmax_cross_entropy_with_logits(logits=pred, labels=y))
optimizer <- tensorflow::tf$train$AdamOptimizer(learning_rate=learning_rate)$minimize(cost)
 
## initialize variable for plotting
learning_val <- base::matrix(data=0.0, nrow=training_epochs, ncol=2)
learning_val <- base::as.data.frame(learning_val)
base::names(learning_val) <- base::c("Epoch""Cost")
 
## initialize the variables
init <- tensorflow::tf$global_variables_initializer()
 
## create session and initialize  variables
sess <- tensorflow::tf$Session()
sess$run(init)
 
## train
# training cycle
total_batch <- base::as.integer(mnist$train$num_examples / batch_size)
 
for(epoch in 1:training_epochs) {
  avg_cost <- 0.0
  
  # loop over all batches
  for(i in 1:total_batch) {
    # load batch_size training examples in each training iteration
    batches <- mnist$train$next_batch(base::as.integer(batch_size))
    batch_xs <- batches[[1]]
    batch_ys <- batches[[2]]
    
    # Run optimization op (backprop) and cost op (to get loss value)
    sess$run(optimizer, feed_dict = dict(x = batch_xs, y = batch_ys))
    
    # Compute average loss
    avg_cost <- avg_cost + sess$run(cost, feed_dict = dict(x = batch_xs, y = batch_ys)) / total_batch
  }
  
  learning_val[epoch,] <- c(epoch, avg_cost)
  
  # Display logs per epoch step
  if((epoch %% display_step) == 0) {
    base::print(base::sprintf("Epoch: %04d, cost: %.9f", epoch, avg_cost))
  }
}
 
base::print("Optimization Finished!")
 
## test trained model
correct_prediction <- tensorflow::tf$equal(tensorflow::tf$argmax(pred, 1L), tensorflow::tf$argmax(y, 1L))
 
## calculate accuracy
accuracy <- tensorflow::tf$reduce_mean(tensorflow::tf$cast(correct_prediction, tensorflow::tf$float32))
res <- base::sprintf("Accuracy: %.5f", sess$run(accuracy, feed_dict = dict(x = mnist$test$images, y = mnist$test$labels)))
base::print(res)
 
## plotting with Plotly
<- plotly::plot_ly(data = learning_val,
                     x = ~Epoch,
                     y = ~Cost,
                     name = 'Cost Value',
                     type = 'scatter',
                     mode = 'lines+markers',
                     line = list(color = 'rgb(205, 12, 24)',width = 3)) %>%
  layout(title = "Cost Values as Epoch Proceeds",
         xaxis = list(title = "Epoch"),
         yaxis = list (title = "Cost"))
 
# print results
base::print(p)
cs

15. 맺음말

본 포스팅에서는 딥러닝의 가장 중요한 개념 중 하나인 Multilayer Perceptron을 TensorFlow에서 어떻게 구현하는가에 대하여 알아보았습니다. 이 코드를 파악하면, 자신의 구미에 맞게 얼마든지 네트워크 구조를 변경하여 사용할 수 있을 것입니다. 머신러닝 테스트 데이터를 제공하는 다양한 사이트를 통해 얻은 테스트 데이터를 활용하여 다양한 문제를 풀어 보시면 딥러닝을 이용한 문제 해결에 감을 얻을 수 있으리라 생각합니다.

Comments