딥러닝 프레임워크는 동작 방식에 따라 크게 두 가지로 나눌 수 있다.
- Define-and-Run (정적 계산 그래프)
- Define-by-Run (동적 계산 그래프)
Define-and-Run
Define-and-Run을 직역하면 '계산 그래프를 정의한 다음 데이터를 흘려보낸다'는 뜻이다.
즉, 아래 순서대로 동작이 진행된다.
- 사용자는 계산 그래프를 정의한다.
- 프레임워크는 주어진 그래프를 컴퓨터가 처리할 수 있는 형태로 변환한다.
- 데이터를 흘려보낸다.
# 계산 그래프 정의
a = Variable('a')
b = Variable('b')
c = a*b
d = c + Constant(1)
# 계산 그래프 컴파일
f = compile(d)
# 데이터 흘려보내기
d = f(a=np.array(2), b=np.array(3))
먼저 첫 네 줄로 계산 그래프를 정의했다.
주의할 점은 이 네 줄의 코드에서는 실제 계산이 이루어지지 않는다.
이는 실제 '수치'가 아닌 '기호'를 대상으로 프로그래밍됐기 때문이다.
이와같이 Define-and-Run 방식 프레임워크에서는 실제 데이터가 아닌 기호를 사용한 추상적인 계산 절차를 코딩해야 한다.
또한 전용 DSL(Domain-specific Language)을 사용해야 한다.
앞의 예에서는 '상수는 Constant에 담아라' 라는 규칙을 들 수 있을 것이다.
DSL이란 '도메인 특화 언어'라는 뜻이다.
우리에게 익숙한 SQL도 DB를 위한 DSL의 한 종류라고 볼 수 있다.
텐서플로우로 작성한 정적 계산 그래프 코드를 보면 아래와 같다.
import tensorflow as tf
flg = tf.placeholder(dtype=tf.bool)
x0 = tf.placeholder(dtype=df.float32)
x1 = tf.placeholder(dtype=df.float32)
y = tf.cond(flg, lambda: x0+x1, lambda: x0*x1)
위 코드에서는 flg가 True이면 첫번째 람다식을 실행하고, flg가 False이면 두번째 람다식을 사용하는 동작을 수행하고 있다.
즉, 우리가 일반적으로 사용하는 if, else 문이 아닌 독자적인 언어(tf.cond)를 사용해야 한다.
딥러닝 초기에는 이 Define-and-Run 방식을 많이 사용했다.
Define-by-Run
Define-by-Run을 직역하면 '데이터를 흘려보냄으로써 계산 그래프가 정의된다'라는 뜻이다.
즉, 아래의 동작이 동시에 이루어진다.
- 데이터 흘려보내기
- 계산 그래프 구축
import numpy as np a = Variable(np.ones(10)) b = Variable(np.ones(10) * 2) c = b*a d = c + 1 print(d)
이는 넘파이를 사용한 일반적인 프로그램과 흡사하다.
유일한 차이는 넘파이 데이터를 Variable이라는 클래스로 감쌌다는 점이다.
Define-by-Run 방식은 2015년에 체이너(Chainer)에 의해 처음 제창되고, 이후 많은 프레임워크에 채용되고 있다.
- PyTorch
- Tensorflow 2.0
Define-by-Run의 장점
동적 계산 그래프 프레임워크에서는 일반 넘파이를 사용할 때와 같은 방식으로 수치 계산이 가능하다.
따라서 프레임워크 고유의 '도메인 특화 언어'를 배우지 않아도 된다.
x = Variable(np.array(3.0))
y = Variable(np.array(0.0))
while True:
y = y + x
if y.data > 100:
break
y.backward()
이와 깉이 계산에 while문이나 if문을 사용할 수 있다.
그러면 계산 그래프가 자동으로 만들어진다.
동적 계산 그래프는 디버깅에도 유리하다.
계산 그래프가 파이썬 프로그램 형태로 실행되기 때문에 디버깅도 항상 파이썬 프로그램으로 할 수 있다.
Define-and-Run 방식이 디버깅이 어려운 이유
이에 반해 Define-and-Run 프레임워크에서는 컴파일을 거쳐 프레임워크만 이해하고 실행할 수 있는 표현 형식으로 변환된다.
당연히 파이썬 프로세서는 이 독자적인 표현 방식을 이해할 수 없다.
또한 정적 계산 그래프에서 디버깅이 어려운 본질적인 이유는 여기에 있다.
'계산 그래프 정의'와 '데이터 흘려보내기' 작업이 분리되어 있다.
버그는 주로 데이터를 흘려보낼 때 발견되지만, 문제의 원인은 '계산 그래프 정의'에 있는 경우가 대부분이기 때문이다.
다시 말해 문제 발생 시점과 원인이 만들어지는 시점이 떨어져 있어서 어디가 문제인지 특정하기 어려울 때가 많다.
Define-and-Run의 장점
그렇다면 Define-and-Run의 장점은 뭘까?
바로 성능이다.
사용자가 직접 계산 그래프를 구성할 수 있다는 것은 직접 최적화가 가능하다는 뜻이고,
이를 통해 '여러 개의 연산'을 '하나의 연산' 으로 '축약'하는 것 또한 가능하다.
또 다른 장점은 어떻게 컴파일하느냐에 따라 다른 실행 파일로 변환할 수 있기에, 따라서 파이썬이 아닌 다른 환경에서도 데이터를 흘려보내는 게 가능하다는 것이다.
파이썬에서 벗어났을 때 얻는 가장 큰 혜택은 파이썬 자체가 주는 오버헤드가 사라진다는 것이다.
IoT처럼 자원이 부족한 edge 전용 환경에서는 특히 중요한 특징이다.
또한 학습을 여러 대의 컴퓨터에 분산해 수행하는 경우에도 Define-and-Run 방식이 유리할 때가 있다.
특히 계산 그래프 자체를 분할하여 여러 컴퓨터로 분배하는 시나리오는 사전에 전체 계산 그래프가 구축되어 있어야만 가능하다.
정리
Define-and-Run
- 장점
- 성능이 좋다
- 신경망 구조를 최적화하기 쉽다
- 분산 학습 시 더 편리하다.
- 단점
- 독자적인 언어(규칙)을 익혀야 한다.
- 동적 계산 그래프를 만들기 어렵다.
- 디버깅하기 매우 어려울 수 있다.Define-by-Run
- 장점
- 파이썬으로 계산 그래프를 제어할 수 있다.
- 디버깅이 쉽다
- 동적인 계산 처리에 알맞다.
- 단점
- 성능이 낮을 수 있다.
본 내용은 밑바닥부터 시작하는 딥러닝 3을 참고하여 작성되었습니다.
밑바닥부터 시작하는 딥러닝 3 - 예스24
코드 3줄이 딥러닝 프레임워크가 되는 마법이 책은 ‘밑바닥부터’ 직접 만들어보며 즐겁게 딥러닝을 익히는 시리즈의 장점을 그대로 따랐다. 코드 3줄로 시작해 60단계까지 차근차근 구현해보
www.yes24.com
'CS Repository > 기초 강화학습' 카테고리의 다른 글
[강화학습] 마르코프 결정 과정(MDP) (0) | 2025.08.28 |
---|---|
[강화학습] 밴디트 문제 (1) | 2025.08.28 |
python - from A import B와 import A.B as b의 차이 (0) | 2025.08.25 |
python 애스터리스크(*) - 언패킹의 역할과 예제 (0) | 2025.08.25 |
Python - zip의 역할과 예제 (0) | 2025.08.24 |