Kursus
Dalam tutorial ini, Anda akan mempelajari apa itu Generative Adversarial Networks (GAN) tanpa masuk ke detail matematika. Setelah itu, Anda akan belajar cara membuat kode GAN sederhana yang dapat membuat digit!
Analogi
Cara termudah untuk memahami apa itu GAN adalah melalui analogi sederhana:
Misalkan ada sebuah toko yang membeli jenis anggur tertentu dari pelanggan untuk kemudian dijual kembali.

Namun, ada pelanggan berniat jahat yang menjual anggur palsu untuk mendapatkan uang. Dalam kasus ini, pemilik toko harus bisa membedakan antara anggur palsu dan asli.

Anda dapat membayangkan bahwa pada awalnya, pemalsu mungkin membuat banyak kesalahan saat mencoba menjual anggur palsu dan pemilik toko akan mudah mengidentifikasi bahwa anggur tersebut tidak asli. Karena kegagalan ini, si pemalsu akan terus mencoba berbagai teknik untuk meniru anggur asli dan beberapa akhirnya akan berhasil. Kini setelah si pemalsu mengetahui bahwa teknik tertentu lolos dari pemeriksaan pemilik toko, ia dapat mulai lebih meningkatkan anggur palsu berdasarkan teknik tersebut.
Pada saat yang sama, pemilik toko mungkin akan mendapat masukan dari pemilik toko lain atau pakar anggur bahwa beberapa anggur yang ia miliki bukan asli. Ini berarti pemilik toko harus meningkatkan cara ia menentukan apakah anggur itu palsu atau asli. Tujuan si pemalsu adalah membuat anggur yang tidak dapat dibedakan dari yang asli, dan tujuan pemilik toko adalah secara akurat mengetahui apakah suatu anggur asli atau tidak.
Persaingan bolak-balik ini adalah ide utama di balik GAN.
Komponen dalam Generative Adversarial Network
Menggunakan contoh di atas, kita dapat menyusun arsitektur GAN.

Ada dua komponen utama dalam GAN: generator dan discriminator. Pemilik toko dalam contoh dikenal sebagai jaringan discriminator dan biasanya merupakan convolutional neural network (karena GAN terutama digunakan untuk tugas gambar) yang menetapkan probabilitas bahwa gambar tersebut asli.
Pemalsu dikenal sebagai jaringan generatif, dan biasanya juga merupakan convolutional neural network (dengan deconvolution layers). Jaringan ini mengambil vektor noise dan menghasilkan sebuah gambar. Saat melatih jaringan generatif, ia mempelajari area mana dari gambar yang perlu ditingkatkan/diubah agar discriminator semakin sulit membedakan gambar yang dihasilkannya dari gambar asli.
Jaringan generatif terus menghasilkan gambar yang semakin mirip dengan gambar asli sementara jaringan diskriminatif berusaha menentukan perbedaan antara gambar asli dan palsu. Tujuan akhirnya adalah memiliki jaringan generatif yang dapat menghasilkan gambar yang tidak dapat dibedakan dari yang asli.
Generative Adversarial Network Sederhana dengan Keras
Sekarang Anda memahami apa itu GAN dan komponen utamanya, kita bisa mulai membuat kode versi yang sangat sederhana. Anda akan menggunakan Keras dan jika Anda belum familiar dengan pustaka Python ini sebaiknya baca tutorial ini sebelum melanjutkan. Tutorial ini didasarkan pada GAN yang dikembangkan di sini.
Hal pertama yang perlu dilakukan adalah memasang paket berikut melalui pip
kerasmatplotlibtensorflowtqdm
Anda akan menggunakan matplotlib untuk plotting, tensorflow sebagai pustaka backend Keras dan tqdm untuk menampilkan bilah progres yang menarik untuk setiap epoch (iterasi).
Langkah berikutnya adalah membuat skrip Python. Dalam skrip ini, pertama-tama Anda perlu mengimpor semua modul dan fungsi yang akan digunakan. Penjelasan masing-masing akan diberikan saat digunakan.
import os
import numpy as np
import matplotlib.pyplot as plt
from tqdm import tqdm
from keras.layers import Input
from keras.models import Model, Sequential
from keras.layers.core import Dense, Dropout
from keras.layers.advanced_activations import LeakyReLU
from keras.datasets import mnist
from keras.optimizers import Adam
from keras import initializers
Sekarang Anda ingin menetapkan beberapa variabel:
# Let Keras know that we are using tensorflow as our backend engine
os.environ["KERAS_BACKEND"] = "tensorflow"
# To make sure that we can reproduce the experiment and get the same results
np.random.seed(10)
# The dimension of our random noise vector.
random_dim = 100
Sebelum mulai membangun discriminator dan generator, Anda harus terlebih dahulu mengumpulkan dan memproses data. Anda akan menggunakan dataset MNIST yang populer yang berisi kumpulan gambar digit tunggal dari 0 hingga 9.

def load_minst_data():
# load the data
(x_train, y_train), (x_test, y_test) = mnist.load_data()
# normalize our inputs to be in the range[-1, 1]
x_train = (x_train.astype(np.float32) - 127.5)/127.5
# convert x_train with a shape of (60000, 28, 28) to (60000, 784) so we have
# 784 columns per row
x_train = x_train.reshape(60000, 784)
return (x_train, y_train, x_test, y_test)
Perhatikan bahwa mnist.load_data() adalah bagian dari Keras dan memungkinkan Anda dengan mudah mengimpor dataset MNIST ke dalam workspace Anda.
Sekarang, Anda dapat membuat jaringan generator dan discriminator. Anda akan menggunakan optimizer Adam untuk kedua jaringan. Baik untuk generator maupun discriminator, Anda akan membuat jaringan saraf dengan tiga hidden layer dengan fungsi aktivasi Leaky Relu. Anda juga sebaiknya menambahkan dropout layer pada discriminator untuk meningkatkan ketahanannya terhadap gambar yang belum pernah dilihat.
# You will use the Adam optimizer
def get_optimizer():
return Adam(lr=0.0002, beta_1=0.5)
def get_generator(optimizer):
generator = Sequential()
generator.add(Dense(256, input_dim=random_dim, kernel_initializer=initializers.RandomNormal(stddev=0.02)))
generator.add(LeakyReLU(0.2))
generator.add(Dense(512))
generator.add(LeakyReLU(0.2))
generator.add(Dense(1024))
generator.add(LeakyReLU(0.2))
generator.add(Dense(784, activation='tanh'))
generator.compile(loss='binary_crossentropy', optimizer=optimizer)
return generator
def get_discriminator(optimizer):
discriminator = Sequential()
discriminator.add(Dense(1024, input_dim=784, kernel_initializer=initializers.RandomNormal(stddev=0.02)))
discriminator.add(LeakyReLU(0.2))
discriminator.add(Dropout(0.3))
discriminator.add(Dense(512))
discriminator.add(LeakyReLU(0.2))
discriminator.add(Dropout(0.3))
discriminator.add(Dense(256))
discriminator.add(LeakyReLU(0.2))
discriminator.add(Dropout(0.3))
discriminator.add(Dense(1, activation='sigmoid'))
discriminator.compile(loss='binary_crossentropy', optimizer=optimizer)
return discriminator
Akhirnya saatnya menyatukan generator dan discriminator!
def get_gan_network(discriminator, random_dim, generator, optimizer):
# We initially set trainable to False since we only want to train either the
# generator or discriminator at a time
discriminator.trainable = False
# gan input (noise) will be 100-dimensional vectors
gan_input = Input(shape=(random_dim,))
# the output of the generator (an image)
x = generator(gan_input)
# get the output of the discriminator (probability if the image is real or not)
gan_output = discriminator(x)
gan = Model(inputs=gan_input, outputs=gan_output)
gan.compile(loss='binary_crossentropy', optimizer=optimizer)
return gan
Untuk kelengkapan, Anda dapat membuat fungsi yang akan menyimpan gambar yang dihasilkan setiap 20 epoch. Karena ini bukan inti pelajaran, Anda tidak perlu benar-benar memahami fungsi tersebut.
# Create a wall of generated MNIST images
def plot_generated_images(epoch, generator, examples=100, dim=(10, 10), figsize=(10, 10)):
noise = np.random.normal(0, 1, size=[examples, random_dim])
generated_images = generator.predict(noise)
generated_images = generated_images.reshape(examples, 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', cmap='gray_r')
plt.axis('off')
plt.tight_layout()
plt.savefig('gan_generated_image_epoch_%d.png' % epoch)
Anda kini telah menulis sebagian besar kode jaringan Anda. Yang tersisa adalah melatih jaringan ini dan melihat gambar yang Anda buat.
def train(epochs=1, batch_size=128):
# Get the training and testing data
x_train, y_train, x_test, y_test = load_minst_data()
# Split the training data into batches of size 128
batch_count = x_train.shape[0] / batch_size
# Build our GAN netowrk
adam = get_optimizer()
generator = get_generator(adam)
discriminator = get_discriminator(adam)
gan = get_gan_network(discriminator, random_dim, generator, adam)
for e in xrange(1, epochs+1):
print '-'*15, 'Epoch %d' % e, '-'*15
for _ in tqdm(xrange(batch_count)):
# Get a random set of input noise and images
noise = np.random.normal(0, 1, size=[batch_size, random_dim])
image_batch = x_train[np.random.randint(0, x_train.shape[0], size=batch_size)]
# Generate fake MNIST images
generated_images = generator.predict(noise)
X = np.concatenate([image_batch, generated_images])
# Labels for generated and real data
y_dis = np.zeros(2*batch_size)
# One-sided label smoothing
y_dis[:batch_size] = 0.9
# Train discriminator
discriminator.trainable = True
discriminator.train_on_batch(X, y_dis)
# Train generator
noise = np.random.normal(0, 1, size=[batch_size, random_dim])
y_gen = np.ones(batch_size)
discriminator.trainable = False
gan.train_on_batch(noise, y_gen)
if e == 1 or e % 20 == 0:
plot_generated_images(e, generator)
if __name__ == '__main__':
train(400, 128)
Setelah melatih selama 400 epoch, Anda dapat melihat gambar yang dihasilkan. Melihat gambar yang dihasilkan setelah epoch pertama, Anda dapat melihat bahwa belum ada struktur nyata; melihat gambar setelah 40 epoch, digit mulai terbentuk dan terakhir, gambar yang dihasilkan setelah 400 epoch menunjukkan digit yang jelas meskipun beberapa masih belum bisa dikenali.
| Hasil setelah 1 epoch | Hasil setelah 40 epoch | Hasil setelah 400 epoch |
|---|---|---|
!![]() |
![]() |
![]() |
Kode ini memerlukan sekitar 2 menit per epoch pada CPU dan itulah alasan utama kode ini dipilih. Anda dapat bereksperimen dengan menggunakan lebih banyak epoch dan menambahkan lebih banyak (dan berbeda) layer pada generator dan discriminator. Namun, saat menggunakan arsitektur yang lebih kompleks dan dalam, waktu proses juga akan meningkat jika Anda hanya menggunakan CPU. Meski begitu, jangan biarkan hal itu menghentikan Anda untuk bereksperimen!
Kesimpulan
Selamat, Anda telah mencapai akhir tutorial ini, di mana Anda mempelajari dasar-dasar Generative Adversarial Networks (GAN) dengan cara yang intuitif! Selain itu, Anda telah mengimplementasikan model pertama Anda dengan bantuan pustaka Keras. Jika Anda ingin mengetahui lebih lanjut tentang deep learning dengan Python, pertimbangkan untuk mengambil kursus Deep Learning in Python dari DataCamp.



