DCGAN(DC 생산적 적대 신경망)

Deep Convolutional GAN(Generative Adversarial Nets)

  • GAN 모델은 ‘생성자 모델 G’(Generator)와 ‘판독자 모델 D’(Discriminator)을 만들고
  • D와 G의 경찰과 도둑 게임하는 형식으로 이미지 생성하는 방식이다.
  • 그렇기 때문에 2가지 모델을 생성해야 한다.
  • G모델이 이미지를 생성하고 그 이미지의 판독 결과가 0.5(진짜도 가짜도 아닌)될 때까지 학습시켜 이미지 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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

##### 모델 G(생성자) #####
generator = Sequential()

generator.add(Dense(128*7*7 ,input_dim = 100 , activation = LeakyReLU(0.2)))
generator.add(BatchNormalization())
# 128은 임의의 수를 입력
# 7*7은 나중에 *2 and *2를 해서 28을 맞추게 될 기초 값
# 28*28로 (mnist 이미지가 28*28이기 때문)
# LeakyReLU 뒤의 값은 음수일때의 기울기 값이며 보통 0.1을 입력

#upsampling시 이미지 크기가 2배가 됨
generator.add(Reshape((7,7,128)))# Conv2D가 받을 수있는 구조로 변경
generator.add(UpSampling2D()) # 14,14,128

generator.add(Conv2D(64, kernel_size =5, padding='same'))
generator.add(BatchNormalization())
generator.add(Activation(LeakyReLU(0.2)))
generator.add(UpSampling2D())# 28,28,64

generator.add(Conv2D(1, kernel_size = 5, padding='same', activation='tanh')) #28,28,1

##### 모델 D(판독자) #####
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 #판별자, 학습 가능 여부 = False #가장 중요한 문구!
#####

#G모델의 input_dim이 100이기에 그에 맞춰야함
g_input = Input(shape=(100,))
dis_output = discriminator(generator(g_input))
gan = Model(g_input, dis_output)
gan.compile(loss='binary_crossentropy', optimizer = 'adam')


##### 트레인 함수 생성, train_on_batch로 학습 #####
# gan_train(2001,32,200)을 사용할 예정
def gan_train(epoch, batch_size, saving_interval):

(X_train, _), (_, _) = mnist.load_data() #gan에서는 타겟,vailidation이 필요없어서 X_train만 저장
X_train = X_train.reshape(X_train.shape[0],28,28,1).astype('float32')
# print(X_train.shape[0])
X_train = (X_train - 127.5) / 127.5 #-1 ~ +1로 스케일링

#
real = np.ones((batch_size,1)) #실제 이미지는 모두 참이므로 1로 초기화
fake = np.zeros((batch_size,1)) #32개(batch_size)의 가짜 이미지는 0으로 초기화
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, real)#train_on_batch(실제 이미지, 레이블(==1))


#가짜 이미지를 판별자에 입력하는 부분
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, real) #생성자의 오차, 진짜라고 속여야되서 real을 줌(생성자에서 레이블을 1(ones)으로 설정해서 판별자로 전달)
print(f'epoch: {i}, d_loss:{d_loss:.4f}, g_loss: {g_loss:.4f}')

if i % saving_interval == 0:
#r, c = 5, 5
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(f'./gan_mnist_{i}.png')

gan_train(2001,32,200)

  • 기존의 이미지가 아닌 가짜의 이미지가 생성됩니다.(숫자지만 숫자 아닌듯한 느낌?)

gan_mnist_2000

Author

InhwanCho

Posted on

2022-12-20

Updated on

2022-12-20

Licensed under

Comments