일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 풀링층
- 합성곱 신경망
- 코딩테스트
- cnn
- 성능 최적화
- 카운트 벡터
- 코랩
- NLTK
- 클러스터링
- 출력층
- 입력층
- KONLPY
- 합성곱층
- 망각 게이트
- 프로그래머스
- RNN
- 시계열 분석
- 임베딩
- 생성모델
- 과적합
- COLAB
- 딥러닝
- 원-핫 인코딩
- 텍스트 마이닝
- 이미지 분류
- 완전연결층
- 양방향 RNN
- 자연어 전처리
- 순환 신경망
- 전이학습
Archives
- Today
- Total
Colab으로 하루에 하나씩 딥러닝
생성모델_3.GAN 본문
728x90
적대적 생성 신경망(Generative Adversarial Network)
- 판별자를 먼저 학습시킨 후 생성자를 학습시키는 과정을 반복하여 서로 적대적인 경쟁자로 인식하여 모두 발전함
- 생성자는 진짜 이미지에 완벽하게 가까운 이미지를 만들고, 판별자는 실제와 구분할 수 없음
- 판별자와 생성자의 파라미터를 번갈아 가며 업데이트하여 학습시킴
GAN 구성요소
1. 생성자(Generator)
- 판별자가 구별할 수 없을 만큼 진짜와 같은 모조 이미지를 노이즈 데이터를 사용하여 만듦
- 경찰과 위조지폐범 사이에서 '위조지폐범' 역할
2. 판별자(Discriminator)
- 주어진 입력 이미지가 진짜 이미지인지 가짜 이미지인지 구별
- 경찰과 위조지폐범 사이에서 '경찰' 역할
GAN 실습
### 라이브러리 호출
import tensorflow as tf
import matplotlib.pyplot as plt
import numpy as np
import os
from tensorflow.keras.layers import Reshape,Dense,Dropout,LeakyReLU,Conv2DTranspose,Conv2D,Flatten,BatchNormalization
from tensorflow.keras import Model, Sequential
from tensorflow.keras.datasets import mnist
import time
from IPython import display
### MNIST 데이터셋 내려받기 및 전처리
(x_train, y_train), (x_test, y_test) = mnist.load_data() # load_data()를 사용하여 MNIST 데이터셋을 내려받음
train_images = x_train.reshape(x_train.shape[0],28,28,1).astype('float32')
train_images = (train_images -127.5) / 127.5
train_dataset = tf.data.Dataset.from_tensor_slices(train_images).shuffle(60000).batch(256) # 벡터 값들을 섞고, 이미지 256개의 배치 단위로 데이터를 메모리로 불러옴
### 생성자 네트워크 생성
def create_generator():
generator=Sequential()
generator.add(Dense(7*7*256, input_dim=100)) # 설명 1
generator.add(LeakyReLU(0.2))
generator.add(Reshape((7, 7, 256)))
generator.add(Conv2DTranspose(128, (5, 5), strides=(1, 1), padding='same', use_bias=True)) # 설명 2
generator.add(BatchNormalization()) # 이미지에서 노이즈를 줄이는 정규화 목적으로 사용
generator.add(LeakyReLU(0.2)) # 활성화 함수로 리키렐루 사용
generator.add(Dropout(0.3))
generator.add(Conv2DTranspose(64, (5, 5), strides=(2, 2), padding='same', use_bias=True))
generator.add(BatchNormalization())
generator.add(LeakyReLU(0.2))
generator.add(Conv2DTranspose(1, (5, 5), strides=(2, 2), padding='same', use_bias=True, activation='tanh'))
return generator
g=create_generator()
g.summary()
상세 설명
- 설명 1
- 7*7*256: 출력 뉴런(노드)의 수
- input_dim: 입력 뉴런(노드)의 수
- 설명 2(Conv2DTranspose는 합성곱 연삭의 역인 '전치 합성곱')
- 128: 서로 다른 종류의 필터를 몇 개 활용할지 나타내는 것으로, 출력 모양의 깊이를 결정
- (5,5): 커널 크기를 의미
- strides=(1,1): 연산을 수행할 때 윈도우가 한 번에 얼마나 움직일지 의미
- padding='same': 입력과 출력 이미지의 크기를 동일하게 맞춰줌
- use_bias=True: 바이어스 벡터 사용
### 판별자 네트워크 생성
def create_discriminator():
discriminator=Sequential()
discriminator.add(Conv2D(64, (5, 5), strides=(2, 2), padding='same', input_shape=[28, 28, 1])) # Conv2DTranspose의 역을 계산하려고 Conv2D 사용
discriminator.add(LeakyReLU()) # 활성화 함수는 생성자와 같은 리키렐루 사용
discriminator.add(Dropout(0.3)) # 훈련 데이터셋의 30%를 제외하고 훈련
discriminator.add(Conv2D(128, (5, 5), strides=(2, 2), padding='same'))
discriminator.add(LeakyReLU())
discriminator.add(Dropout(0.3))
discriminator.add(Flatten())
discriminator.add(Dense(1))
return discriminator
d =create_discriminator()
d.summary()
### 손실 함수 정의
loss_function = tf.keras.losses.BinaryCrossentropy(from_logits=True) # 설명 1
def D_loss(real_output, fake_output): # 판별자에 대한 오차(loss) 정의
real_loss = loss_function(tf.ones_like(real_output), real_output) # 설명 2
fake_loss = loss_function(tf.zeros_like(fake_output), fake_output) # 설명 3
final_loss = real_loss + fake_loss
return final_loss
def G_loss(fake_output): # 생성자에 대한 오차(loss) 정의
return loss_function(tf.ones_like(fake_output), fake_output)
상세 설명
- 설명 1
- 모델이 확률 값을 출력하므로 BinaryCrossentropy를 사용
- True로 설정되면 logits를 직접 사용
- 설명 2
- 모든 원소값이 1인 텐서를 생성
- 설명 3
- 모든 원소 값이 0인 텐서를 생성
### 옵티마이저 정의
G_optimizer = tf.keras.optimizers.Adam()
D_optimizer = tf.keras.optimizers.Adam()
### 파라미터의 초깃값 설정
noise_dim = 100
num_of_generated_examples = 16
BATCH_SIZE = 1
seed = tf.random.normal([num_of_generated_examples, noise_dim]) # 정규 분포의 난수를 생성한 수 seed에 저장
### 모델 훈련을 위한 파이프라인 정의
generator = create_generator()
discriminator = create_discriminator()
@tf.function
def train_step(images):
noise = tf.random.normal([BATCH_SIZE, noise_dim])
with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape: # 설명 1
generated_images = generator(noise, training=True)
real_output = discriminator(images, training=True) # 실제 이미지를 사용하여 판별자 훈련 루 판별 값 반환
fake_output = discriminator(generated_images, training=True) # 모조 이미지를 사용하여 판별자 훈련 후 판별 값 반환
gen_loss = G_loss(fake_output) # 생성자에 대한 오차 계산
disc_loss = D_loss(real_output, fake_output) # 판별자에 대한 오차 계산
gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables) # 생성자의 오차 계산
gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.trainable_variables) # 판별자의 오차 계산
G_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables)) # 생성자의 기울기 계산
D_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables)) # 판별자의 기울기 계산
상세 설명
- 설명 1
- GradientTape를 사용해서 주어진 입력에 대한 연산의 미분 값을 자동으로 계산
### 생성된 이미지 출력 함수
def generate_images(model, epoch, test_input):
predictions = model(test_input, training=False)
fig = plt.figure(figsize=(4,4))
for i in range(predictions.shape[0]):
plt.subplot(4, 4, i+1)
plt.imshow(predictions[i, :, :, 0] * 127.5 + 127.5, cmap='rainbow')
### 모델 훈련 함수
def train_GAN(dataset, epochs):
for epoch in range(epochs):
start = time.time()
for image_batch in dataset:
train_step(image_batch)
if epoch % 10 == 0:
generate_images(generator,epoch + 1,seed)
print ('에포크 {} 은/는 {} 초'.format(epoch + 1, time.time()-start))
generate_images(generator,epochs,seed)
### 모델 훈련 및 생성 이미지 출력
train_GAN(train_dataset, 30)
참고: 서지영, 『딥러닝 텐서플로 교과서』, 길벗(2022)
'딥러닝_개념' 카테고리의 다른 글
NLP_허깅페이스 트랜스포머 (0) | 2023.02.08 |
---|---|
생성모델_2.변형 오토인코더 (0) | 2023.02.06 |
생성모델_1.오토인코더 (0) | 2023.02.03 |
클러스터링_3.자기 조직화 지도 (0) | 2023.01.31 |
클러스터링_2.가우시안 혼합 모델 (0) | 2023.01.30 |