Notice
Recent Posts
Recent Comments
NeuroWhAI의 잡블로그
[Python] Keras로 DCGAN 구현하고 MNIST 이미지 생성하기 본문
사실 정석의 DCGAN과는 차이(드롭아웃을 썼다거나)가 있지만 신경망 구성이야 쉽게 바꿀 수 있으니 틀만 보신다는 느낌으로 봐주세요.
참고로 제가 처음부터 짠 코드는 아니고 오픈소스를 좀 수정했습니다.
import numpy as np
from keras.models import *
from keras.layers import *
from keras.optimizers import *
from keras.datasets import mnist
import keras.backend as K
import matplotlib.pyplot as plt
K.set_image_data_format('channels_last')
class Gan:
def __init__(self, img_data):
img_size = img_data.shape[1]
channel = img_data.shape[3] if len(img_data.shape) >= 4 else 1
self.img_data = img_data
self.input_shape = (img_size, img_size, channel)
self.img_rows = img_size
self.img_cols = img_size
self.channel = channel
self.noise_size = 100
# Create D and G.
self.create_d()
self.create_g()
# Build model to train D.
optimizer = Adam(lr=0.0008)
self.D.compile(loss='binary_crossentropy', optimizer=optimizer)
# Build model to train G.
optimizer = Adam(lr=0.0004)
self.D.trainable = False
self.AM = Sequential()
self.AM.add(self.G)
self.AM.add(self.D)
self.AM.compile(loss='binary_crossentropy', optimizer=optimizer)
def create_d(self):
self.D = Sequential()
depth = 64
dropout = 0.4
self.D.add(Conv2D(depth*1, 5, strides=2, input_shape=self.input_shape,
padding='same'))
self.D.add(LeakyReLU(alpha=0.2))
self.D.add(Dropout(dropout))
self.D.add(Conv2D(depth*2, 5, strides=2, padding='same'))
self.D.add(LeakyReLU(alpha=0.2))
self.D.add(Dropout(dropout))
self.D.add(Conv2D(depth*4, 5, strides=2, padding='same'))
self.D.add(LeakyReLU(alpha=0.2))
self.D.add(Dropout(dropout))
self.D.add(Conv2D(depth*8, 5, strides=1, padding='same'))
self.D.add(LeakyReLU(alpha=0.2))
self.D.add(Dropout(dropout))
self.D.add(Flatten())
self.D.add(Dense(1))
self.D.add(Activation('sigmoid'))
self.D.summary()
return self.D
def create_g(self):
self.G = Sequential()
dropout = 0.4
depth = 64+64+64+64
dim = 7
self.G.add(Dense(dim*dim*depth, input_dim=self.noise_size))
self.G.add(BatchNormalization(momentum=0.9))
self.G.add(Activation('relu'))
self.G.add(Reshape((dim, dim, depth)))
self.G.add(Dropout(dropout))
self.G.add(UpSampling2D())
self.G.add(Conv2DTranspose(int(depth/2), 5, padding='same'))
self.G.add(BatchNormalization(momentum=0.9))
self.G.add(Activation('relu'))
self.G.add(UpSampling2D())
self.G.add(Conv2DTranspose(int(depth/4), 5, padding='same'))
self.G.add(BatchNormalization(momentum=0.9))
self.G.add(Activation('relu'))
self.G.add(Conv2DTranspose(int(depth/8), 5, padding='same'))
self.G.add(BatchNormalization(momentum=0.9))
self.G.add(Activation('relu'))
self.G.add(Conv2DTranspose(1, 5, padding='same'))
self.G.add(Activation('sigmoid'))
self.G.summary()
return self.G
def train(self, batch_size=100):
# Pick image data randomly.
images_train = self.img_data[np.random.randint(0, self.img_data.shape[0], size=batch_size), :, :, :]
# Generate images from noise.
noise = np.random.uniform(-1.0, 1.0, size=[batch_size, self.noise_size])
images_fake = self.G.predict(noise)
# Train D.
x = np.concatenate((images_train, images_fake))
y = np.ones([2*batch_size, 1])
y[batch_size:, :] = 0
self.D.trainable = True
d_loss = self.D.train_on_batch(x, y)
# Train G.
y = np.ones([batch_size, 1])
noise = np.random.uniform(-1.0, 1.0, size=[batch_size, self.noise_size])
self.D.trainable = False
a_loss = self.AM.train_on_batch(noise, y)
return d_loss, a_loss, images_fake
# Load MNIST dataset.
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.astype('float32') / 255.0
x_train = x_train.reshape((x_train.shape[0],) + (28, 28, 1))
print(x_train.shape)
# Init network
gan = Gan(x_train)
# Some parameters.
epochs = 30
sample_size = 10
batch_size = 100
train_per_epoch = x_train.shape[0] // batch_size
for epoch in range(0, epochs):
print("Epoch:", epoch + 1)
total_d_loss = 0.0
total_a_loss = 0.0
for batch in range(0, train_per_epoch):
d_loss, a_loss, imgs = gan.train(batch_size)
total_d_loss += d_loss
total_a_loss += a_loss
total_d_loss /= train_per_epoch
total_a_loss /= train_per_epoch
print("D Loss: {}, AM Loss: {}".format(total_d_loss, total_a_loss))
# Show generated images.
fig, ax = plt.subplots(1, sample_size, figsize=(sample_size, 1))
for i in range(0, sample_size):
ax[i].set_axis_off()
ax[i].imshow(imgs[i].reshape((28, 28)));
plt.show()
plt.close(fig);
결과:
뭐 그럭저럭 괜찮네요.
사실 원래 목적은 포켓몬 이미지를 생성하는 거였는데 계속 안돼서 MNIST로 회귀했습니다 ㅠㅠ
GAN이 딥러닝 모델? 중에서 가장 재미있는 것 같습니다 ㅎㅎ
두번째로는 Seq2Seq가 재밌는 것 같고요.
LAPGAN이란 것도 있다는데 고해상도 이미지 생성을 위한 GAN이라고 합니다.
주말에 공부해서 돌려볼 수 있으면 좋겠네요 ㅎ.. (근데 이해는 해도 컴퓨터 성능이 안좋은데 고화질까지 가면... ㅠ)
'개발 및 공부 > 라이브러리&프레임워크' 카테고리의 다른 글
[Rust] 구글 애널리틱스에서 페이지별 조회수를 얻는 HTTP API 만들기 성공! (0) | 2018.11.10 |
---|---|
[Python] Keras DCGAN으로 포켓몬 이미지 생성 (+소스코드) (0) | 2018.10.31 |
[Rust] Rocket 사용해서 20줄로 정적 파일 서버 만들기 (0) | 2018.10.04 |
[Rust] Rocket으로 웹 서버 만들어서 Heroku에 올리기 (0) | 2018.10.03 |
[Python] Keras로 MNIST 학습하고 직접 그린 이미지 추측시켜보기 (0) | 2018.07.30 |
Comments