'TensorFlow 2.x placeholder 미사용'에 해당되는 글 1건

  1. 2020.08.09 TensorFlow 1.x 지연 실행모드 (lazy execution) vs. TensorFlow 2.x 즉시 실행모드(eager execution)

2019년도 9월 말에 TensorFlow 2.0 버전이 공개되었으며. 이전의 TensorFlow 1.x 대비 (1) API Cleanup, (2) Eager execution, (3) No more globals, (4) Functions, not sessions 와 같은 변화가 있었습니다. (https://www.tensorflow.org/guide/effective_tf2)


이번 포스팅에서는 TensorFlow 1.x 에서의 지연 실행모드(Lazy execution), Global namespace, Session 호출 대비, TensorFlow 2.x 에서  Global namespace 나 Session 호출 없이, 즉시 실행모드(Eager execution)에 대해서 간단한 예제를 들어서 비교 설명해보겠습니다. 

(Keras API 와의 통합은 다음번 포스팅에서 소개하겠습니다.)


아래 비교 예제를 살펴보면 TensorFlow 2.x 에서의 코드가 한결 깔끔해져서 가독성도 좋아지고, 디버깅하기에도 편리해졌음을 알 수 있을 겁니다.  Python 프로그리밍에 이미 익숙한 사용자라면 TensorFlow 2.x 버전이 사용하기에 무척 친숙하게 느껴질 것입니다. 


아래에는 TensorFlow 1.12.0 버전과 TensorFlow 2.3.0 버전을 사용하여 TensorFlow 의 핵심 데이터 구조인 상수(constant), 변수(Variable), Placeholder 로 나누어서 TensorFlow 버전 간 비교해보겠습니다. 


  (1) 상수 (constant) 생성 및 연산 실행


 TensorFlow 1.x: 지연 실행 (lazy execution)

TensorFlow 2.x: 즉시 실행 (eager execution)


import tensorflow as tf


tf.__version__

'1.12.0'


a = tf.constant([0, 1, 2])

b = tf.constant([10, 20, 30])


# lazy execution

c = tf.add(a, b)

print(c)

Tensor("Add:0", shape=(3,), 
dtype=int32)



with tf.Session() as sess:

    print(sess.run(c))


[10 21 32]


import tensorflow as tf


tf.__version__

'2.3.0'


a = tf.constant([0, 1, 2])

b = tf.constant([10, 20, 30])


# eager execution

c = tf.add(a, b) # or c = a + b

print(c)

tf.Tensor([10 21 32], 
shape=(3,), dtype=int32)


TensorFlow 1.x 버전에서는 지연 실행 모드 (lazy execution) 가 기본 설정이므로 위의 더하기(add) 예제에서처럼 tf.constant() 로 두 개의 상수 배열을 만들고, tf.add(a, b)를 하면 바로 실행되는 것이 아니며, 계산 그래프와 Session을 생성하고 명시적으로 tf.Session().run() 을 호출하고 나서야 연산이 실행됩니다. 


반면에 TensorFlow 2.x 버전에서는 즉시 실행 모드 (eager execution) 가 기본 설정이므로 a, b 의 두 상수 배열을 생성한 후 tf.add(a, b) 를 하면 Session().run() 없이 바로 더하기 연산이 실행되어 그 결과를 반환합니다. 


TensorFlow 2.x 에서는 아래의 예처럼 numpy() 메소드를 사용해서 텐서를 numpy array 로 변환하여 텐서의 값에 접근할 수 있습니다. (참고로, 반대로 tf.convert_to_tensor(arr) 메소드를 사용하면 numpy array를 텐서 값으로 변환할 수 있습니다.)



# TensorFlow 2.x

# accessing the value of a Tensor

c_arr = c.numpy()

print(c_arr)

[10 21 32]

 




  (2) 변수 (Variable) 생성 및 연산 실행


TensorFlow 1.x

: lazy execution, session, global namespaces

TensorFlow 2.x

: eager execution, no session, no globals


import tensorflow as tf


tf.__version__

'1.12.0'


w = tf.Variable([[1.], [2.]])

x = tf.constant([[3., 4.]])


print(w)

<tf.Variable 'Variable:0' shape=(2, 1) dtype=float32_ref>


print(x)
Tensor("Const_2:0", shape=(1, 2), 
dtype=float32)


# lazy execution

w_x_matmul = tf.matmul(w, x)

print(w_x_matmul)

Tensor("MatMul:0", shape=(2, 2), 
dtype=float32)


with tf.Session() as sess:
    # initialization of variable
    sess.run(tf.global_variables_initializer())
    
    # runn tf.Session
    print(sess.run(w_x_matmul))


[[3. 4.]
 [6. 8.]]


import tensorflow as tf


tf.__version__

'2.3.0'


w = tf.Variable([[1.], [2.]])

x = tf.constant([[3., 4.]]) 


print(w)

<tf.Variable 'Variable:0' shape=(2, 1) dtype=float32, numpy=
array([[1.],
       [2.]], dtype=float32)>



print(x)

tf.Tensor([[3. 4.]], shape=(1, 2), 
dtype=float32)



# eager execution

# no need for tf.global_variables_initializer()

w_x_matmul = tf.matmul(w, x)

print(w_x_matmul)

tf.Tensor(
[[3. 4.]
 [6. 8.]], shape=(2, 2), 
dtype=float32)


tf.Variable() 로 생성한 w 변수(Variable)와 tf.constant()로 생성한 상수로 tf.matmul() 메소드로 행렬곱 연산을 수행하여 보았습니다. 


TensorFlow 1.x 버전에서는 지연 연산 (lazy execution) 모드이므로 tf.matmul(w, x) 에서는 아무런 연산이 일어나지 않으며, Session을 열고 session.run()으로 명시적으로 호출할 때에야 비로서 행렬곱 연산이 실행됩니다. 더불어서, 변수를 Session 에서 실행시키기 전에 tf.global_variables_initializer() 를 먼저 호출해서 변수를 초기화(initialization) 해주어야 합니다. 


반면에 TensorFlow 2.x 버전에서는 tf.Variable(), tf.constant() 로 값을 할당해주면 바로 실행이 되어 변수와 상수가 생성이 됩니다. 그리고 tf.matmul() 메소드로 행렬곱 연산을 즉시 수행하여 결과값을 반환받습니다. (이때 tf.global_variables_initializer() 를 호출할 필요는 없습니다.) TenforFlow 1.x 대비 TensorFlow 2.x 가 코드가 한결 깔끔해졌습니다. 




  (3) tf.placeholder(...), feed_dict


Placeholder 는 TensorFlow에서 그래프를 실행할 때 사용자가 데이터를 주입할 수 있는 통로입니다. TensforFlow 1.x 버전에서는 아래처럼 Session을 실행할 때 feed_dict 매개변수를 사용하여 feed_dict = {placeholder: input} 처럼 사전형으로 값을 입력할 수 있습니다. 

반면에 TensorFlow 2.x 버전에서는 Session() 실행없이 바로 함수(function)에 입력값(input)을 넣어서 즉시 실행할 수 있습니다. 역시 코드가 한결 깔끔해졌습니다. 


# TensorFlow 1.x

outputs = session.run(f(placeholder), feed_dict={placeholder: input})


# TensorFlow 2.x

outputs = f(input)



TensorFlow 1.x:

Session, Placeholder & feed_dict 

 TensorFlow 2.x:

function


import tensorflow as tf


tf.__version__

'1.12.0'


# placeholder

a = tf.placeholder(tf.int32)

b = tf.placeholder(tf.int32)


# defining a summation function

def tf_sum(a, b):

    return a + b


# lazy execution

a_b_sum = tf_sum(a, b)


print(a_b_sum)

Tensor("add_1:0", dtype=int32)



with tf.Session() as sess:

    print(sess.run(a_b_sum, 

                  feed_dict = {a: [0, 1, 2], 

                               b: [10, 20, 30]}))


[10 21 32]



import tensorflow as tf


tf.__version__

'2.3.0'


a = tf.constant([0, 1, 2])

b = tf.constant([10, 20, 30])


# define a summation fuction

def tf_sum(a, b):

    return a + b


# eager execution

a_b_sum = tf_sum(a, b)


print(a_b_sum)

tf.Tensor([10 21 32], shape=(3,), 
dtype=int32)



많은 도움이 되었기를 바랍니다. 

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. 



728x90
반응형
Posted by Rfriend
,