2017. 6. 16. 14:34ㆍmachine learning
tensorflow에서는 변수를 공유해서 쓸 수 있는 기능을 제공하고 있다. 가령 아래의 예제를 살펴보자. 아래의 예제는 relu function을 5개 생성하는 것이 목적인데, 생성 시에 threshold 파라미터를 함께 넘겨줘서 초기화를 진행하고 있다.
def relu(X, threshold):
with tf.name_scope("relu"):
[...]
return tf.maximum(z, threshold, name="max")
threshold = tf.Variable(0.0, name="threshold")
X = tf.placeholder(tf.float32, shape=(None, n_features), name="X")
relus = [relu(X, threshold) for i in range(5)]
위와 같은 경우는 파라미터 개수가 적어서 가독성이 괜찮았지만 만약에 파라미터 개수가 10개 혹은 그 이상이라면, 위와 같은 방식으로 초기화 하는 것이 바람직할까?
이를 위해 tensorflow에서는 sharing variable을 지원한다. 아래의 방식을 살펴보자.
def relu(X):
with tf.variable_scope("relu", reuse=True):
threshold = tf.get_variable("threshold")
[...]
return tf.maximum(z, threshold, name="max")
x = tf.placeholder(tf.float32, shape=(None, n_features), name="X")
with tf.variable_scope("relu"):
threshold = tf.get_variable("threshold", shape=(), initializer=tf.constant_initializer(0.0))
relues = [relu(X) for relu_index in range(5)]
variable_scope를 두고 reuse를 True로 설정을 했다. 이렇게 되면, 첫 번째 relu 함수 호출 시에 relu/threshold란 변수를 만들고 그 이후에는 relu/threshold 변수를 재사용할 것이다. 이렇게 사용될 경우 tensorflow에서는 동일한 이름의 이름 범위가 있다면 접미사 부분만 인덱스를 추가한다. 아래의 그림과 같다.
relu 이름의 경우 _1,_2,_3,_4,_5를 추가하여 unique를 유지했고 각각의 relu는 threshold라는 변수를 함께 사용하고 있다.
참고로 reuse=True로 설정된 경우, 블록 내에서 False로 다시 설정할 수 없다. 게다가 reuse로 설정한 변수 내에 다른 변수를 정의하면 reuse=True를 자동으로 상속 받게 된다. 마지막으로 오직 변수만 get_variable() 함수에 의해 재사용이 가능하다.
위의 코드의 경우 실제 threshold 변수는 relu에서만 사용되는데 relu 함수 바깥에다가 정의하는 게 아무래도 모양이 나빠보인다. threshold 변수를 relu 함수 내에 정의하고, 위의 reuse 속성을 상속 기능을 활용해서 아래와 같이 다시 정의해 보자.
def relu(X):
threshold = tf.get_variable("threshold", shape=(), initializer=tf.constant_initializer(0.0))
[...]
return tf.maximum(z, threshold, name="max")
X = tf.placeholder(tf.float32, shape=(None, n_features), name="X")
relus = []
for relu_index in range(5):
with tf.variable_scope("relu", reuse=(relu_index >= 1) as scope:
relus.append(relu(X))
relu_index가 1일때는 reuse를 False로, 그 외에는 relu를 재사용하도록 구성했으며, 아래의 그림과 같다. 참고로 threshold의 경우 reuse 상속을 받기 때문에 함께 재사용된다.