해당 포스트는 책 “골빈해커의 3분 딥러닝 텐서플로맛”의 3장 “텐서플로 프로그래밍 101”을 학습하고 내용을 정리한 글입니다.


텐서플로

  • 그래프 형태의 수학식 계산을 핵심 라이브러리를 구현
  • 그 위에 딥러닝을 포함한 여러 머신러닝을 쉽게 할 수 있는 다양한 라이브러리를 올린 형태
  • 일반적인 프로그래밍 방식과는 약간 다른 개념들을 포함
    • 텐서(tensor)
    • 플레이스홀더(placeholder)
    • 변수(variable)
    • 연산의 개념
    • 그래프 실행



3.1 텐서와 그래프 실행

3.1.1 텐서플로 라이브러리 임포트

import tensorflow as tf

3.1.2 변수 저장 및 변수 출력

  • tf.constant로 상수를 hello 변수에 저장
hello = tf.constant('Hello, TensorFlow!')
print(hello)
Tensor("Const:0", shape=(), dtype=string)
  • Tensor : hello가 텐서플로의 텐서(Tensor) 자료형이다.
  • Const : 상수를 담고 있음을 의미

텐서 (Tensor)

  • 텐서플로에서 다양한 수학식을 계산하기 위한 가장 기본적이고 중요한 자료형
  • 랭크(Rank)셰이프(Shape) 라는 개념을 가지고 있음
3 # Rank = 0, Shape = []
3
[1., 2., 3.] # Rank = 1, Shape = [3]
[1.0, 2.0, 3.0]
[[1., 2., 3.], [4., 5., 6.]] # Rank = 2, Shape = [2, 3]
[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]
[[[1., 2., 3.]], [[7., 8., 9.]]] # Rank = 3, Shape = [2, 1, 3]
[[[1.0, 2.0, 3.0]], [[7.0, 8.0, 9.0]]]
  • 텐서 자료형의 형태는 배열과 비슷

랭크 (Rank)

  • 차원의 수
  • Rank = 0 : 스칼라
  • Rank = 1 : 벡터
  • Rank = 2 : 행렬
  • Rank >= 3 : n-Tensor 또는 n차원 텐서

셰이프 (Shape)

  • 각 차원의 요소 개수
  • 텐서의 구조를 설명

dtype

  • 해당 텐서에 담긴 요소들의 자료형
  • string, float, int 등이 올 수 있음

3.1.3 연산 수행

  • 텐서를 이용해 다양한 연산 수행 가능
  • 다음과 같이 덧셈 계산
a = tf.constant(10)
b = tf.constant(32)
c = tf.add(a, b)
print(c)
Tensor("Add:0", shape=(), dtype=int32)
  • 일반적인 프로그래밍 언어와 같이 42가 출력되지 않고 텐서의 형태가 출력
  • 그 이유는 텐서플로 프로그램 구조가 다음의 두 가지로 분리되어 있기 때문

    1. 그래프 생성
    2. 그래프 실행

그래프

  • 텐서들의 연산 모음
  • 텐서와 텐서의 연산들을 먼저 저으이하여 그래프를 만듬
  • 이후 필요할 때 연산을 실행하는 코드를 넣어 ‘원하는 시점’ 에 실제 연산을 수행 (지연 실행; lazy evaluation)

  • 실제 계산은 C++로 구현한 코어 라이브러리에서 수행
  • 파이썬으로 프로그램을 작성하지만 매우 뛰어난 성능을 얻을 수 있음
  • 모델 구성과 실행을 분리 \(\rightarrow\) 프로그램을 깔끔하게 작성할 수 있음

3.1.4 그래프 실행

  • 그래프의 실행은 Session 안에서 이루어져야 함
  • Session 객체와 run 메서드 이용
sess = tf.Session()

print(sess.run(hello))
print(sess.run([a, b, c]))

sess.close()
b'Hello, TensorFlow!'
[10, 32, 42]

3.1.5 전체 코드

# 3.1.1
import tensorflow as tf

# 3.1.2
hello = tf.constant('Hello, TensorFlow!')
print(hello)

# 3.1.3
a = tf.constant(10)
b = tf.constant(32)
c = tf.add(a, b)
print(c)

# 3.1.4
sess = tf.Session()

print(sess.run(hello))
print(sess.run([a, b, c]))

sess.close()
Tensor("Const_3:0", shape=(), dtype=string)
Tensor("Add_1:0", shape=(), dtype=int32)
b'Hello, TensorFlow!'
[10, 32, 42]



3.2 플레이스홀더와 변수

플레이스홀더

  • 그래프에 사용할 입력값을 나중에 받기 위해 사용하는 매개변수(parameter)

변수

  • 그래프를 최적화하는 용도로 텐서플로가(더 정확히는 학습 함수들이) 학습한 결과를 갱신하기 위해 사용하는 변수
  • 이 변수의 값들이 신경망의 성능을 좌우

3.2.1 플레이스홀더의 사용

# None : 크기가 정해지지 않았음을 의미
X = tf.placeholder(tf.float32, [None, 3])
print(X)
Tensor("Placeholder:0", shape=(?, 3), dtype=float32)
  • 이 코드를 실행하면 Placeholder라는 (?, 3) 모양의 float32 자료형을 가진 텐서가 생성된 것 확인

3.2.2 자료 정의

  • 플레이스홀더 X에 넣을 자료 정의
  • 텐서 모양을 (?, 3)으로 정의했으므로, 두 번째 차원은 요소를 3개씩 가지고 있어야 한다.
x_data = [[1, 2, 3], [4, 5, 6]]

3.2.3 변수 정의

W = tf.Variable(tf.random_normal([3, 2]))
b = tf.Variable(tf.random_normal([2, 1]))
  • 각각 W와 b에 텐서플로의 변수를 생성하여 할당
  • W : [3, 2] 행렬 형태의 텐서
  • b : [2, 1] 행렬 형태의 텐서
  • tf.random_normal 함수 : 정규분포(normal distribution) 의 무작위 값으로 초기화

  • 다른 생성 함수를 사용하거나 다음처럼 직접 원하는 텐서의 형태의 데이터를 만들어 넣어줄 수도 있다.
W = tf.Variable([[0.1, 0.1], [0.2, 0.2], [0.3, 0.3]])

3.2.4 수식 작성

  • 입력값과 변수들을 계산할 수식 작성
  • X와 W가 행렬이기 때문에 tf.matmul 함수를 사용
  • 행렬이 아닌 경우 곱셈 연산자(*)나 tf.mul 함수를 사용
expr = tf.matmul(X, W) + b

\(\,\) 행렬곱 정의

  • 행렬곱 AxB에 대하여, 행렬 A의 열 수와 행렬 B의 행 수는 같아야 한다.
  • 행렬곱 AxB를 계산한 행렬 AB의 크기는 A의 행 개수와 B의 열 개수가 된다.

  • X에 넣을 데이터를 [2, 3] 형태의 행렬로 정의
  • 행렬곱을 하기 위해 W의 형태를 [3, 2]로 정의한 것

3.2.5 연산 실행

  • 연산을 실행하고 결과를 출력
  • 설정한 텐서들과 계산된 그래프 결과 확인
sess = tf.Session()
sess.run(tf.global_variables_initializer())

print("=== x_data ===")
print(x_data)
print("=== W ===")
print(sess.run(W))
print("=== b ===")
print(sess.run(b))
print("=== expr ===")
print(sess.run(expr, feed_dict={X: x_data}))

sess.close()
=== x_data ===
[[1, 2, 3], [4, 5, 6]]
=== W ===
[[0.1 0.1]
 [0.2 0.2]
 [0.3 0.3]]
=== b ===
[[ 0.6529823 ]
 [-0.87003857]]
=== expr ===
[[2.0529823 2.0529823]
 [2.3299615 2.3299615]]


tf.global_variables_initializer

  • 앞에서 정의한 변수들을 초기화하는 함수
  • 기존에 학습한 값을 가져와서 사용하는 것이 아닌 처음 실행하는 것 이라면, 연산을 실행하기 전에 반드시 이 함수를 이용해 변수들을 초기화해야 한다.

feed_dict 매개변수

  • 그래프를 실행할 때 사용할 입력값을 지정
  • expr 수식에는 X, W, b를 사용
  • 이들 중 X가 플레이스홀더라 X에 값을 넣어주지 않으면 계산에 사용할 값이 없으므로 에러가 남
  • 미리 정의해 둔 x_data를 X의 값으로 넣어 줌

실행 결과

  • X(x_data)는 [2, 3], W는 [3, 2] 형태
  • 결과값(expr)은 [2, 2] 형태

3.2.6 전체 코드

import tensorflow as tf

# 3.2.1
X = tf.placeholder(tf.float32, [None, 3])
print(X)

# 3.2.2
x_data = [[1, 2, 3], [4, 5, 6]]

# 3.2.3
W = tf.Variable(tf.random_normal([3, 2]))
b = tf.Variable(tf.random_normal([2, 1]))

# 3.2.4
expr = tf.matmul(X, W) + b

# 3.2.5
sess = tf.Session()
sess.run(tf.global_variables_initializer())

print("=== x_data ===")
print(x_data)
print("=== W ===")
print(sess.run(W))
print("=== b ===")
print(sess.run(b))
print("=== expr ===")
print(sess.run(expr, feed_dict={X: x_data}))

sess.close()
Tensor("Placeholder_1:0", shape=(?, 3), dtype=float32)
=== x_data ===
[[1, 2, 3], [4, 5, 6]]
=== W ===
[[ 0.4356766  -0.10741346]
 [-1.0840358  -1.0250919 ]
 [-1.1020888  -1.0256674 ]]
=== b ===
[[1.1071613]
 [0.590997 ]]
=== expr ===
[[ -3.9314997  -4.1274385]
 [ -9.699008  -11.118121 ]]



3.3 선형 회귀 모델 구현하기

선형 회귀

  • 주어진 x와 y값을 가지고 서로 간의 관계를 파악하는 것
  • 관계를 알고 나면 새로운 x 값이 주어졌을 때 y 값을 쉽게 알 수 있음

  • 어떤 입력에 대한 출력을 예측하는 것 \(\rightarrow\) 머신러닝의 기본

텐서플로의 최적화 함수를 이용해 X와 Y의 상관관계를 분석하는 기초적인 선형 회귀 모델을 만들고 실행해보자. 다음과 같이 주어진 x_data와 y_data의 상관관계를 파악해보자 한다.

x_data = [1, 2, 3]
y_data = [1, 2, 3]

3.3.1 변수 정의

  • x와 y의 상관관계를 설명하기 위한 변수들인 W와 b를 각각 -1.0부터 1.0사이의 균등분포(uniform distribution) 를 가진 무작위 값으로 초기화
W = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
b = tf.Variable(tf.random_uniform([1], -1.0, 1.0))

3.3.2 플레이스홀더 설정

  • 자료를 입력받을 플레이스홀더 설정
X = tf.placeholder(tf.float32, name="X")
Y = tf.placeholder(tf.float32, name="Y")

cf) 플레이스홀더에 이름 부여하기

  • 플레이스홀더의 name 매개변수로 플레이스 홀더의 이름을 설정
print(X, Y)
Tensor("X:0", dtype=float32) Tensor("Y:0", dtype=float32)
  • name 없이 설정한 플레이스홀더를 출력하면 이름이 자동으로 부여된 것 확인 가능
A = tf.placeholder(tf.float32)
print(A)
Tensor("Placeholder_2:0", dtype=float32)
  • 5장에서 학습할 디버깅 도구인 텐서보드(TensorBoard) 에서도 이 이름으로 출력해주므로 디버깅도 더 수월하게 할 수 있음
  • 변수(Variable)와 연산 또는 연산함수에도 이름을 지정할 수 있음

3.3.3 수식 작성

  • X와 Y의 상관관계 (여기서는 선형관계)를 분석하기 위한 수식 작성
hypothesis = W * X + b
  • 이 수식의 의미 : W와의 곱과 b와의 합을 통해 X와 Y의 관계를 설명하겠다.
  • X가 주어졌을 때 Y를 만들어 낼 수 있는 W와 b를 찾아내겠다는 의미

  • W : 가중치(weight)
  • b : 편향(bias)
  • 이 수식은 선형회귀는 물론 신경망 학습 에 가장 기본이 되는 수식이다.

  • 여기서 W와 X가 행렬이 아니므로 tf.matmul가 아닌 기본 곱셈 연산자를 사용

3.3.4 손실 함수 작성

손실 함수 (loss function)

  • 한 쌍(x, y)의 데이터에 대한 손실값 을 계산하는 함수

손실값

  • 실제값과 모델로 예측한 값이 얼마나 차이가 나는가를 나타내는 값
  • 손실값이 작을수록 그 모델이 X와 Y의 관계를 잘 설명하고 있다는 뜻

비용(cost)

  • 이 손실을 전체 데이터에 대해 구한 경우

학습

  • 변수들의 값을 다양하게 넣어 계산해보면서 이 손실값을 최소화하는 W와 b의 값을 구하는 것

  • 손실값으로는 ‘예측값과 실제값의 거리’를 가장 많이 사용
  • 손실값은 예측값에서 실제값을 뺀 뒤 제곱하여 계산
  • 비용은 모든 데이터에 대한 손실값의 평균을 내어 계산
cost = tf.reduce_mean(tf.square(hypothesis - Y))
  • 텐서플로는 수식 계산을 위한 다양한 함수를 구현해 제공
  • 텐서플로 API 문서 사이트를 방문하여 어떤 함수들이 있는 지 확인해보자.

3.3.5 손실값 최소화

  • 텐서플로가 기본 제공하는 경사하강법(gradient descent) 최적화 함수를 이용해 손실값을 최소화하는 연산 그래프를 생성
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1)
train_op = optimizer.minimize(cost)


최적화 함수

  • 가중치와 편향 값을 변경해가면서 손실갑을 최소화하는 가장 최적화된 가중치와 편향 값을 찾아주는 함수
  • 이때 값들을 무작위로 변경하면 시간이 너무 오래 걸리고 학습 시간도 예측하기 어려울 것임
  • 빠르게 최적화하기 위한, 즉 빠르게 학습하기 위한 다양한 방법 사용

경사하강법

  • 최적화 방법 중 가장 기본적인 알고리즘
  • 함수의 기울기를 구하고 기울기가 낮은 쪽으로 계속 이동시키면서 최적의 값을 찾아나가는 방법

학습률

  • 최적화 함수의 매개변수
  • learning_rate
  • 학습을 얼마나 ‘급하게’ 할 것인가를 설정하는 값
  • 값이 너무 크면 \(\rightarrow\) 최적의 손실값을 찾지 못하고 지나치게 됨
  • 값이 너무 작으면 \(\rightarrow\) 학습 속도가 매우 느려짐

하이퍼 파라미터(hyperparameter)

  • 학습률(learning rate)과 같이 학습을 진행하는 과정에 영향을 주는 변수
  • 이 값에 따라 학습 속도나 신경망 성능이 크게 달라질 수 있다.
  • 머신러닝에서는 이 하이퍼 파라미터를 잘 튜닝하는 것이 큰 과제이다.

3.3.6 그래프 실행

  • 그래프를 실행해 학습을 시키고 결과 확인

1) 세션 생성 및 변수들 초기화

  • 여기서는 파이썬의 with 기능을 이용해 세션 블록을 만들고 세션 종료를 자동으로 처리
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

2) 그래프 실행 및 결과 확인

  • 최적화를 수행하는 그래프 train_op를 실행
  • 실행 시마다 변화하는 손실값을 출력하는 코드
  • 학습은 100번 수행
  • feed_dict 매개변수를 통해, 상관관계를 알아내고자 하는 데이터인 x_data와 y_data를 입력
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    for step in range(100):
        _, cost_val = sess.run([train_op, cost], feed_dict={X: x_data, Y: y_data})
        print(step, cost_val, sess.run(W), sess.run(b))
0 10.661012 [0.66357744] [1.1379786]
1 0.29180253 [0.5223804] [1.0449519]
2 0.16012865 [0.55017793] [1.0270094]
3 0.15111516 [0.55920815] [1.0015364]
4 0.14392029 [0.56999934] [0.97754586]
5 0.13708377 [0.58031493] [0.95403695]
6 0.13057216 [0.5904062] [0.9311036]
7 0.12436995 [0.60025233] [0.9087204]
8 0.118462205 [0.60986197] [0.8868754]
9 0.11283523 [0.61924064] [0.8655555]
10 0.10747543 [0.6283938] [0.84474814]
11 0.10237029 [0.637327] [0.824441]
12 0.097507626 [0.6460454] [0.804622]
13 0.09287596 [0.65455425] [0.78527945]
14 0.08846426 [0.6628585] [0.7664019]
15 0.08426216 [0.67096317] [0.74797815]
16 0.080259636 [0.67887294] [0.7299973]
17 0.0764473 [0.68659264] [0.71244866]
18 0.072815955 [0.6941267] [0.69532186]
19 0.06935714 [0.7014797] [0.6786068]
20 0.06606262 [0.70865595] [0.6622936]
21 0.06292457 [0.71565956] [0.6463725]
22 0.059935644 [0.72249496] [0.63083416]
23 0.05708869 [0.72916603] [0.61566937]
24 0.05437691 [0.7356767] [0.6008691]
25 0.051793963 [0.7420308] [0.5864246]
26 0.04933372 [0.74823225] [0.5723274]
27 0.046990335 [0.75428456] [0.558569]
28 0.044758264 [0.7601914] [0.5451414]
29 0.042632196 [0.7659562] [0.53203654]
30 0.04060712 [0.7715824] [0.51924676]
31 0.038678255 [0.77707344] [0.5067644]
32 0.036840998 [0.7824325] [0.49458215]
33 0.03509104 [0.7876627] [0.48269272]
34 0.03342421 [0.7927671] [0.4710891]
35 0.031836495 [0.7977488] [0.45976442]
36 0.030324263 [0.8026108] [0.448712]
37 0.028883813 [0.80735594] [0.43792528]
38 0.027511813 [0.8119869] [0.42739785]
39 0.026205003 [0.8165067] [0.41712353]
40 0.024960225 [0.8209177] [0.40709615]
41 0.0237746 [0.8252227] [0.3973098]
42 0.022645315 [0.82942426] [0.3877588]
43 0.021569652 [0.8335248] [0.37843734]
44 0.020545058 [0.8375267] [0.36933994]
45 0.01956916 [0.8414325] [0.3604613]
46 0.018639613 [0.84524435] [0.35179603]
47 0.01775421 [0.8489646] [0.3433391]
48 0.016910886 [0.8525954] [0.33508545]
49 0.016107589 [0.8561388] [0.3270302]
50 0.015342455 [0.85959715] [0.31916863]
51 0.014613696 [0.8629724] [0.31149605]
52 0.0139195165 [0.86626637] [0.3040079]
53 0.013258322 [0.86948127] [0.29669976]
54 0.0126285665 [0.87261885] [0.28956732]
55 0.012028701 [0.87568104] [0.28260633]
56 0.011457317 [0.8786695] [0.27581263]
57 0.01091309 [0.88158625] [0.2691823]
58 0.010394716 [0.88443285] [0.26271135]
59 0.009900955 [0.88721097] [0.25639594]
60 0.009430654 [0.8899223] [0.25023237]
61 0.008982691 [0.8925685] [0.24421696]
62 0.008556014 [0.89515114] [0.23834616]
63 0.008149586 [0.89767164] [0.23261648]
64 0.0077624843 [0.9001315] [0.22702454]
65 0.0073937452 [0.9025323] [0.22156703]
66 0.0070425384 [0.90487534] [0.21624072]
67 0.006708021 [0.9071621] [0.21104243]
68 0.0063893883 [0.90939385] [0.20596913]
69 0.0060858857 [0.9115719] [0.20101775]
70 0.005796801 [0.91369766] [0.19618542]
71 0.0055214525 [0.9157724] [0.19146928]
72 0.0052591786 [0.91779715] [0.18686648]
73 0.0050093527 [0.9197732] [0.18237433]
74 0.0047714105 [0.92170185] [0.17799018]
75 0.0045447624 [0.9235841] [0.17371142]
76 0.0043288865 [0.925421] [0.16953549]
77 0.0041232645 [0.9272139] [0.16546]
78 0.003927399 [0.92896354] [0.16148242]
79 0.0037408555 [0.93067133] [0.15760054]
80 0.003563147 [0.9323378] [0.15381187]
81 0.003393897 [0.93396443] [0.15011437]
82 0.0032326933 [0.9355519] [0.14650573]
83 0.0030791312 [0.9371011] [0.14298382]
84 0.00293287 [0.9386132] [0.1395466]
85 0.002793561 [0.94008887] [0.13619201]
86 0.0026608573 [0.9415291] [0.13291804]
87 0.0025344677 [0.9429347] [0.12972279]
88 0.002414081 [0.94430655] [0.12660436]
89 0.0022994156 [0.9456454] [0.12356087]
90 0.002190183 [0.946952] [0.12059054]
91 0.0020861516 [0.9482272] [0.11769164]
92 0.0019870626 [0.94947183] [0.11486242]
93 0.0018926753 [0.9506865] [0.1121012]
94 0.0018027662 [0.95187193] [0.10940634]
95 0.0017171344 [0.9530289] [0.10677631]
96 0.0016355732 [0.95415807] [0.10420949]
97 0.0015578829 [0.9552601] [0.10170437]
98 0.0014838809 [0.95633554] [0.09925944]
99 0.0014133969 [0.9573853] [0.09687334]
  • 학습의 진행 상황 출력됨
  • 손실값과 변수들의 변화를 확인
  • 손실값이 점점 줄어든다면 학습이 정상적으로 이뤄지고 있는 것

3.3.7 학습 결과 확인 (테스트 데이터 이용)

  • 학습에 사용되지 않았던 값인 5와 2.5를 X값으로 넣고 결과 확인
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    for step in range(100):
        _, cost_val = sess.run([train_op, cost], feed_dict={X: x_data, Y: y_data})
        #print(step, cost_val, sess.run(W), sess.run(b))

    print("X: 5, Y: ", sess.run(hypothesis, feed_dict={X: 5}))
    print("X: 2.5, Y: ", sess.run(hypothesis, feed_dict={X: 2.5}))
X: 5, Y:  [5.0316358]
X: 2.5, Y:  [2.502631]
  • 기대한 대로 X가 5일 때는 Y값으로 5를, 2.5일 때는 2.5를 정확히 예측함

3.3.8 전체 코드

import tensorflow as tf

x_data = [1, 2, 3]
y_data = [1, 2, 3]

# 3.3.1
W = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
b = tf.Variable(tf.random_uniform([1], -1.0, 1.0))

# 3.3.2
X = tf.placeholder(tf.float32, name="X")
Y = tf.placeholder(tf.float32, name="Y")

# 3.3.3
hypothesis = W * X + b

# 3.3.4
cost = tf.reduce_mean(tf.square(hypothesis - Y))

# 3.3.5
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1)
train_op = optimizer.minimize(cost)

# 3.3.6
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

    for step in range(100):
        _, cost_val = sess.run([train_op, cost], feed_dict={X: x_data, Y: y_data})
        print(step, cost_val, sess.run(W), sess.run(b))

    # 3.3.7
    print("\n=== Test ===")
    print("X: 5, Y: ", sess.run(hypothesis, feed_dict={X: 5}))
    print("X: 2.5, Y: ", sess.run(hypothesis, feed_dict={X: 2.5}))
0 13.9641905 [1.2223984] [-0.07493311]
1 0.16977327 [1.0447998] [-0.14890587]
2 0.0048552467 [1.062549] [-0.13704462]
3 0.0027509674 [1.0589879] [-0.13465528]
4 0.002597921 [1.0577946] [-0.13131937]
5 0.0024742528 [1.0563807] [-0.12817334]
6 0.0023567178 [1.0550281] [-0.12509097]
7 0.0022447715 [1.053705] [-0.12208401]
8 0.0021381478 [1.052414] [-0.11914921]
9 0.002036581 [1.0511539] [-0.11628494]
10 0.0019398452 [1.0499243] [-0.11348952]
11 0.0018476918 [1.0487242] [-0.1107613]
12 0.0017599283 [1.0475528] [-0.1080987]
13 0.0016763322 [1.0464097] [-0.10550009]
14 0.0015967126 [1.0452939] [-0.10296397]
15 0.0015208652 [1.0442052] [-0.10048876]
16 0.0014486229 [1.0431426] [-0.09807309]
17 0.0013798111 [1.0421054] [-0.0957155]
18 0.0013142689 [1.0410932] [-0.09341457]
19 0.0012518367 [1.0401053] [-0.09116894]
20 0.0011923764 [1.0391413] [-0.0889773]
21 0.0011357386 [1.0382004] [-0.08683836]
22 0.0010817917 [1.037282] [-0.08475085]
23 0.0010304024 [1.0363858] [-0.08271348]
24 0.0009814606 [1.0355111] [-0.0807251]
25 0.00093483814 [1.0346575] [-0.07878453]
26 0.0008904347 [1.0338243] [-0.07689062]
27 0.0008481328 [1.0330112] [-0.07504222]
28 0.00080785045 [1.0322176] [-0.07323825]
29 0.00076948013 [1.0314431] [-0.07147766]
30 0.00073292555 [1.0306872] [-0.06975938]
31 0.00069810887 [1.0299495] [-0.06808238]
32 0.0006649488 [1.0292296] [-0.06644572]
33 0.0006333626 [1.0285269] [-0.06484842]
34 0.0006032805 [1.0278411] [-0.06328951]
35 0.00057462417 [1.0271719] [-0.06176805]
36 0.00054732733 [1.0265187] [-0.06028318]
37 0.00052132754 [1.0258812] [-0.05883401]
38 0.00049656274 [1.025259] [-0.05741967]
39 0.00047297624 [1.0246518] [-0.05603934]
40 0.00045051076 [1.0240592] [-0.05469218]
41 0.000429108 [1.0234809] [-0.0533774]
42 0.00040872817 [1.0229163] [-0.05209428]
43 0.00038931367 [1.0223655] [-0.05084196]
44 0.00037081764 [1.0218278] [-0.04961973]
45 0.0003532079 [1.021303] [-0.04842693]
46 0.0003364283 [1.0207909] [-0.04726276]
47 0.00032044813 [1.0202912] [-0.04612657]
48 0.0003052256 [1.0198034] [-0.04501773]
49 0.0002907267 [1.0193273] [-0.04393554]
50 0.00027691902 [1.0188627] [-0.04287935]
51 0.0002637642 [1.0184093] [-0.04184857]
52 0.00025123483 [1.0179667] [-0.04084256]
53 0.00023930134 [1.0175349] [-0.03986075]
54 0.0002279356 [1.0171132] [-0.03890255]
55 0.00021710724 [1.0167019] [-0.03796733]
56 0.0002067939 [1.0163004] [-0.03705463]
57 0.00019697331 [1.0159085] [-0.03616389]
58 0.00018761605 [1.015526] [-0.0352945]
59 0.00017870375 [1.0151529] [-0.03444602]
60 0.00017021496 [1.0147886] [-0.03361799]
61 0.00016212974 [1.0144331] [-0.03280985]
62 0.00015442964 [1.0140861] [-0.03202115]
63 0.00014709344 [1.0137476] [-0.03125136]
64 0.00014010507 [1.0134171] [-0.03050011]
65 0.00013345007 [1.0130945] [-0.02976693]
66 0.00012711225 [1.0127797] [-0.02905136]
67 0.000121074576 [1.0124725] [-0.02835298]
68 0.00011532244 [1.0121727] [-0.02767138]
69 0.00010984556 [1.01188] [-0.02700619]
70 0.000104628496 [1.0115944] [-0.02635698]
71 9.965845e-05 [1.0113157] [-0.02572336]
72 9.4922165e-05 [1.0110438] [-0.02510496]
73 9.0414454e-05 [1.0107783] [-0.02450148]
74 8.611925e-05 [1.0105191] [-0.0239125]
75 8.203033e-05 [1.0102663] [-0.02333766]
76 7.81334e-05 [1.0100195] [-0.02277665]
77 7.442201e-05 [1.0097786] [-0.02222915]
78 7.0887014e-05 [1.0095435] [-0.02169477]
79 6.752063e-05 [1.0093141] [-0.02117324]
80 6.43121e-05 [1.0090902] [-0.02066422]
81 6.125713e-05 [1.0088717] [-0.02016745]
82 5.834846e-05 [1.0086584] [-0.01968264]
83 5.557584e-05 [1.0084503] [-0.01920948]
84 5.293651e-05 [1.0082471] [-0.01874769]
85 5.0420906e-05 [1.0080489] [-0.018297]
86 4.8026082e-05 [1.0078554] [-0.01785715]
87 4.57453e-05 [1.0076666] [-0.01742789]
88 4.3572345e-05 [1.0074823] [-0.01700894]
89 4.1502306e-05 [1.0073024] [-0.01660006]
90 3.9531278e-05 [1.0071268] [-0.01620102]
91 3.765331e-05 [1.0069555] [-0.01581154]
92 3.58648e-05 [1.0067884] [-0.01543143]
93 3.416149e-05 [1.006625] [-0.0150605]
94 3.253824e-05 [1.0064659] [-0.01469842]
95 3.099271e-05 [1.0063105] [-0.0143451]
96 2.952052e-05 [1.0061587] [-0.01400026]
97 2.8118235e-05 [1.0060107] [-0.01366369]
98 2.6782893e-05 [1.0058662] [-0.01333522]
99 2.551089e-05 [1.0057251] [-0.01301465]

=== Test ===
X: 5, Y:  [5.0156107]
X: 2.5, Y:  [2.5012982]

댓글남기기