생성적 적대 신경망(GAN, Generative Adversarial Network)
- 딥러닝의 원리를 활용해 가상의 이미지를 생성하는 알고리즘
- 적대 (Adversarial, 서로 대립 관계에 있는)이란 단어는 GAN 알고리즘의 성격을 잘 표현함
- 진짜 같은 가짜 이미지를 생성하기 위해 GAN 알고리즘 내부에서는 ‘적대적’인 경합을 진행하기 때문임
- 생성자(Generator) : 가짜 이미지를 만들어 내는 공장임
- 초기에는 무작위한 픽셀 값으로 채워진 가짜 이미지로 시작해서 판별자의 판별 결과에 따라 지속적으로 학습하며, 점차 진짜 같은 가짜 이미지를 생성함
- 페이스북의 AI 연구팀이 만들어 발표한 DCGAN(Deep Convolutional GAN)은 생성자 신경망으로 컨볼루션 신경망(CNN)을 이용함
- 먼저 옵티마이저(optimizer)를 사용하는 최적화 과정이나 컴파일하는 과정이 없음
- 일부 매개 변수를 삭제하는 풀링(pooling) 과정이 없고, 패딩(padding) 과정이 포함됨
DCGAN의 제안자들은 생성자 컨볼루션 신경망 학습에 꼭 필요한 옵션들
- 그 중 하나가 배치 정규화(Batch Normalization)라는 과정임
- 배치 정규화 : 입력 데이터의 평균이 0, 분산이 1이 되도록 재배치하는 것인데, 다음 층으로 입력될 값을 일정하게 재배치하는 역할을 함
- 배치 정규화 과정을 통해 층의 개수가 늘어나도 안정적인 학습을 진행할 수 있게 됨
- 케라스는 이를 쉽게 적용할 수 있게끔 BatchNormalization() 함수를 제공함
- 생성자의 활성화 함수로는 ReLU() 함수를 사용하고, 판별자로 넘겨 주기 직전에는 tanh() 함수를 사용하고 있음
- tanh() 함수를 쓰면 출력되는 값이 -1 ~ 1 사이로 맞춰짐
- 따라서 판별자에 입력될 MNIST 손글씨의 픽셀 범위 또한 -1 ~ 1로 맞추면 판별 조건이 모두 갖춰짐
generator.add(Dense (128*7*7, input_dim=100, activation-LeakyReLU(0.2)))
- 임의의 노드 수 : 128 / 100차원의 크기의 랜덤 벡터 입력 / 7*7 -> 이미지 최소 크기
#생성자 모델을 만듭니다.
generator = Sequential()
generator.add(Dense (128*7*7, input_dim=100, activation-LeakyReLU(0.2)))
generator.add(BatchNormalization())
generator.add(Reshape((7, 7, 128)))
generator.add(UpSampling2D())
generator.add(Conv2D(64, kernel_size=5, padding='same'))
generator.add(BatchNormalization())
generator.add(Activation (LeakyReLU(0.2))) # ReLU() 대신 LeakyReLU() 사용
generator.add(UpSampling2D())
generator.add(Conv2D(1, kernel_size=5, padding='same', activation='tanh'))
- 판별자(Generator) : 생성자에서 넘어온 이미지가 가짜인지 진짜인지를 판별해주는 장치
- 판별자는 DCGAN 논문 뿐만 아니라 대부분의 GAN 알고리즘들이 컨볼루션 신경망 구조를 사용함
- 컨볼루션 신경망이란 것이 원래 무언가를 (예를 들면 개와 고양이 사진을) 구별하는 데에 최적화된
알고리즘이기 때문에 그 목적 그대로 사용하면 되는 것 - 패딩 과정, ReLU 활성화 함수, 드롭 아웃(Dropout) 층을 포함한 컨볼루션 신경망 구조를 사용함
- 진짜 이미지(1) 아니면 가짜 이미지(0)
- 둘 중 하나를 결정하는 문제 상황이므로 손실 함수로는 binary_crossentropy, 최적화 함수로는 adam
#판별자 모델을 만듭니다.
discriminator = Sequential()
discriminator.add(Conv2D(64, kernel_size=5, strides 2, input_shape=(28,28,1), padding="same"))
discriminator.add(Activation (LeakyReLU(0.2)))
discriminator.add(Dropout (0.3))
discriminator.add(Conv2D(128, kernel_size=5, strides 2, padding="same"))
discriminator.add(Activation (LeakyReLU(0.2)))
discriminator.add(Dropout (0.3))
discriminator.add(Flatten())
discriminator.add(Dense(1, activation='sigmoid'))
discriminator.compile(loss='binary_crossentropy', optimizer='adam')
discriminator.trainable = False
#생성자와 판별자 모델을 연결시키는 gan 모델을 만듭니다.
ginput = Input (shape=(100,))
dis_output = discriminator (generator (ginput))
gan = Model (ginput, dis_output)
gan.compile(loss='binary_crossentropy', optimizer='adam')
gan.summary()
#신경망을 실행시키는 함수를 만듭니다.
def gan_train(epoch, batch_size, saving_interval):
# MNIST 데이터 불러오기
(X_train, _), (_, _) = mnist.load_data()
X_train X_train.reshape(X_train.shape[0], 28, 28, 1).astype('float32')
X_train = (X_train - 127.5) / 127.5
# 픽셀값은 0에서 255 사이의 값입니다. 이전에 255로
#X_train, shape, Y_train,shape, X_test.shape, Y_test.shape
true = np.ones((batch_size, 1))
fake = np.zeros((batch_size, 1))
for i in range(epoch):
# 실제 데이터를 판별자에 입력하는 부분입니다.
idx = np.random.randint(0, X_train.shape[0], batch_size)
imgs = X_train[idx]
d_loss_real = discriminator.train_on_batch(imgs, true)
#가상 이미지를 판별자에 입력하는 부분입니다.
noise = np.random.normal(0, 1, (batch_size, 100))
gen_imgs = generator.predict(noise)
d_loss_fake = discriminator.train_on_batch(gen_imgs, fake)
#판별자와 생성자의 오차를 계산합니다.
d_loss = 0.5 + np.add(d_loss_real, d_loss_fake)
g_loss = gan.train_on_batch(noise, true)
print('epoch: %d' % i, d_loss: %.4f' % d_loss, g_loss:%.4f' % g_loss)
GAN 모델 만들기
from tensorflow.keras.datasets import mnist
from tensorflow.keras.layers import Input, Dense, Reshape, Flatten, Dropout
from tensorflow.keras.layers import BatchNormalization, Activation, LeakyReLU, UpSampling2D, Conv2D
from tensorflow.keras.models import Sequential, Model
import numpy as np
import matplotlib.pyplot as plt
#생성자 모델을 만듭니다.
generator = Sequential()
generator.add(Dense (128*7*7, input_dim=100, activation-LeakyReLU(0.2)))
generator.add(BatchNormalization())
generator.add(Reshape((7, 7, 128)))
generator.add(UpSampling2D())
generator.add(Conv2D(64, kernel_size=5, padding='same'))
generator.add(BatchNormalization())
generator.add(Activation (LeakyReLU(0.2))) # ReLU() 대신 LeakyReLU() 사용
generator.add(UpSampling2D())
generator.add(Conv2D(1, kernel_size=5, padding='same', activation='tanh'))
#판별자 모델을 만듭니다.
discriminator = Sequential()
discriminator.add(Conv2D(64, kernel_size=5, strides 2, input_shape=(28,28,1), padding="same"))
discriminator.add(Activation (LeakyReLU(0.2)))
discriminator.add(Dropout (0.3))
discriminator.add(Conv2D(128, kernel_size=5, strides 2, padding="same"))
discriminator.add(Activation (LeakyReLU(0.2)))
discriminator.add(Dropout (0.3))
discriminator.add(Flatten())
discriminator.add(Dense(1, activation='sigmoid'))
discriminator.compile(loss='binary_crossentropy', optimizer='adam')
discriminator.trainable = False
#생성자와 판별자 모델을 연결시키는 gan 모델을 만듭니다.
ginput = Input (shape=(100,))
dis_output = discriminator (generator (ginput))
gan = Model (ginput, dis_output)
gan.compile(loss='binary_crossentropy', optimizer='adam')
gan.summary()
#신경망을 실행시키는 함수를 만듭니다.
def gan_train(epoch, batch_size, saving_interval):
# MNIST 데이터 불러오기
(X_train, _), (_, _) = mnist.load_data()
X_train X_train.reshape(X_train.shape[0], 28, 28, 1).astype('float32')
X_train = (X_train - 127.5) / 127.5
# 픽셀값은 0에서 255 사이의 값입니다. 이전에 255로
#X_train, shape, Y_train,shape, X_test.shape, Y_test.shape
true = np.ones((batch_size, 1))
fake = np.zeros((batch_size, 1))
for i in range(epoch):
# 실제 데이터를 판별자에 입력
idx = np.random.randint(0, X_train.shape[0], batch_size)
imgs = X_train[idx]
d_loss_real = discriminator.train_on_batch(imgs, true)
#가상 이미지를 판별자에 입력
noise = np.random.normal(0, 1, (batch_size, 100))
gen_imgs = generator.predict(noise)
d_loss_fake = discriminator.train_on_batch(gen_imgs, fake)
#판별자와 생성자의 오차를 계산합니다.
d_loss = 0.5 + np.add(d_loss_real, d_loss_fake)
g_loss = gan.train_on_batch(noise, true)
print('epoch: %d' % i, d_loss: %.4f' % d_loss, g_loss:%.4f' % g_loss)
if i % saving_interval == 0:
noise = np.random.normal(0, 1, (25, 100))
gen_imgs = generator.predict(noise)
# Rescale images 0-1
gen_imgs = 0.5 gen_imgs + 0.5
fig, axs = plt.subplots(5, 5)
count = 0
for j in range(5):
for k in range(5):
axs[j, k].imshow(gen_imgs[count, :,:, 0], cmap='gray')
axs[j, k].axis('off')
count += 1
fig.savefig("gan_images/gan_mnist_%d.png" % i)
# 4,000번 반복되고(+1을 하는 것에 주의), 배치 크기는 32,200번마다 결과가 저장됨
gan_train (4001, 32, 200)
'빅데이터 분석가 양성과정 > Python - 딥러닝' 카테고리의 다른 글
이미지 증강 (0) | 2024.07.18 |
---|---|
오토인코더 (0) | 2024.07.18 |
순환신경망_재정리 및 추가 (1) | 2024.07.18 |
자연어 처리_재정리 (2) | 2024.07.18 |
DNN을 이용한 영상 분류_재정리 (0) | 2024.07.18 |