Eager execution Vs Graph execution - pai-plznw4me/tensorflow_basic GitHub Wiki

Eager execution Vs Graph execution

ν•΄λ‹Ή ν¬μŠ€νŠΈμ—μ„œλŠ” Tensorflow의 Eager execution κ³Ό Graph execution의 차이점을 μ•„λž˜ 주제둜 μ„€λͺ…ν•©λ‹ˆλ‹€.

  • Debug
  • λ³€μˆ˜ 관리
  • Computation Speed

Debug

Graph Execution Mode

Tensorflow 2.x λ²„μ „μœΌλ‘œ μ—…λ°μ΄νŠΈ λ˜λ©΄μ„œ
Tensorflow λŠ” Eager Excution μ΄λΌλŠ” Tensorflow 1.x 에 μ—†λ˜ μƒˆλ‘œμš΄ κ°œλ…μ„ λ„μž…ν•©λ‹ˆλ‹€.

기쑴의 Tensorflow 1.x 은 Graph 을 생성 ν•œ ν›„
ν•΄λ‹Ή κ·Έλž˜ν”„μ™€ μ—°κ²°λœ Session 을 μƒμ„±ν•˜κ³  Session 을 톡해 μ‹€ν–‰ν•˜κ³ μž ν•˜λŠ” Tensor λ˜λŠ” Operation 을 μˆ˜ν–‰ν•΄ μ›ν•˜λŠ” κ²°κ³Όλ₯Ό μ–»λŠ” 과정을 μˆ˜ν–‰ ν•˜μ˜€μŠ΅λ‹ˆλ‹€.
μ•„λž˜ μ—μ œ μ½”λ“œλ₯Ό μ‚΄νŽ΄ λ΄…μ‹œλ‹€.

# create new graph 
g = tf.Graph()

# set graph to default graph 
# add node, tensor to graph 
with g.as_default():
  a = tf.constant(3)
  b = tf.constant(5)
  c = a + b

# create session with graph g 
sess = tf.Session(graph=g)

# get result from tensor c 
sess.run(c)

μœ„ μ˜ˆμ œμ—μ„œ 4κ°€μ§€ λ‹¨κ³„λ‘œ Tensorflow 1.x κ°€ μˆ˜ν–‰λ˜λŠ” 것을 μ•Œμˆ˜ μžˆμŠ΅λ‹ˆλ‹€.

  1. Graph 생성
  2. Graph 에 λ…Έλ“œ 및 ν…μ„œ μΆ”κ°€
  3. Session 생성 및 Sessionκ³Ό Graph 연동
  4. μˆ˜ν–‰ν•˜κ³  자 ν•˜λŠ” Tensor μˆ˜ν–‰

ν•˜μ§€λ§Œ Tensorflow 1.x 의 μ½”λ“œ κ΅¬ν˜„ 방식은 Python 의 μž₯점을 μΆ©λΆ„νžˆ 살리지 λͺ»ν•˜λŠ” 단점이 μžˆμŠ΅λ‹ˆλ‹€.
Python 은 Interpreter μ–Έμ–΄λ‘œμ„œ μ‹€ν–‰ κ²°κ³Όλ₯Ό λ°”λ‘œλ°”λ‘œ μ•Œμˆ˜ μžˆμŠ΅λ‹ˆλ‹€.
이λ₯Ό 톡해 디버그도 맀우 νŽΈν•˜λ‹€λŠ” μž₯점을 κ°€μ§€κ³  μžˆμŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ Graph 을 λͺ¨λ‘ μƒμ„±ν•œ ν›„ Session 을 톡해 μ›ν•˜λŠ” κ²°κ³Όλ₯Ό μ–»μ–΄μ•Ό ν•˜λŠ” Tensorflow 1.xλŠ” λ°”λ‘œ λ°”λ‘œ κ²°κ³Όλ₯Ό 확인할 수 μ—†μŠ΅λ‹ˆλ‹€. μ΄λŠ” μ½”λ“œ 디버그λ₯Ό μ–΄λ ΅κ²Œ ν•©λ‹ˆλ‹€.

Imgur

Tensorflow 1.x λ²„μ „μ—μ„œμ˜ Debug λ°©λ²•μœΌλ‘œ Tensorboard λ˜λŠ” tfdbg을 μΆ”μ²œν•©λ‹ˆλ‹€.

Eager Execution mode

Tensorflow 2.x λ²„μ „μ—μ„œλŠ” Tensorflow 1.x 의 단점을 κ·Ήλ³΅ν•˜κ³ μž Eager execution κΈ°λŠ₯을 κΈ°λ³Έ λͺ¨λ“œλ‘œ μ œκ³΅ν•©λ‹ˆλ‹€.
Eager Execution λͺ¨λ“œλŠ” Graph을 μƒμ„±ν•˜μ§€ μ•Šκ³  계산값을 λ°”λ‘œλ°”λ‘œ μ•Œλ €μ£ΌλŠ” λͺ…λ Ήν˜•(imperative) ν”„λ‘œκ·Έλž˜λ° ν™˜κ²½μž…λ‹ˆλ‹€.

Eager Execution λͺ¨λ“œλŠ” python μ½”λ“œλ₯Ό μž‘λ™μ‹œν‚€λŠ” 일반적인 κ³Όμ •κ³Ό 맀우 μœ μ‚¬ν•©λ‹ˆλ‹€. 즉 ν•œμ€„ ν•œμ€„ λ°”λ‘œ μ‹€ν–‰ν•˜λ©΄μ„œ λ°”λ‘œ κ²°κ³Όλ₯Ό 확인해 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.

a = tf.constant(3)
b = tf.constant(5)
c = a + b

Imgur

그렇기에 μœ„ 그림처럼 ν…μ„œ μ•ˆμ— μžˆλŠ” 값듀을 λ°”λ‘œλ°”λ‘œ 확인 κ°€λŠ₯ν•©λ‹ˆλ‹€.

λ³€μˆ˜ 관리

Graph

Tensorflow Graph의 λͺ¨λ“  λ…Έλ“œμ™€ ν…μ„œμ—λŠ” κ³ μœ ν•œ 이름을 κ°€μ§€κ³  μžˆμŠ΅λ‹ˆλ‹€.

tf.constant(3, name='const')

μœ„ μ½”λ“œλ₯Ό μˆ˜ν–‰ν•˜κ²Œ 되면 이름이 'const'인 operationκ³Ό 이름이 'const:0' ν…μ„œλ₯Ό λ§Œλ“€κ²Œ λ©λ‹ˆλ‹€.
그렇기에 python λ³€μˆ˜μ— κ²°κ³Όλ₯Ό μ•Šμ•„λ„ μš°λ¦¬λŠ” tensor λ˜λŠ” operation을 호좜 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
μ•„λž˜ μ½”λ“œλ₯Ό 톡해 확인해 λ³΄κ² μŠ΅λ‹ˆλ‹€.

tf.constant(3, name='const')

# tensorflow version 1.x
g = tf.get_default_graph()

# call 'const:0' tensor
g.get_tensor_by_name('const:0')

# call 'const' operation
g.get_operation_by_name('const')

μœ„ μ½”λ“œλ₯Ό 보면
GraphλŠ” λ…Έλ“œμ™€ ν…μ„œμ— κ³ μœ ν•œ 이름을 λΆ€μ—¬ν•˜κ³  κ·Έ μ΄λ¦„μœΌλ‘œ ν…μ„œμ™€ λ…Έλ“œλ₯Ό κ΄€λ¦¬ν•˜κΈ° λ•Œλ¬Έμ— μ•Œλ©΄ ꡳ이 파이썬 λ³€μˆ˜μ— λ“±λ‘ν•˜μ§€ μ•Šμ•„λ„ λœλ‹€λŠ” 점 μž…λ‹ˆλ‹€.

Eager Execution

반면 Eager Execution은 파이썬 λ³€μˆ˜λ₯Ό 톡해 Tensor을 κ΄€λ¦¬ν•©λ‹ˆλ‹€.

a = tf.constant(3, name='const')

Computation Speed

계산 μŠ€ν”Όλ“œλŠ” Graph κ°€ Eager Execution 보닀 λΉ λ¦…λ‹ˆλ‹€.
eager execution 은 line-by-line 으둜 ν•œμ€„ν•œμ€„ μ‹€ν–‰ν•˜μ§€λ§Œ
graph execution 은 compile 을 톡해 효율적으둜 κ·Έλž˜ν”„λ₯Ό build ν•˜κ³  μˆ˜ν–‰ν•˜κΈ° λ•Œλ¬Έμ— eager execution 보닀 λΉ λ₯΄κ²Œ μˆ˜ν–‰ λ©λ‹ˆλ‹€.

4μΈ΅ 짜리 Dense Layer 을 λ§Œλ“ ν›„ μˆ˜ν–‰ν•΄ λ³΄λ©΄μ„œ 속도λ₯Ό ν™•μΈν•΄λ΄…λ‹ˆλ‹€.

Eager execution mode

# tensorflow 2.x eager Execution
import tensorflow as tf 
import numpy as np 
import time 
from tqdm import tqdm

# load MNIST Dataset 
train_data, test_data = tf.keras.datasets.mnist.load_data()
(train_xs, train_ys) = train_data
train_xs = train_xs.reshape([-1, 784])
train_xs = train_xs.astype(np.float32)

# Generate W, b
def generate_w_b(in_, out):
  w_init = tf.random.normal([in_, out])
  w = tf.Variable(w_init, dtype=tf.float32)
  b_init = tf.zeros(out)
  b = tf.Variable(b_init,dtype=tf.float32)
  return w, b

w1, b1 = generate_w_b(784, 128)
w2, b2 = generate_w_b(128, 128)
w3, b3 = generate_w_b(128, 128)
w4, b4 = generate_w_b(128, 10)

# Run Dense Layer , 100 times
s = time.time()
for i in tqdm(range(100)):
    layer = train_xs

    z1 = tf.matmul(layer, w1) + b1
    a1 = tf.nn.relu(z1)

    z2 = tf.matmul(a1, w2) + b2
    a2 = tf.nn.relu(z2)

    z3 = tf.matmul(a2, w3) + b3
    a3 = tf.nn.relu(z3)

    logits = tf.matmul(a3, w4) + b4

print('Consume time : {}'.format(time.time() - s))
# >>> 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 100/100 [00:31<00:00,  3.22it/s] Consume time : 31.025146961212158

Graph execution mode

연산이 μˆ˜ν–‰λ˜λŠ” 뢀뢄을 Graph 둜 λ³€ν™˜ν›„ μ—°μ‚°ν•©λ‹ˆλ‹€.

# tensorflow 2.x Graph Execution
import tensorflow as tf 
import numpy as np 
import time 
from tqdm import tqdm

# load MNIST Dataset 
train_data, test_data = tf.keras.datasets.mnist.load_data()
(train_xs, train_ys) = train_data
train_xs = train_xs.reshape([-1, 784])
train_xs = train_xs.astype(np.float32)

# Generate W, b
def generate_w_b(in_, out):
    w_init = tf.random.normal([in_, out])
    w = tf.Variable(w_init, dtype=tf.float32)
    b_init = tf.zeros(out)
    b = tf.Variable(b_init,dtype=tf.float32)
    return w, b

w1, b1 = generate_w_b(784, 128)
w2, b2 = generate_w_b(128, 128)
w3, b3 = generate_w_b(128, 128)
w4, b4 = generate_w_b(128, 10)

# Run Dense Layer, 100 times
@tf.function
def graph_execution(layer):
    z1 = tf.matmul(layer, w1) + b1
    a1 = tf.nn.relu(z1)

    z2 = tf.matmul(a1, w2) + b2
    a2 = tf.nn.relu(z2)

    z3 = tf.matmul(a2, w3) + b3
    a3 = tf.nn.relu(z3)

    logits = tf.matmul(a3, w4) + b4

# execute Graph, 100 times 
s = time.time()
for i in tqdm(range(100)):
    graph_execution(train_xs)
print('Consume time : {}'.format(time.time() - s))
# >>> 100%|β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 100/100 [00:00<00:00, 847.78it/s] Consume time : 0.12074828147888184

속도가 Eager Execution mode 와 Graph Execution Mode κ°€ μ•½ 266λ°° 정도 차이가 λ‚˜λŠ”κ²ƒμ„ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

Sum-up

Tensorflow 을 톡해 μ—°μ‚°(Computation)을 μˆ˜ν–‰ν•˜λŠ” 방법은 크게 Eager execution, Graph execution λͺ¨λ“œκ°€ μžˆμŠ΅λ‹ˆλ‹€.
Eager execution λͺ¨λ“œλŠ” 톡해 기쑴에 μ‚¬μš©ν–ˆλ˜ 파이썬 λ³€μˆ˜ 관리 방식을 μ‚¬μš©ν•  수 있으며 Debug λͺ¨λ“œλ₯Ό μ‚¬μš© κ°€λŠ₯ν•©λ‹ˆλ‹€.
ν•˜μ§€λ§Œ Graph λͺ¨λ“œλ³΄λ‹€ 속도가 λŠλ¦½λ‹ˆλ‹€.
그렇기에 μš°λ¦¬λŠ” Eager execution 을 톡해 λ¨Όμ € λŒμ•„κ°€λŠ” μ½”λ“œλ₯Ό λ§Œλ“€κ³  이후
eager Execution μ—μ„œ Computation 뢀뢄을 Graph Execution 으둜 λ°”κΎΈλŠ” μ½”λ“œ μž‘μ—…μ„ μˆ˜ν–‰ν•˜κ²Œ λ©λ‹ˆλ‹€.