GAN - 코드를 통한 이해(2)

조영재·2021년 9월 1일
0

GAN

목록 보기
4/4

이번 실습에서는 이전과 같은 GAN 모델을 훈련하는데, Dataset으로 MNIST 대신 Celeb_a Dataset을 사용합니다.

Large-scale CelebFaces Attributes (CelebA) Dataset

스크롤을 내려서 아래 다운로드 목록 중, Align&Cropped Images 를 선택하면 CelebA에서 공유한 GDrive가 열립니다. 여기서 Img/img_align_celeba.zip 파일을 다운로드 하여 사용합니다.

이전 실습인 MNIST 생성기 코드를 변형하며 진행하는 실습입니다.

MNIST 생성기

Google Colaboratory

전체 코드는 아래 링크에서 확인 할 수 있습니다.

CelebA Face Image 생성기

Google Colaboratory

과정은 총 3단계로 이루어집니다.

  1. MNIST Dataset을 같은 크기의 CelebA Dataset(28x28x1)으로 변경

  2. Dataset reshape (28x28x1) → (64x64x1) 저화질 -> 고화질

  3. Dataset reshape (64x64x1) → (64x64x3) 흑백 -> 컬러

    실패

1. MNIST Dataset을 같은 크기의 CelebA Dataset으로 변경

cv2 Library 추가

import cv2

데이터셋 준비를 위해 cv2 라이브러리를 추가합니다.

이전 실습의 Dataset을 준비하는 부분은 아래와 같았습니다.

(train_images, train_labels), (_, _) = tf.keras.datasets.mnist.load_data()
train_images = train_images.reshape(train_images.shape[0], 28, 28, 1).astype('float32')
train_images = (train_images - 127.5) / 127.5 # 이미지를 [-1, 1]로 정규화합니다.

이 부분을 아래와 같이 변경합니다.

%cd /content
!gdown --id 1_2glEieyMJt8O8IgtlsQEgCX-ZYbvKMm
!unzip -qq "/content/img_align_celeba.zip"
!rm "/content/img_align_celeba.zip"

gdown 명령을 사용하면 GDrive에서 공유된 파일을 커맨드로 간편하게 다운로드 할 수 있습니다.
상단에 적힌 id는 celeb_a에서 img_align_celeba.zip 파일을 다운로드하고, 제 GDrive에 직접 업로드하여 공유한 파일의 id 값입니다.

celeb_a에서 공유한 zip 파일의 id로 바로 연결하면, 요청이 많아서인지 다운로드가 정상적으로 진행되지 않는 경우가 있습니다. 따라서 직접 공유하여 사용합니다.

다운로드 한 zip 파일을 압축 해제하고, 삭제합니다.

IMG_WIDTH = 28
IMG_HEIGHT = 28

def get_dataset():
  img_path = '/content/img_align_celeba/*.jpg'
  image_list = []
  for idx, filename in enumerate(glob.glob(img_path)):
      if idx == 60000:
        break
      img= cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
      img = cv2.resize(img, (IMG_WIDTH, IMG_HEIGHT), interpolation = cv2.INTER_AREA)
      img = np.array(img).astype('float32')
      img = (img - 127.5)/127.5
      image_list.append(img)

  image_list = np.array(image_list).reshape(len(image_list), IMG_WIDTH, IMG_HEIGHT, 1).astype('float32')
  return image_list

train_images = get_dataset()

/content/img_align_celeba의 경로에 약 20만개의 Celeb_a 이미지가 저장되어 있을 것입니다. 이 중 6만 개의 이미지만 메모리로 불러와 전처리하는 과정을 진행합니다.

img= cv2.imread(filename, cv2.IMREAD_GRAYSCALE)
CelebA Dataset은 3개의 채널을 갖는 Color 이미지입니다. 그러나 MNIST와 똑같은 모델에서의 훈련을 위해 1개의 채널을 갖는 GrayScale 이미지로 변환하여 읽습니다.

img = cv2.resize(img, (IMG_WIDTH, IMG_HEIGHT), interpolation = cv2.INTER_AREA)
CelebA Dataset은 대부분 218x178의 크기를 갖는 이미지입니다. 위와 같은 이유로 28x28 크기의 이미지로 리사이징합니다.

img = np.array(img).astype('float32')
img 를 Numpy로 변형하고 DataType을 float32로 지정합니다.

img = (img - 127.5)/127.5
각 픽셀을 -1 ~ 1 사이의 값으로 조정합니다.

image_list = np.array(image_list).reshape(len(image_list), IMG_WIDTH, IMG_HEIGHT, 1).astype('float32')
img 들을 담고 있는 image_list 또한 numpy 타입으로 바꾸고 학습에 적합한 모양으로 reshape 합니다.

결과 확인

  • 훈련이 진행 될 수록 사람의 형상을 갖춰가지만, 28x28이라는 낮은 해상도 때문에 선명한 이미지는 기대 할 수 없었습니다.
  • 64x64의 더 높은 해상도로 학습을 진행해보겠습니다.

2. Dataset reshape (28x28x1) → (64x64x1) 저화질 -> 고화질

더 선명한 이미지를 위해, 단순히 해상도를 높혀서 훈련을 진행해봅니다.

# WIDTH, HEIGHT 수정!
IMG_WIDTH = 64 
IMG_HEIGHT = 64

데이터의 전처리 과정에서 get_dataset 함수의 상단에 선언한 IMG_WIDTH, IMG_HEIGHT 의 값을 64로 변경합니다.

def make_generator_model():
    model = tf.keras.Sequential()
    model.add(layers.Dense(164, activation='relu', input_shape=(100,)))
    model.add(layers.Dense(328, activation='relu'))
    model.add(layers.Dense(656, activation='relu'))
    model.add(layers.Dense(64*64*1, activation='tanh'))
    model.add(layers.Reshape((64, 64, 1)))

    return model

Dataset의 size를 변경했기 때문에, 신경망의 크기도 변경해줘야합니다.

Generator의 초기 layer size는 Latant Vector의 크기(100)에 IMG_SIZE(64)를 더하여 164로 시작했습니다. 이에 2배씩 증가나가도록 구현했는데, 656의 3번째 Layer와 아웃풋인 64*64 = 4096 Layer 간에 크기차이가 좀 많이 나긴합니다만, 학습은 잘 되었으니 됐습니다.

def make_discriminator_model():
    model = tf.keras.Sequential()
    model.add(layers.Flatten())
    model.add(layers.Dense(656, activation='relu'))
    model.add(layers.Dense(328, activation='relu'))
    model.add(layers.Dense(164, activation='relu'))
    model.add(layers.Dense(1))

    return model

Discriminator 또한 Generator와 동일하게 Layer의 크기를 구성했습니다.

결과 확인


이전 28x28에 비해 더 나은 이미지를 생성하는 것을 눈으로 확인 할 수 있습니다!

3. Dataset reshape (64x64x1) → (64x64x3) 흑백 -> 컬러

이전 과정과 비슷하게 아래의 과정을 진행했습니다.

  1. Dataset 전처리 중 Image load 시 Color 채널로 변경
  2. Generator, Discriminator Layer 확장
  3. Prediction Image Color 채널로 확장

그러나, Dense Layer로 구성된 신경망에서 Layer의 크기가 너무 커져서인지, 1Epochs에 10분가량이 걸리는 상황이 발생했습니다. 300Epochs이면 3000분, 즉 50시간이 필요한데 체크포인트를 활용하면 학습이 불가능 한건 아니지만, Colab에서 GPU를 하루 12시간밖에 못쓰는 실습환경상.. 비효율적인 행동이라 판단하고, DCGAN으로 신경망을 구성해보도록 하겠습니다.

→ 64x64 Color 채널에서의 GAN 모델은 대체로 이 이상의 시간을 사용하는 것 같습니다. GPU에 최적화된 PC를 사용 할 수 없는 지금은, 체크포인트를 이용하며 차근차근 학습을 진행 할 필요가 있겠습니다.

profile
Be Good Developer

0개의 댓글