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

Scientific Computing & Data Science

[Artificial Intelligence / TensorFlow] R-TensorFlow 예제 - Fitting Line 본문

Artificial Intelligence/TensorFlow

[Artificial Intelligence / TensorFlow] R-TensorFlow 예제 - Fitting Line

cinema4dr12 2017. 3. 12. 20:34

by Geol Choi | 


지난 포스팅에서 R에서 TensorFlow 개발환경 구축에 대하여 설명한 바 있다.

R에서 TensorFlow 개발환경 구축에 성공하였다면, 간단한 예제를 실행해 보도록 하자.


패키지 라이브러리 로딩하기

TensorFlow 패키지 라이브러리와 Plotting을 위해 plotly 패키지 라이브러를 로딩한다:


## load necessary library packages
if (! ("tensorflow" %in% rownames(installed.packages()))) { install.packages("tensorflow") }
library(tensorflow)

if (! ("plotly" %in% rownames(installed.packages()))) { install.packages("plotly") }
library(plotly)


Training Data 생성

Uniform Distribution으로 100개의 [0,1]에 속하는 x 데이터를 생성하고,



x_data <- stats::runif(100, min=0, max=1)


x  yy = x * 0.1 + 0.3 (w = 0.1, b = 0.3) 식으로 데이터를 대응시킨다:


y_data <- x_data * 0.1 + 0.3


TensorFlow 변수 설정

Line Fitting: y = w * x + b 의 [wb] 를 계산하기 위해 TensorFlow 함수인 tensorflow::tf$Variable()를 이용하여 TensorFlow 변수 w를 생성한다:


# Try to find values for W and b that compute y_data = W * x_data + b
# (We know that W should be 0.1 and b 0.3, but TensorFlow will figure that out for us.)
W <- tensorflow::tf$Variable(tensorflow::tf$random_uniform(shape=tensorflow::shape(1L), minval=-1.0, maxval=1.0))


마찬가지로 변수 b도 등록한다:


b <- tensorflow::tf$Variable(tensorflow::tf$zeros(shape=tensorflow::shape(1L)))


Loss Function, Optimizer 정의

손실함수(Loss Function, 경우에 따라 Cost Function이라고도 일컬음)는 Mean Squared Error로 정의하여 이를 최소화(Minimize)하는 문제를 정의한다:



여기서, n은 데이터 개수, yi의 계산된 값이다.


따라서, 풀고자 하는 최적화 문제를 다음과 같이 정의할 수 있다:



변수 loss로 다음과 같이 손실함수를 정의하는 코드를 작성한다:


# Minimize the mean squared errors.
loss <- tensorflow::tf$reduce_mean(input_tensor = ((y - y_data) ^ 2))

optimizer는 급강하법(Steepest Gradient Method)을 사용하는데. 이를 위한 TensorFlow 함수는tf$train$GradientDescentOptimizer()이다:


optimizer <- tensorflow::tf$train$GradientDescentOptimizer(learning_rate=0.5)

Learning Rate α는 0.5로 하였으며, 사실상 optimizer는 변수라기 보다는 클래스이다.


이제 minimizer 클래스로부터 minimize를 수행하는 train 변수를 정의한다:


train <- optimizer$minimize(loss=loss)


Session 등록 및 변수 초기화

TensorFlow 코드에 항상 등장하는 Session 등록 및 변수 초기화를 하는 코드를 다음과 같이 작성한다:


# Launch the graph and initialize the variables.
sess = tf$Session()
sess$run(tf$global_variables_initializer())


Plotting을 위한 Data Frame 초기화

최적화 문제를 푸는 Step이 진행됨에 따라 wb의 값이 업데이트 되는 값을 그래프로 출력하기 위해 learning이라는 Data Frame 변수를 초기화하고:


# initialize so_hr_decade: average strikeouts & homeruns for each decade
learning <- base::data.frame(matrix(ncol = 3, nrow = 1))

Field 이름을 정의한다:


base::names(learning) <- base::c("step", "w", "b")


최적화 수행

최적화 수행을 위해 200번의 반복계산(Iteration)을 수행하였으며, 매번 계산되는 결과(step, w, b)를 learning에 저장한다:


# Fit the line (Learns best fit is W: 0.1, b: 0.3)
rowIndex <- 0
for (step in 1:200) {
  sess$run(train)
  cat(step, "-", sess$run(W), sess$run(b), "\n")
  rowIndex <- rowIndex + 1
  learning[rowIndex,] <- base::c(step, sess$run(W), sess$run(b))
}


그래프 출력

plotly 라이브러리 패키지를 이용하여 learning에 저장된 값을 그래프로 출력해 본다:


# plotting with Plotly
p <- plotly::plot_ly(data = learning,
                     x = ~step,
                     y = ~w,
                     name = "w",
                     type = 'scatter',
                     mode = 'lines+markers',
                     line = list(color = 'rgb(205, 12, 24)', width = 3)) %>%
  add_trace(y = ~b,
            name = "b",
            line = list(color = 'rgb(22, 96, 167)',
                        width = 4)) %>%
  layout(title = "Weghts and Bias as Steps Proceed",
         xaxis = list(title = "steps"),
         yaxis = list (title = "w & b"))

print(p)


결과 확인

우선 R Console에 출력되는 값은 다음과 같았다(x_datay_data가 랜덤 분포로 생성되므로 계산 결과는 동일하지 않다):


1 - 0.5424107 0.05722957 
2 - 0.5080853 0.0600853 
3 - 0.485089 0.07869962 
4 - 0.4606258 0.09117027 
5 - 0.4385776 0.1044364 
... 
199 - 0.1000014 0.2999992 
200 - 0.1000013 0.2999992 
201 - 0.1000013 0.2999993


그래프 출력결과는 아래 이미지와 같다:






빨간색 Curve가 w이며, 파란색 Curve가 b인데, wstep이 진행됨에 따라 0.1로 수렴되며 b는 0.3으로 수렴됨을 확인할 수 있다.


Stopping Criterion으로 계산

전체 반복계산 횟수를 지정하는 것보다 수렴되는 정도에 따라 계산 중지 조건(Stopping Criterion)을 정의할 수 있다.


예를 들어 계산 중지 조건으로 업데이트 되는 wb의 변화값(εwεb) 보다 작은 것으로 정의해 보자:


# stopping criterion
eps_w <- 0.001
eps_b <- 0.001

For Loop 대신 다음과 같이 While Loop으로 대체하였으며, 계산 중지 조건이 만족되며 While Loop를 빠져나간다:


# Fit the line (Learns best fit is W: 0.1, b: 0.3)
sess$run(train)
w_old <- sess$run(W)
b_old <- sess$run(b)

rowIndex <- 0
step <- 0
while (1) {
  step <- step + 1
  sess$run(train)
  
  w_new <- sess$run(W)
  b_new <- sess$run(b)
  
  cat(step, "-", w_new, b_new, "\n")
  
  rowIndex <- rowIndex + 1
  learning[rowIndex,] <- base::c(step, w_new, b_new)
  
  if ( (base::abs(w_new - w_old) < eps_w) & (base::abs(b_new - b_old) < eps_b) ) break
  
  w_old <- w_new
  b_old <- b_new
}


결과 확인

For Loop의 경우와 달리 While Loop을 이용한 경우, 계산 횟수 56번만에 계산을 마쳤다(역시 마찬가지로 wb는 Uniform Distribution으로 랜덤하게 생성되므로 아래 결과와 다를 것이다).


1 - -0.381916 0.5023978 
2 - -0.3158821 0.5556316 
3 - -0.3018452 0.520604 
4 - -0.2742785 0.5131581 
5 - -0.2526808 0.4985354 
6 - -0.2310975 0.487079 
7 - -0.2112029 0.4756301 
8 - -0.1923934 0.465077 
9 - -0.1747538 0.4550996 
10 - -0.1581685 0.4457427 
11 - -0.1425873 0.4369451 
12 - -0.1279456 0.42868 
13 - -0.1141879 0.4209134 
14 - -0.1012604 0.4136156 
15 - -0.08911323 0.4067582 
16 - -0.07769918 0.4003148 
17 - -0.06697406 0.3942602 
18 - -0.05689623 0.3885711 
19 - -0.04742667 0.3832254 
20 - -0.03852865 0.3782022 
21 - -0.03016767 0.3734823 
22 - -0.02231133 0.3690472 
23 - -0.01492915 0.3648798 
24 - -0.007992543 0.360964 
25 - -0.001474584 0.3572845 
26 - 0.004649976 0.353827 
27 - 0.01040488 0.3505782 
28 - 0.01581245 0.3475256 
29 - 0.02089363 0.3446572 
30 - 0.02566814 0.3419618 
31 - 0.03015449 0.3394292 
32 - 0.03437006 0.3370494 
33 - 0.0383312 0.3348133 
34 - 0.04205325 0.3327121 
35 - 0.04555066 0.3307377 
36 - 0.04883699 0.3288826 
37 - 0.05192496 0.3271393 
38 - 0.05482655 0.3255013 
39 - 0.05755302 0.3239622 
40 - 0.06011493 0.3225159 
41 - 0.06252222 0.321157 
42 - 0.06478421 0.31988 
43 - 0.06690967 0.3186802 
44 - 0.06890685 0.3175527 
45 - 0.0707835 0.3164933 
46 - 0.07254688 0.3154978 
47 - 0.07420383 0.3145625 
48 - 0.07576077 0.3136835 
49 - 0.07722374 0.3128577 
50 - 0.07859842 0.3120816 
51 - 0.07989012 0.3113524 
52 - 0.08110386 0.3106672 
53 - 0.08224435 0.3100234 
54 - 0.083316 0.3094184 
55 - 0.08432298 0.30885 
56 - 0.08526918 0.3083158


Plotting한 그래프는 아래 이미지와 같다:




전체 코드

FittingLine.R


마치며...

R-TensorFlow의 간단한 예제 코드를 작성해 보았다.

Python에서 코드를 작성할 때의 차이라면 "." 대산 "$"를 사용하는 것이며, 모든 API는 TensorFlow의 공식 API  Guide 문서를 동일하게 참고할 수 있다.

Comments