https://www.youtube.com/watch?v=BZwUR9hvBPE
GAN: Generative Adversarial Networks (๊ผผ๊ผผํ ๋ฅ๋ฌ๋ ๋ ผ๋ฌธ ๋ฆฌ๋ทฐ์ ์ฝ๋ ์ค์ต)
์์ฑ์ ์ ๋ ์ ๊ฒฝ๋ง์ด๋ผ๊ณ ํ๋ค.
๊ฒฝ์์ ํตํด์ ๋ฐฐ์ฐ๋ ๊ฐ๋ ์ ๊ธฐ์ ์ด๋ค.
์ค์ ์์๊ฒ ๊ฐ์ ๋ญ๊ฐ๋ฅผ ๋ง๋ค์ด๋ธ๋ค ๊ด์ ์์
์์ฑ์ ์ ํด๋ผ ์ ์๋ค๋ผ๋ ๊ด์ ์ผ๋ก ๋ณธ๋ค๋ฉด
Pix2Pix๋ผ๋ ๋ง์ ์ด์ฉํ๊ฒ ๋๋ฉด
NG = No Good
ํ๋ณ์(๋ถ๋ฅ)์ ์์ฑ์(ํด๋ฌ์คํฐ๋ง)
์์ฑ๋ชจ๋ธ์ ๋ชฉํ
Generative Adversarial์ ๋์ ์ธ Network-2014๋ Ian Goodfellow
์์ฑ์(Generator)
๋ ์๋ฌด ์๋ฏธ ์๋ ๋๋ค ๋
ธ์ด์ฆ๋ก๋ถํฐ ์ ๊ฒฝ๋ง์์์ ์ฐ์ฐ์ ํตํด ์ด๋ฏธ์ง ํ์์ ๋ฒกํฐ๋ฅผ ์์ฑํด ๋
๋๋ค. ์ฆ, ๋ฌด์์ ์ ๋ฅผ ์ฐฝ์กฐํ๋ ๊ฒ๊ณผ ๊ฐ์ ์ญํ ์ ํฉ๋๋ค
Generative Model
.ํ๋ณ์(Discriminator)
๋ ๊ธฐ์กด์ ์๋ ์ง์ง ์ด๋ฏธ์ง์ ์์ฑ์๊ฐ ๋ง๋ค์ด๋ธ ์ด๋ฏธ์ง๋ฅผ ์
๋ ฅ๋ฐ์ ๊ฐ ์ด๋ฏธ์ง๊ฐ Real ์ธ์ง, Fake ์ธ์ง์ ๋ํ ํ๋จ ์ ๋๋ฅผ ์ค์ซ๊ฐ์ผ๋ก ์ถ๋ ฅํฉ๋๋ค.
Discriminative Model
์์กฐํํ๋ฅผ ๋ง๋๋ ๋ฒ์ธ๊ณผ ๊ฒฝ์ฐฐ์ด ์ธ์ฐ๋ฏ์ด. ๊ฒ์์ ๊ฒฝ์์ ํตํด์ ์์กฐํ์ด ์งํ์ฒ๋ผ ๋ง๋ค๋๊น์ง ์ฑ๋ฅ์ ๊ฐ์ ํ๋ค.
DCGAN(Deep Convolutional GAN)- 2015
def make_generator_model():
# Start
model = tf.keras.Sequential()
# First: Dense layer
model.add(layers.Dense(7*7*256, use_bias=False, input_shape=(100,)))
model.add(layers.BatchNormalization())
model.add(layers.LeakyReLU())
# input_shape=(100,))) ๋ฐฐ์น์ฌ์ด์ฆ(1),100 ์ ํ์ค๋ฒกํฐ ์์ฑ
#๊ทธํ 7x7x256 12544 ๊ฐ ๋ด์ค๋ ์ด์ด๋ฅผ ๊ฑฐ์ณ์ batch,12544
#๊ทธํ 3์ฐจ์์ ๋ฒกํฐ๋ก ๋ณํ
# Second: Reshape layer
model.add(layers.Reshape((7, 7, 256)))
# Third: Conv2DTranspose layer
model.add(layers.Conv2DTranspose(128, kernel_size=(5, 5), strides=(1, 1), padding='same', use_bias=False))
7, 7, 128
# Fourth: Conv2DTranspose layer
model.add(layers.Conv2DTranspose(64, kernel_size=(5, 5), strides=(2, 2), padding='same', use_bias=False))
#(14, 14, 64)
# Fifth: Conv2DTranspose layer
model.add(layers.Conv2DTranspose(1, kernel_size=(5, 5), strides=(2, 2), padding='same', use_bias=False, \
activation='tanh'))
#(28, 28, 1)
return model
What is Transposed Convolutional Layer?
[1(๋ฐฐ์น์ฌ์ด์ฆ), 28, 28, 1] 1์ฑ๋ ์ด๋ฏธ์ง ์์ฑ๋จ.
BatchNormalization
ย ๋ ์ด์ด๋ ์ ๊ฒฝ๋ง์ ๊ฐ์ค์น๊ฐ ํญ๋ฐํ์ง ์๋๋ก ๊ฐ์ค์น ๊ฐ์ ์ ๊ทํ
๋ ธ๋ฉ๋ฆฌ์ ์ด์ ์ ์ ์ฒด ๋ฐฐ์น = ์ ์ฒด ์งํฉ์ผ๋ก ๊ณ์ฐํด์ผ ํ์ง๋ง ๋ฏธ๋ ๋ฐฐ์น๋ก ์ ๋ ฅํ๋ค๋ ์ฌ์ค์ด ํฌ์ธํธ ๋ฏธ๋๋ฐฐ์น๋ก ์ ๋ ฅํ์ง๋ง nn์ ์ ์ฒด ์งํฉ์ ๋ํํ๋๊ฒ์ฒ๋ผ ์๊ฐํ๋ค.
r b๊ฐ ์ถ๊ฐ๋์์ผ๋ฏ๋ก rb๋ฅผ ๊ธฐ์ตํด๋์ผ๋ฉด ์๋ ํํ๋ก ๋๋๋ฆฌ๊ธฐ๋ ๊ฐ๋ฅํ๋ค.
BN์ ์ ๊ฒฝ๋ง ๊ณ์ด๋ก ์ญ์ ํ๊ฐ ๊ฐ๋ฅํ๋ค.
ํ๋ณ์ ๋ง๋ค๊ธฐ
def make_discriminator_model():
# Start
model = tf.keras.Sequential()
#28,28,1์ด๋ฏธ์ง๋ฅผ ๋ฐ์์
#๋ฐ๋๋ก ํด๊ฐ (28, 28, 1) โ (14, 14, 64) โ (7, 7, 128)
# First: Conv2D Layer
model.add(layers.Conv2D(64, (5, 5), strides=(2, 2), padding='same', input_shape=[28, 28, 1]))
model.add(layers.LeakyReLU())
model.add(layers.Dropout(0.3))
# Second: Conv2D Layer
model.add(layers.Conv2D(128, (5, 5), strides=(2, 2), padding='same'))
# Third: Flatten Layer
model.add(layers.Flatten())
#Flatten ์ธต์ ์ฌ์ฉํด 3์ฐจ์ ์ด๋ฏธ์ง๋ฅผ 1์ฐจ์์ผ๋ก ์ญ ํด์ 7x7x128=6272, ์ฆ (1, 6272)๋ฒกํฐ๋ฅผ ๋ง๋ฌ
# Fourth: Dense Layer
model.add(layers.Dense(1))# ์ง์ง ๊ฐ์ง 1๊ฐ๋ง ๊ฒฐ๊ณผ๋กํจ.
return model
ํ์ต ์ํ๋๋ฒ
์์คํจ์์ ์ตํฐ๋ง์ด์ (์ต์ ํ)ํจ์ ๋ฐ๊ฟ๋ณด๊ธฐ
์์ค = ๊ต์ฐจ ์ํธ๋กํผ
๋๊ฐ์ ์ฐจ์ด๊ฐ ์ผ๋ง๋ ๋๋์ง๋ฅผ ์ ๋์ ์ผ๋ก ๋ณด์ฌ์ค์์๋ค.
ํ ๊ฐ์ ์ด๋ฏธ์ง๊ฐ ๊ฐ์ง์ธ์ง ์ง์ง์ธ์ง ๋ํ๋ด๋ 2๊ฐ ํด๋์ค ๊ฐ ๋ถ๋ฅ ๋ฌธ์ ๋ฅผ ํ์ด์ผ ํ๋ฏ๋ก, ์ด์ง ๊ต์ฐจ ์ํธ๋กํผ(binary cross entropy)๋ฅผ ์ฌ์ฉ
์์ฑ์ : ํ๋ณ์๊ฐ Fake Image์ ๋ํด ํ๋ณํ ๊ฐ, ์ฆย D(fake_image)
ย ๊ฐ์ดย 1
์ ๊ฐ๊น์์ง๋ ๊ฒ
ํ๋ณ์ : Real Image ํ๋ณ๊ฐ, ์ฆย D(real_image)
๋ย 1
์, Fake Image ํ๋ณ๊ฐ, ์ฆย D(fake_image)
๋ย 0
์ ๊ฐ๊น์์ง๋ ๊ฒ
์์คํจ์์ ๋ค์ด๊ฐ๋ ๊ฐ์ ๋ชจ๋ ํ๋ณ์์ ํ๋ณ๊ฐ
tf.keras.losses์ BinaryCrossEntropy ํด๋์ค๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ณธ์ธ์๊ฒ ๋ค์ด์ค๋ ์ธํ๊ฐ์ด 0-1 ์ฌ์ด์ ๋ถํฌํ๋ ํ๋ฅ ๊ฐ์ด๋ผ๊ณ ๊ฐ์
cross_entropy = tf.keras.losses.BinaryCrossentropy(from_logits=True)
(from_logits=True) ์ต์ ์ ์ฐ๋ฉด๋๋ค. sigmoid ํจ์๋ฅผ ์ฌ์ฉํด 0~1์ผ๋ก ์ ๊ทํํ ๊ฐ์ด ๋ค์ด๊ฐ.
?#๋ ์ด์ด์ ์๊ทธ๋ชจ์ด๋ ๋๋ ค๋๋๋?#
fake_output
ย : ์์ฑ์๊ฐ ์์ฑํ Fake Image๋ฅผ ๊ตฌ๋ถ์์ ์
๋ ฅ์์ผ์ ํ๋ณ๋ ๊ฐ, ์ฆย D(fake_image)
real_output
ย : ๊ธฐ์กด์ ์๋ Real Image๋ฅผ ๊ตฌ๋ถ์์ ์
๋ ฅ์์ผ์ ํ๋ณ๋ ๊ฐ, ์ฆย D(real_image)
ํ๋ณ์๊ฐ 1.0์ผ๋ก ๊ฐ๊น์์ง๊ฐ ๋๋ค ํ๋จํ๋ฉด ํ๋ณ์๊ฐ ๋๋ฌด ์ผ์ ์ํ๊ณ ์์ด์ ๋ฌธ์
์์ฑ์๊ฐ ์ ๋ฐ๋ก ์ผ์ ๋ชปํ๊ณ ์๋ค.
real accuracy, fake accuracy 0.5๋ก ๋์ค๋๊ฒ ์ด์์ ์ด๋ค. ๋์ถฉ์ฐ์ด๋ ๋์ค๋ ํ๋ฅ ์ด๊ธฐ๋๋ฌธ์.
์ตํฐ ๋น์ฐํ ์๋ด.
@tf.function
def train_step(images): #(1) ์
๋ ฅ๋ฐ์ดํฐ
noise = tf.random.normal([BATCH_SIZE, noise_dim]) #(2) ์์ฑ์ ์
๋ ฅ ๋
ธ์ด์ฆ
with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape: #(3) tf.GradientTape() ์คํ
generated_images = generator(noise, training=True) #(4) generated_images ์์ฑ
#(5) discriminator ํ๋ณ
real_output = discriminator(images, training=True)
fake_output = discriminator(generated_images, training=True)
#(6) loss ๊ณ์ฐ
gen_loss = generator_loss(fake_output)
disc_loss = discriminator_loss(real_output, fake_output)
#(7) accuracy ๊ณ์ฐ
real_accuracy, fake_accuracy = discriminator_accuracy(real_output, fake_output)
#(8) gradient ๊ณ์ฐ
gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables)
gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.trainable_variables)
#(9) ๋ชจ๋ธ ํ์ต
generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables))
discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables))
return gen_loss, disc_loss, real_accuracy, fake_accuracy #(10) ๋ฆฌํด๊ฐ
(1) ์
๋ ฅ ๋ฐ์ดํฐ: Real Image ์ญํ ์ ํ ย images
ย ํ ์ธํธ๋ฅผ ์
๋ ฅ์ผ๋ก ๋ฐ์
(2) ์์ฑ์ ์
๋ ฅ ๋
ธ์ด์ฆ : generator๊ฐ FAKE IMAGE๋ฅผ ์์ฑํ๊ธฐ ์ํย noise
๋ฅผย images
ย ํ ์ธํธ์ ๊ฐ์ ํฌ๊ธฐ์ธย BATCH_SIZE
ย ๋งํผ ์์ฑํจ
(3)ย tf.GradientTape()
๋ ๊ฐ์ค์น ๊ฐฑ์ ์ ์ํ Gradient๋ฅผ ์๋ ๋ฏธ๋ถ์ผ๋ก ๊ณ์ฐํ๊ธฐ ์ํดย with
ย ๊ตฌ๋ฌธ ์ด๊ธฐ
(4) generated_images ์์ฑ : generator๊ฐย noise
๋ฅผ ์
๋ ฅ๋ฐ์ ํย generated_images
ย ์์ฑ
(5) discriminator ํ๋ณ : discriminator๊ฐ Real Image์ธย images
์ Fake Image์ธย generated_images
๋ฅผ ๊ฐ๊ฐ ์
๋ ฅ๋ฐ์ ํย real_output
,ย fake_output
ย ์ถ๋ ฅ(
6) loss ๊ณ์ฐ :ย fake_output
,ย real_output
์ผ๋ก generator์ discriminator ๊ฐ๊ฐ์ loss ๊ณ์ฐ
(7) accuracy ๊ณ์ฐ :ย fake_output
,ย real_output
์ผ๋ก discriminator์ ์ ํ๋ ๊ณ์ฐ
(8) gradient ๊ณ์ฐ :ย gen_tape
์ย disc_tape
๋ฅผ ํ์ฉํด gradient๋ฅผ ์๋์ผ๋ก ๊ณ์ฐ
(9) ๋ชจ๋ธ ํ์ต : ๊ณ์ฐ๋ gradient๋ฅผ optimizer์ ์ ๋ ฅํด ๊ฐ์ค์น ๊ฐฑ์ (10) ๋ฆฌํด๊ฐ : ์ด๋ฒ ์คํ ์ ๊ณ์ฐ๋ loss์ accuracy๋ฅผ ๋ฆฌํด