Deep Learning (TF, Keras, PyTorch)/TensorFlow basics

TensorFlow 2.0 의 AutoGraph 와 tf.function 으로 Python코드를 TF Graph로 자동 변환하기

Rfriend 2020. 8. 23. 00:33

TensorFlow에서 그래프(Graphs)는 tf.Operation 객체의 집합을 포함하고 있는 데이터 구조로서, 연산의 단위와 텐서 객체, 연산간에 흐르는 데이터 단위를 나타냅니다. ("Graphs are data structures that contain a set of tf.Operation objects, which represent units of computation; and tf.Tensor objects, which represent the units of data that flow between operations.") 

* source: https://www.tensorflow.org/guide/intro_to_graphs


TensorFlow 1.x 버전에서의 지연 실행(Lazy execution) 모드 에서는 연산 그래프 (Computational Graph)를 생성하고, 연산을 수행하기 이전에 그래프로 부터 텐서를 어떤 연산을 어떤 순서로 최적화해서 수행할지를 결정한 다음에야 연산을 게으르게(Lazy) 수행을 합니다. TensorFlow 1.x 버전에서는 Session 을 열어서 그래프를 명시적으로 작동(explicitly run)시켜줘야 합니다. 


그래프 최적화(Graph Optimization) 는 만약 동일한 연산이 여기저기서 반복되는 경우 해당 연산 결과를 캐쉬(cache)로 저장해서 사용함으로써 동일 연산이 반복적으로 일어나지 않도록 한다거나, 복잡한 연산의 경우 다수의 장비에서 병렬처리(parallel on multiple devices)를 하여 연산을 빠르게 수행할 수 있도록 하여 성능을 최적화해줍니다. 


TensorFlow 2.x 버전부터는 즉시 실행(Eager execution) 모드로 바뀌었다고 지난 포스팅에서 소개하였는데요, 이는 코드가 즉시 수행된다는 뜻으로서, 즉 "연산 그래프를 그리고 그래프 최적화를 한 후에 코드를 지연 수행"하는 것이 아니라는 뜻입니다. 


그런데 만약 복잡한 모델의 성능을 최적화할 필요가 있다거나, 다른 장비로 모델을 내보내야한다거나 할 때(가령, Python interpreter가 없는 모바일 애플리케이션, 임베디드 장비, 백엔드 서버 등), 파이썬의 즉시 실행 코드를 TensorFlow Graph 로 변환해야 할 필요가 생깁니다. 


이때 TensorFlow 2.x 에서 사용할 수 있는 것이 바로 AutoGraph 모듈과 tf.function 데코레이터(tf.function Python decorator) 입니다. TensorFlow 1.x 버전때처럼 Placeholder를 정의하거나 Session을 열고 작동시켜야하는 번거로움이 TensorFlow 2.x 에서는 없으므로 무척 편리합니다. 




TensorFlow 2.3.0 버전을 사용해서 간단한 예를 들어보겠습니다. 



import tensorflow as tf


print(tf.__version__)

[Out] 2.3.0

 



a, b, c 세개의 객체를 input으로 받아서 곱셈과 덧셈 연산을 해서 얻은 d, e 객체를 반환하는 간단한 Python 사용자 정의 함수 (User defined function) 를 만들어서 실행시켜 보겠습니다.  



# python UDF

def calc(a, b, c):

    d = a * b + c

    e = a * b * c

    return d, e

 

# run python UDF

d, e = calc(2, 3, 4)


print('d:', d)

print('e:', e)

[Out]

d: 10 e: 24




위에서 만든 Python code 를 TensorFlow 2.x 버전에서 텐서를 input으로 받아서 그래프 최적화 (Graph Optimization) 하여 연산을 수행할 수 있도록 @tf.function 과 AutoGraph 모듈을 사용하여 자동으로 그래프로 변환하여 보겠습니다. Python code 함수를 정의하기 전에 @tf.function 데코레이터를 써주면 됩니다. 



@tf.function

def calc(a, b, c):

    d = a * b + c

    e = a * b * c

    return d, e

 

 


혹시 Python 함수가 AutoGraph 에서 그래프로 어떻게 변환되었는지 궁금하다면 아래와 같이 tf.autograph.to_code() 함수를 사용해서 확인해볼 수 있습니다. (좀 복잡하군요. ^^; 이걸 알아서 자동으로 해주니 참 좋은 세상입니다! Many thanks to TensorFlow and Google!)



# If you're curious you can inspect the code autograph generates.

print(tf.autograph.to_code(calc.python_function))


def tf__calc(a, b, c):
    with ag__.FunctionScope('calc', 'fscope', ag__.ConversionOptions(recursive=True, user_requested=True, optional_features=(), internal_convert_user_code=True)) as fscope:
        do_return = False
        retval_ = ag__.UndefinedReturnValue()
        d = ((ag__.ld(a) * ag__.ld(b)) + ag__.ld(c))
        e = ((ag__.ld(a) * ag__.ld(b)) * ag__.ld(c))
        try:
            do_return = True
            retval_ = (ag__.ld(d), ag__.ld(e))
        except:
            do_return = False
            raise
        return fscope.ret(retval_, do_return)

 




TensorFlow 1.x 버전에서는 Session을 열고 명시적으로 그래프 연산을 동작을 시켜야 하는 반면에, TensorFlow 2.x 버전에서는 Session 없이 바로 그래프 연산을 수행할 수 있습니다. 


Session 없이 바로 위에서 정의하고 그래프로 변환했던 calc() 함수에 a, b, c 상수 텐서를 입력해서 d, e 텐서를 결과로 반환해보겠습니다. 



# input constant tensor

a = tf.constant(2.0, name="a")

b = tf.constant(3.0, name="b")

c = tf.constant(4.0, name="c")


# run AutoGraph function without opening Session()

d, e = calc(a, b, c)


print('d:', d)

print('e:', e)

[Out] 
d: tf.Tensor(10.0, shape=(), dtype=float32)
e: tf.Tensor(24.0, shape=(), dtype=float32)


# convert tensor into numpy array format

(d.numpy(), e.numpy())

[Out] (10.0, 24.0)

 


[ Reference ] 

* Better performance with tf.function: https://www.tensorflow.org/guide/function

TensorFlow 2.0: tf.function and AutoGraph: https://towardsdatascience.com/tensorflow-2-0-tf-function-and-autograph-af2b974cf4f7


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

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


728x90
반응형