오랜만에 설명 자료 하나 번역합니다. 주로 http://blog.aylien.com/introduction-generative-adversarial-networks-code-tensorflow/ 를 보고 번역합니다만 적당히 편집과 내용추가가 있어서 1:1 번역은 아닙니다.
GAN?
시선을 끌기위해 예제부터 뽑아오자. 아래 예제가 GAN으로 만든 - 요즘 신문기사처럼 표현하면 "인공지능이 그린" 그림이다.
서문
최근에 GAN: Generative Adversarial Network가 무지무지 인기를 끌고있다. GAN은 Ian Goodfellow가 https://arxiv.org/abs/1406.2661 등에서 제안한 것이다. 참고로 2014, 2015년에 Adversarial example 등 용어가 범람하면서 다소 개념이 애매한 부분이 있는데, 이는 Ian Goodfellow의 Quora답변을 참고하자. 아무튼 위대한 Yann LeCun이 꼽은 중요한 기술 1위 GAN이라는게 뭔지 한번 알아보겠다.
Discriminative vs. Generative 구별 대 생성 모델
간단하게 구별 모델과 생성 모델을 짚고 넘어가자.
- 구별 모델은 입력-->출력의 관계를 알아내는 것이 목적이다. 즉, 조건부 확률 p(y|x)을 추정하자는 것.
- 생성 모델은 더 일반적인 입력과 출력의 관계를 알아내려는 모델이다. 즉 p(x, y)을 추정하자는 것. p(x, y)를 알면 당연히 p(y|x)도 알아낼 수 있을 뿐만 아니라 더 재밌는 일을 할 수 있다. 예를 들어 새로운 (x, y) 데이터를 생성할 수 있고, 그래서 이름이 생성 모델이다. 더 강력한 정보를 필요로 하는 만큼 더 어렵다.
Generative Adversarial Networks
(그림 출처: https://ishmaelbelghazi.github.io 라고 나오는데 이 블로그가 사라짐..)
위의 그림이 GAN의 구조다. 간단하지요! 그야 간단히 그렸으니까 그렇고, 저기에서 보통 discriminator (구별망)와 generator (생성망)가 여러 층의 신경망로 이루어진 경우가 대부분이다. 대부분의 연구가 이미지를 다루고 있고, 그래서 두 신경망도 컨브넷인 경우가 많다. 자, 핵심은,
GAN의 핵심은,
- 생성망은 최대한 실제 데이터와 비슷한 데이터를 생성해내려고 하고
- 구별망은 열심히 그 둘을 구별하려고 한다는 것
이다. 이를 원문에서는 minimax two-player game이라고 표현했다.
- arg max D: 여기에서는 목적함수를 극대화하는 분류망 D를 찾는다
- 첫번째 항 E[Log D(x)]은 실제 데이터 (x), 예를 들어 진짜 그림을 넣었을 때의 목적함수의 값이다.
- 두번째 항 E[log(1-D(g(z)))]은 가짜 데이터 (G(z)), 즉 생성망이 만들어낸 그림이 들어가있다. 그리고 arg max D인데 항 내부는 1-D(G(z))이다. 다시 말해 둘째 항의 극대화는 D(G(z))의 극소화다.
- 결과적으로, 이 두 항의 목적함수를 이용해
- 진짜 그림을 넣으면 큰 값을,
- 가짜 그림을 넣으면 작은 값을
- ..출력하도록 구별망 D를 열심히 학습시키자는 것이다.
- arg min G: 이 말은 목적함수를 극소화하는 생성망 G를 찾자는 이야기다.
- G는 두번째 항에만 포함되어있다.
- 전체 함수를 극소화하는 G는, 둘째 항을 극소화하는 G이고, 결국 D(G(z))를 극대화하는 G이다.
- 결과적으로, 구별망을 속이는 생성망 G를 열심히 학습시켜보자는 이야기다.
코드
def generator(input, hidden_size):
h0 = tf.nn.softplus(linear(input, hidden_size, 'g0'))
h1 = linear(h0, 1, 'g1')
return h1
def discriminator(input, hidden_size):
h0 = tf.tanh(linear(input, hidden_size * 2, 'd0'))
h1 = tf.tanh(linear(h0, hidden_size * 2, 'd1'))
h2 = tf.tanh(linear(h1, hidden_size * 2, 'd2'))
h3 = tf.sigmoid(linear(h2, 1, 'd3'))
return h3
각각 생성망과 구별망이다. 여기에서 중요한 내용이 언급되었다. 생성망보다 복잡하게 구별망을 짜야한다!
사실은 아래 코드가 핵심이다.
with tf.variable_scope('G'):
z = tf.placeholder(tf.float32, shape=(None, 1))
G = generator(z, hidden_size)
with tf.variable_scope('D') as scope:
x = tf.placeholder(tf.float32, shape=(None, 1))
D1 = discriminator(x, hidden_size)
scope.reuse_variables()
D2 = discriminator(G, hidden_size)
loss_d = tf.reduce_mean(-tf.log(D1) - tf.log(1 - D2))
loss_g = tf.reduce_mean(-tf.log(D2))
아래 두 줄이 각각 구별망과 생성망에 arg max D, arg min G를 구현한 부분이다. loss를 감소하도록 학습되기 때문에 loss_d는 위에서 소개한 식과 부호가 반대다.
결과
보강
위의 영상을 보면 결과가 조금 아쉬운데, 이에 대해 https://arxiv.org/abs/1606.03498에서 해결 방법을 소개했다. 미니배치를 써라! 구별망이 한번에 여러 샘플을 보게 하라는 내용이다. 그 외에도 몇 가지 방법이 있는데 실제로 써본적이 없으므로 원문을 참고하면 된다.
그 결과는? 아래처럼 더 잘된다.
------
번역은 여기까지입니다. 우리모두 열공!
이해하기 쉬운 번역 감사합니다.
ReplyDelete"두번째 항 E[log(1-D(g(z)))]은 가짜 데이터 (G(z)), 즉 생성망이 만들어낸 그림이 들어가있다. 그리고 arg max D인데 항 내부는 1-D(G(z))이다. 다시 말해 둘째 항의 극대화는 D(G(z))의 극소화다."
ReplyDelete이 문구에서, D가 G(Z)를 보고 이놈은 가짜야라고 판단해서 return하는 값이 0 일 텐데요. 그럴려면 D(G(z))가 극대화 되어야 하는 것 아닌가요??
"D가 G(Z)를 보고 이놈은 가짜야라고 판단해서 return하는 값이 0 일 텐데요." : 맞습니다.
Delete그러므로 D(G(z))를 극소화 ([0, 1] 범위 내에서 0에 가깝게) 하는것이죠.
Log(1-x)는 monotonically 감소 함수이므로 D(G(z))의 극소화가 Log(1-D(G(z)))의 극대화가 되구요.
This comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDelete