close_btn
조회 수 977 추천 수 0 댓글 0
?

단축키

Prev이전 문서

Next다음 문서

+ - Up Down Comment Print Files
?

단축키

Prev이전 문서

Next다음 문서

+ - Up Down Comment Print Files
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import keras
from keras.layers import Dense, Dropout, Input
from keras.models import Model,Sequential
from keras.datasets import mnist
from tqdm import tqdm
from keras.layers.advanced_activations import LeakyReLU
from keras.optimizers import Adam
 
1. 데이터 로드
def load_data():
    (x_train, y_train), (x_test, y_test) = mnist.load_data()
    x_train = (x_train.astype(np.float32) - 127.5)/127.5
    
    # convert shape of x_train from (60000, 28, 28) to (60000, 784) 
    # 784 columns per row
    x_train = x_train.reshape(60000784)
    return (x_train, y_train, x_test, y_test)
 
 
2. 모델 평가 함수
#학습하기 위해서는 모델을 평가할 수 있어야 한다. 모델의 평가 지표가 좋아지는 방향으로 
#매개 변수를 업데이트할 것이기 때문이다.
#구분자의 출력값은 이미지가 진짜일 확률이고, 이 확률이 얼마나 정답과 가까운지를 측정하기 위해 
#바이너리 크로스 엔트로피(Binary cross entropy) 손실 함수(loss function)를 사용한다. 
#이 함수는 구분자가 출력한 확률값이 정답에 가까우면 낮아지고 정답에서 멀면 높아진다. 
#이 손실 함수의 값을 낮추는 것이 모델 학습의 목표가 된다.
 
def adam_optimizer():
    return Adam(lr=0.0002, beta_1=0.5)
#이제 생성자와 구분자의 매개 변수를 업데이트하는 최적화 함수가 필요하다. 
#최적화 기법에는 여러 종류가 있지만 여기서는 가장 널리 쓰이는 기법인 아담(Adam)을 사용했다. 
#아담은 매개 변수마다 업데이트 속도를 최적으로 조절하는 효율적인 최적화 기법이다.
 
3. GAN의 생성자(Generator)
#생성자는 랜덤 벡터 ‘z’를 입력으로 받아 가짜 이미지를 출력하는 함수다. 
#여기서 ‘z’는 단순하게 균등 분포(Uniform Distribution)나 정규 분포(Normal Distribution)에서 무작위로 추출된 값이다. 
#생성자는 이렇게 단순한 분포를 사람 얼굴 이미지와 같은 복잡한 분포로 매핑(Mapping)하는 함수라고 볼 수 있다. 
#생성자 모델에 충분한 수의 매개 변수가 있다면 어떤 복잡한 분포도 근사할 수 있다는 것이 알려져 있다.
 
def create_generator():
    generator=Sequential()
    generator.add(Dense(units=256,input_dim=100))
    generator.add(LeakyReLU(0.2))
    
    generator.add(Dense(units=512))
    generator.add(LeakyReLU(0.2))
    
    generator.add(Dense(units=1024))
    generator.add(LeakyReLU(0.2))
    
    generator.add(Dense(units=784, activation='tanh'))
    
    generator.compile(loss='binary_crossentropy', optimizer=adam_optimizer())
    return generator

#왜 noise vector크기를 100으로 하는건가? ㅜㅜ
 
#‘z’ 벡터가 존재하는 공간을 잠재 공간(Latent Space)
#여기서는 잠재 공간의 크기를 임의로 100차원으로 뒀다.
#재 공간의 크기에는 제한이 없으나 나타내려고 하는 대상의 정보를 충분히 담을 수 있을 만큼은 커야 한다. 
#GAN은 우리가 이해할 수는 없는 방식이지만 ‘z’ 벡터의 값을 이미지의 속성에 매핑시키기 때문이다.
#(출처 : https://dreamgonfly.github.io/2018/03/17/gan-explained.html)
 
#생성자는 랜덤 벡터 ‘z’를 입력으로 받아 가짜 이미지를 출력하는 함수다. 
#여기서 ‘z’는 단순하게 균등 분포(Uniform Distribution)나 정규 분포(Normal Distribution)에서 무작위로 추출된 값이다. 
#생성자는 이렇게 단순한 분포를 사람 얼굴 이미지와 같은 복잡한 분포로 매핑(Mapping)하는 함수라고 볼 수 있다. 
#생성자 모델에 충분한 수의 매개 변수가 있다면 어떤 복잡한 분포도 근사할 수 있다는 것이 알려져 있다.
 
#이 구현에서는 4개의 선형 레이어(Linear Layer, Fully Connected Layer, Linear Transformation)를 쌓아서 생성자를 만들었다. 
#선형 레이어는 속해있는 모든 뉴런이 이전 레이어의 모든 뉴런과 연결되는 가장 단순한 구조의 레이어다. 
#이 모델에서는 100차원의 랜덤 벡터를 받아 이를 256개의 뉴런을 가진 레이어로 보내고,
# 다시 레이어의 크기를 512, 1024로 점점 증가시켰다. 
#마지막에는 출력을 MNIST 이미지의 크기로 맞추기 위해 레이어 크기를 28x28로 줄였다.
#각 레이어마다 활성 함수로는 LeakyReLU를 이용했다.
#생성자의 마지막 레이어에서는 출력값을 픽셀값의 범위인 -1과 1 사이로 만들어주기 위해 Tanh를 사용했다.
 
def create_discriminator():
    discriminator=Sequential()
    discriminator.add(Dense(units=1024,input_dim=784))
    discriminator.add(LeakyReLU(0.2))
    discriminator.add(Dropout(0.3))
    
    discriminator.add(Dense(units=512))
    discriminator.add(LeakyReLU(0.2))
    discriminator.add(Dropout(0.3))
       
    discriminator.add(Dense(units=256))
    discriminator.add(LeakyReLU(0.2))
    
    discriminator.add(Dense(units=1, activation='sigmoid'))
    
    discriminator.compile(loss='binary_crossentropy', optimizer=adam_optimizer())
    return discriminator
#구분자는 이미지를 입력으로 받고 그 이미지가 진짜일 확률을 0과 1 사이의 숫자 하나로 출력하는 함수다.
#구분자의 구현은 생성자와 마찬가지로 4개의 선형 레이어를 쌓았으며 레이어마다 활성 함수로 LeakyReLU를 넣어줬다. 
#입력값으로 이미지 크기인 28x28개의 변수를 받은 뒤 레이어의 크기가 
#28x28에서 1024로, 512로, 256으로 점차 줄어들다. 
#마지막에는 확률값을 나타내는 숫자 하나를 출력한다.
#레이어마다 들어간 드롭아웃(Dropout)은 학습 시에 무작위로 절반의 뉴런을 사용하지 않도록 한다. 
#이를 통해 모델이 과적합(Overfitting, 오버피팅)되는 것을 방지할 수 있고, 
#또한 구분자가 생성자보다 지나치게 빨리 학습되는 것도 막을 수 있다.
#구분자의 마지막 레이어에서는 출력값을 0과 1 사이로 만들기 위해 활성 함수로 Sigmoid를 넣었다.
 
def create_gan(discriminator, generator):
    discriminator.trainable=False
    gan_input = Input(shape=(100,))
    x = generator(gan_input)
    gan_output= discriminator(x)
    gan= Model(inputs=gan_input, outputs=gan_output)
    gan.compile(loss='binary_crossentropy', optimizer='adam')
    return gan
#학습하기 위해서는 모델을 평가할 수 있어야 한다. 
#모델의 평가 지표가 좋아지는 방향으로 매개 변수를 업데이트할 것이기 때문이다.
#구분자의 출력값은 이미지가 진짜일 확률이고, 이 확률이 얼마나 정답과 가까운지를 측정하기 위해 
#바이너리 크로스 엔트로피(Binary cross entropy) 손실 함수(loss function)를 사용한다. 
#이 함수는 구분자가 출력한 확률값이 정답에 가까우면 낮아지고 정답에서 멀면 높아진다. 
#이 손실 함수의 값을 낮추는 것이 모델 학습의 목표가 된다.
 
def plot_generated_images(epoch, generator, examples=100, dim=(10,10), figsize=(10,10)):
    noise= np.random.normal(loc=0, scale=1, size=[examples, 100])
    generated_images = generator.predict(noise)
    generated_images = generated_images.reshape(100,28,28)
    plt.figure(figsize=figsize)
    for i in range(generated_images.shape[0]):
        plt.subplot(dim[0], dim[1], i+1)
        plt.imshow(generated_images[i], interpolation='nearest')
        plt.axis('off')
    plt.tight_layout()
    plt.savefig('gan_generated_image %d.png' %epoch)
#! pip install pydot
#! pip install pydot>=1.2.4
#! pip install graphviz
import pydot  
from IPython.display import SVG
from keras.utils.vis_utils import model_to_dot  
from keras.utils.vis_utils import plot_model  
def training(epochs=1, batch_size=128):
    
    #Loading the data
    (X_train, y_train, X_test, y_test) = load_data()
    batch_count = X_train.shape[0/ batch_size
    
    # Creating GAN
    generator = create_generator()
    discriminator = create_discriminator()
    gan = create_gan(discriminator, generator)
    
    ## structure of model
    from keras.utils import plot_model
    plot_model(generator, show_shapes=True, to_file='generator.png')
    
    plot_model(discriminator, show_shapes=True, to_file='discriminator.png')
    
    plot_model(gan, show_shapes=True, to_file='gan.png')
    
    for e in range(1,epochs+1):
        print("Epoch %d" %e)
        for _ in tqdm(range(batch_size)):
        # Generate random noise as an input to initialize the generator
            noise= np.random.normal(0,1, [batch_size, 100])
            
            # Generate fake MNIST images from noised input
            generated_images = generator.predict(noise)
            
            # Get a random set of  real images
            image_batch =X_train[np.random.randint(low=0,high=X_train.shape[0],size=batch_size)]
            
            # Construct different batches of real and fake data 
            X= np.concatenate([image_batch, generated_images])
            
            # Labels for generated and real data
            y_dis=np.zeros(2*batch_size)
            y_dis[:batch_size]=0.9
            
            # Pretrain discriminator on  fake and real data before starting the gan. 
            discriminator.trainable=True
            discriminator.train_on_batch(X, y_dis)
            
            # Tricking the noised input of the Generator as real data
            y_gen = np.ones(batch_size)
            
            # During the training of gan, the weights of discriminator should be fixed. 
            # We can enforce that by setting the trainable flag
            discriminator.trainable=False
            
            # Training  the GAN by alternating the training of the Discriminator and training the chained GAN model with Discriminator's weights freezed.
            gan.train_on_batch(noise, y_gen)
            
        if e == 1 or e % 20 == 0:
             plot_generated_images(e, generator)
training(400,128)
 
#구분자는 진짜 이미지를 입력하면 1에 가까운 확률값을 출력하고, 
#가짜 데이터를 입력하면 0에 가까운 확률값을 출력해야 한다. 
#따라서 구분자의 손실 함수는 두 가지의 합으로 이루어진다. 
#진짜 이미지를 입력했을 때의 출력값과 1과의 차이, 그리고 가짜 이미지를 입력했을 때의 출력값과 0과의 차이, 
#두 경우의 합이 구분자의 손실 함수다. 이 손실 함수의 값을 최소화하는 방향으로 구분자의 매개 변수가 업데이트된다.
 
#생성자의 목적은 구분자를 속이는 것이다. 다시 말해 생성자가 만들어낸 가짜 이미지를 구분자에 넣었을 때 출력값이 1에 가깝게 나오도록 해야 한다. 
#이 값이 1에서 떨어진 정도가 생성자의 손실 함수가 되고, 이를 최소화 시키도록 생성자를 학습시키게 된다.
 
#참조 사이트
 
#코드 관련 해설 및 이해 (출처: https://dreamgonfly.github.io/2018/03/17/gan-explained.html)
#GAN 이해 (출처: https://skymind.ai/kr/wiki/generative-adversarial-network-gan) gan_mnist keras 구현 (출처: https://m.blog.naver.com/PostView.nhn?blogId=qbxlvnf11&logNo=221524732924&categoryNo=87&proxyReferer=https%3A%2F%2Fwww.google.com%2F)
 
cs

List of Articles
번호 제목 글쓴이 날짜 조회 수
공지 우수 코드 게시판 이용 관련 공지사항 DataMarket 2014.05.21 43164
187 투빅스 11기&12기 9주차 CNN심화(1) - 12기 김주호 file 김주호 2019.09.25 1225
186 투빅스 11기&12기 9주차 CNN심화(2) - 12기 김태한 file 12기김태한 2019.09.25 878
185 투빅스 11기&12기 8주차 CNN심화(3) - 12기 배유나 file 배유나 2019.09.24 981
» 투빅스 11기&12기 8주차 CNN심화(4) - 12기 배유나 file 배유나 2019.09.24 977
183 투빅스 11기&12기 8주차 CNN - 12기 박재민 jaemin0095 2019.09.23 912
182 투빅스 11기&12기 8주차 NLP기초 - 12기 박진혁 file 박진혁 2019.09.21 947
181 투빅스 11기&12기 8주차 NLP - 12기 김주호 file 김주호 2019.09.20 857
180 투빅스 11기&12기 7주차 알고리즘(1) - 12기 김탁영 file 2019.09.19 888
179 투빅스 11기&12기 7주차 알고리즘(2) - 김효은 file 김효은 2019.09.17 836
178 투빅스 11기&12기 7주차 프레임워크(PyTorch) - 12기 신윤종 file yj 2019.09.16 889
177 투빅스 11기&12기 6주차 크롤링 - 이유진 yooj_lee 2019.09.04 874
176 투빅스 11기&12기 6주차 크롤링 - 12기 신윤종 file yj 2019.08.31 811
175 투빅스 11기&12기 6주차 크롤링 - 12기 김주호 file 김주호 2019.08.31 861
174 투빅스 11기&12기 5주차 알고리즘 - 12기 김탁영 2019.08.29 856
173 투빅스 11기&12기 5주차 SVM - 12기 이홍정 올타임넘버원메시 2019.08.27 896
172 투빅스 11기&12기 5주차 PCA - 12기 김태한 file 12기김태한 2019.08.27 927
171 투빅스 11기&12기 4주차 Ensemble - 12기 배유나 배유나 2019.08.26 892
170 투빅스 11기&12기 5주차 Class - 12기 이세윤 세윤 2019.08.26 825
169 투빅스 11기&12기 3주차 Naive bayes - 12기 김태한 12기김태한 2019.08.19 849
168 투빅스 11기&12기 4주차 Clustering - 12기 신윤종 file yj 2019.08.17 867
Board Pagination ‹ Prev 1 2 3 4 5 6 7 8 9 ... 10 Next ›
/ 10

나눔글꼴 설치 안내


이 PC에는 나눔글꼴이 설치되어 있지 않습니다.

이 사이트를 나눔글꼴로 보기 위해서는
나눔글꼴을 설치해야 합니다.

설치 취소

Designed by sketchbooks.co.kr / sketchbook5 board skin

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5

Sketchbook5, 스케치북5