GAN :: 컴퓨터 비전 - mindscale
Skip to content

GAN

임포트

import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras.layers import Input, Dense, Dropout, LeakyReLU
from tensorflow.keras.optimizers import Adam
from tensorflow.keras import initializers
import tqdm.notebook

설정

np.random.seed(10)
random_dim = 32

데이터

(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train = x_train[y_train < 2]
x_train = (x_train.astype(np.float32) - 127.5)/127.5
x_train = x_train.reshape(-1, 784)

생성자

generator = tf.keras.models.Sequential([
    Dense(256, input_dim=random_dim, 
          kernel_initializer=initializers.RandomNormal(stddev=0.02)),
    LeakyReLU(0.2),
    Dense(784, activation='tanh')
])

generator.compile(loss='binary_crossentropy', 
                  optimizer=Adam(learning_rate=0.0002, beta_1=0.5))

구분자

discriminator = tf.keras.models.Sequential([
    Dense(1024, input_dim=784,
          kernel_initializer=initializers.RandomNormal(stddev=0.02)),
    LeakyReLU(0.2),
    Dropout(0.3),
    Dense(1, activation='sigmoid'),
])
discriminator.compile(loss='binary_crossentropy', 
                      optimizer=Adam(learning_rate=0.0002, beta_1=0.5))

GAN

discriminator.trainable = False
gan_input = Input(shape=(random_dim,))
x = generator(gan_input)
gan_output = discriminator(x)
gan = tf.keras.models.Model(inputs=gan_input, outputs=gan_output)
gan.compile(loss='binary_crossentropy', 
            optimizer=Adam(learning_rate=0.0002, beta_1=0.5))

예시 이미지 생성 함수

def plot_generated_images(epoch, generator, dim=(5, 5)):
    examples = dim[0] * dim[1]
    noise = np.random.normal(0, 1, size=[examples, random_dim])
    generated_images = generator.predict(noise, verbose=0)
    generated_images = generated_images.reshape(examples, 28, 28)

    plt.figure(figsize=dim)
    for i in range(generated_images.shape[0]):
        plt.subplot(dim[0], dim[1], i+1)
        plt.imshow(generated_images[i], interpolation='nearest', cmap='gray_r')
        plt.axis('off')
    plt.tight_layout()
    plt.savefig(f'gan{epoch:02d}.png')

훈련

epochs = 3
batch_size = 128
batch_count = x_train.shape[0] // batch_size

progress = tqdm.notebook.tqdm(total=epochs * batch_count)
for e in range(epochs):
    for _ in range(batch_count):
        # 실제 이미지
        idx = np.random.randint(0, x_train.shape[0], size=batch_size)
        image_batch = x_train[idx]

        # 가짜 이미지 생성
        noise = np.random.normal(0, 1, size=[batch_size, random_dim])  # 노이즈
        generated_images = generator.predict(noise, verbose=0)  

        # 구분자 훈련 데이터
        X = np.concatenate([image_batch, generated_images])  
        y_dis = np.zeros(2*batch_size)
        y_dis[:batch_size] = 0.9  # 실제 = 0.9(label smoothing), 가짜 = 0

        # 구분자 훈련
        discriminator.trainable = True
        discriminator.fit(X, y_dis, batch_size=batch_size, verbose=0)

        # 생성자 훈련 데이터
        noise = np.random.normal(0, 1, size=[batch_size, random_dim])
        y_gen = np.ones(batch_size)

        # 생성자 훈련
        discriminator.trainable = False
        gan.fit(noise, y_gen, batch_size=batch_size, verbose=0)
        progress.update(1)

    plot_generated_images(e, generator)
progress.close()
  0%|          | 0/294 [00:00<?, ?it/s]