Implementasi Neural Style Transfer dengan TensorFlow: Menggabungkan Konten dan Gaya Gambar

Lhuqita Fazry
Deep Learning TensorFlow Neural Style Transfer Computer Vision
Implementasi Neural Style Transfer dengan TensorFlow: Menggabungkan Konten dan Gaya Gambar
text
!pip install tensorflow matplotlib

Output:

text
TensorFlow 2.16.1, matplotlib, dan Pillow berhasil diinstal.

Memahami Prinsip Neural Style Transfer melalui Ekstraksi Fitur CNN

Neural Style Transfer (NST) adalah teknik yang menggabungkan konten dari satu gambar dengan gaya artistik dari gambar lain menggunakan deep learning. Ide dasarnya berasal dari paper A Neural Algorithm of Artistic Style oleh Gatys et al. pada tahun 2015. Konsep utamanya sederhana: kita mengambil dua gambar input, yaitu content image yang memuat struktur objek dan style image yang memuat tekstur artistik, lalu menghasilkan gambar baru yang memiliki konten dari gambar pertama dengan gaya dari gambar kedua.

CNN memiliki kemampuan unik untuk mengekstrak fitur secara hierarkis. Layer awal dalam arsitektur CNN menangkap informasi tekstur dasar seperti tepi, sudut, dan pola sederhana. Layer yang lebih dalam menangkap representasi semantik tingkat tinggi seperti bentuk objek dan struktur komposisi.

Hierarki fitur CNN dari tepi hingga objek

Gambar: Visualisasi hierarki fitur CNN — layer awal mendeteksi tepi dan tekstur sederhana, layer tengah mengenali pola dan bagian objek, sedangkan layer dalam memahami objek secara utuh. Sumber: [Melody Koh — Neural Style Transfer](https://melo04.github.io/neural-style-transfer/)

NST memanfaatkan properti ini dengan cara meminimalkan dua fungsi loss secara simultan. Content loss mengukur perbedaan representasi konten antara gambar yang dihasilkan dengan content image asli. Style loss mengukur perbedaan tekstur antara gambar yang dihasilkan dengan style image. Proses optimasi dilakukan secara iteratif, dimulai dari inisialisasi gambar acak atau salinan content image, lalu memperbarui nilai piksel secara bertahap menggunakan gradient descent.

Hasil akhir dari proses ini sangat bergantung pada pemilihan layer CNN yang digunakan. Menggunakan layer yang lebih dalam untuk content loss akan mempertahankan struktur semantik yang lebih abstrak, sementara layer yang lebih dangkal akan mempertahankan detail tekstur yang lebih halus.

Content Loss dan Style Loss sebagai Dua Fungsi Objektif

Untuk memahami NST secara teknis, kita perlu mendalami dua fungsi loss yang menjadi fondasi algoritma ini. Gambar di bawah mengilustrasikan arsitektur dasar NST: content image (kiri) dan style image (kanan) masing-masing melewati VGG19 untuk mengekstrak feature maps, lalu dihitung content loss dan style loss-nya terhadap generated image.

Arsitektur dasar Neural Style Transfer

Gambar: Arsitektur dasar Neural Style Transfer — content image, style image, dan generated image diproses melalui VGG19 untuk mengekstrak feature maps. Content loss dihitung dari layer dalam, sementara style loss menggunakan Gram matrix dari beberapa layer. Sumber: [Melody Koh — Neural Style Transfer](https://melo04.github.io/neural-style-transfer/)

Content loss dihitung menggunakan Mean Squared Error (MSE) antara feature maps content image dan generated image pada satu layer tertentu, biasanya layer convolutional yang cukup dalam seperti block5_conv2. Perbedaannya, MSE yang rendah berarti generated image mempertahankan struktur visual yang mirip dengan content image.

Style loss bekerja dengan cara yang berbeda. Representasi gaya ditangkap menggunakan Gram matrix, yaitu matriks korelasi antar channel dalam sebuah feature map. Gram matrix dihitung dengan mengalikan feature map yang sudah di-flatten dengan transposenya. Hasilnya adalah matriks yang merepresentasikan tekstur dan pola tanpa menyimpan informasi spasial. Inilah yang membuat style bisa ditransfer secara independen dari posisi objek dalam gambar.

Style loss dihitung dengan menjumlahkan MSE antara Gram matrix style image dan generated image dari beberapa layer sekaligus. Kombinasi layer style yang berbeda akan menghasilkan skala tekstur yang berbeda. Layer awal menangkap pola halus, layer tengah menangkap tekstur sedang, dan layer dalam menangkap komposisi gaya global.

Total loss yang dioptimasi adalah kombinasi linear dari content loss, style loss, dan total variation loss. Total variation loss berfungsi sebagai regularizer yang mengurangi noise berlebih pada generated image. Rasio antara content weight dan style weight adalah parameter paling penting dalam NST, karena menentukan sejauh mana konten asli dipertahankan versus seberapa kuat gaya diterapkan.

Arsitektur lengkap Neural Style Transfer dengan alur optimasi
Deep Learning Bootcamp
Machine Learning • Intermediate

Deep Learning Bootcamp

A beginner-friendly, highly interactive bootcamp designed to take you from found...

Daftar

Gambar: Arsitektur lengkap NST — content image dan style image diekstrak fiturnya melalui VGG19, kemudian content loss dan style loss dihitung dan dikombinasikan menjadi total loss. Gradien dari total loss digunakan untuk memperbarui piksel generated image secara iteratif. Sumber: [Melody Koh — Neural Style Transfer](https://melo04.github.io/neural-style-transfer/)

Setup TensorFlow dan Load Model Pre-trained VGG19 untuk Ekstraksi Feature Maps

VGG19 adalah pilihan standar untuk NST karena arsitekturnya yang sederhana namun mampu menangkap representasi visual yang kaya. Tidak seperti arsitektur modern yang kompleks, VGG19 menggunakan susunan layer convolutional yang seragam, memudahkan kita memilih layer spesifik untuk mengekstrak fitur konten dan gaya.

Berikut kode untuk memuat VGG19 dan membangun model intermediate:

pythonpython
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

# Load VGG19 tanpa classification head
vgg = tf.keras.applications.VGG19(include_top=False, weights="imagenet")
vgg.trainable = False

# Definisikan layer untuk content dan style
content_layers = ["block5_conv2"]
style_layers = [
    "block1_conv1",
    "block2_conv1",
    "block3_conv1",
    "block4_conv1",
    "block5_conv1",
]

# Bangun model yang mengembalikan output dari layer terpilih
layer_outputs = [vgg.get_layer(name).output for name in content_layers + style_layers]
feature_model = tf.keras.Model(inputs=vgg.input, outputs=layer_outputs)

# Test dengan input dummy
dummy = tf.random.normal([1, 400, 400, 3])
outputs = feature_model(dummy)
for i, (name, out) in enumerate(zip(content_layers + style_layers, outputs)):
    print(f"{name}: {out.shape}")

Output:

text
block5_conv2: (1, 25, 25, 512)
block1_conv1: (1, 400, 400, 64)
block2_conv1: (1, 200, 200, 128)
block3_conv1: (1, 100, 100, 256)
block4_conv1: (1, 50, 50, 512)
block5_conv1: (1, 25, 25, 512)

Kode di atas memuat VGG19 dengan include_top=False agar kita hanya mengambil bagian convolutional. Kita memilih block5_conv2 untuk content loss karena letaknya yang dalam, dan lima layer dari block1_conv1 sampai block5_conv1 untuk style loss agar menangkap variasi skala tekstur. Model intermediate yang kita bangun akan mengembalikan output dari keenam layer tersebut setiap kali kita melakukan forward pass.

Output yang dihasilkan berupa konfirmasi bentuk tensor setiap layer, misalnya block5_conv2: (1, 12, 12, 512) yang menunjukkan feature map dengan resolusi spasial 12x12 dan 512 channel.

Implementasi Gram Matrix, Fungsi Loss, dan Training Loop dengan GradientTape

Setelah model siap, kita perlu mengimplementasikan Gram matrix, fungsi loss, dan training loop. Gram matrix dihitung dengan operasi tf.matmul antara feature map yang di-flatten dengan transposenya, lalu dinormalisasi dengan jumlah elemen.

Berikut implementasi lengkapnya:

pythonpython
def gram_matrix(features):
    features = tf.reshape(features, (tf.shape(features)[0], -1, tf.shape(features)[-1]))
    gram = tf.matmul(features, features, transpose_a=True)
    return gram / tf.cast(tf.shape(features)[1] * tf.shape(features)[2], tf.float32)

def content_loss(content, generated):
    return tf.reduce_mean(tf.square(content - generated))

def style_loss(style, generated):
    return tf.reduce_mean(tf.square(gram_matrix(style) - gram_matrix(generated)))

content_weight = 1e4
style_weight = 1e-2
tv_weight = 30

# Preprocessing fungsi
def preprocess(img_path, target_size=400):
    img = Image.open(img_path).resize((target_size, target_size))
    img = tf.keras.applications.vgg19.preprocess_input(np.array(img)[None, ...])
    return tf.constant(img)

content_img = preprocess("content.jpg")
style_img = preprocess("style.jpg")

# Ekstrak target features
content_features = feature_model(content_img)[0]
style_features = feature_model(style_img)[1:]

# Inisialisasi generated image
generated = tf.Variable(tf.cast(content_img, tf.float32))
optimizer = tf.keras.optimizers.Adam(learning_rate=2.0)

@tf.function
def train_step():
    with tf.GradientTape() as tape:
        gen_outputs = feature_model(generated)
        gen_content = gen_outputs[0]
        gen_style = gen_outputs[1:]

        c_loss = content_loss(content_features, gen_content)
        s_loss = sum(style_loss(s, g) for s, g in zip(style_features, gen_style))
        tv_loss = tf.reduce_sum(tf.image.total_variation(generated))

        total = content_weight * c_loss + style_weight * s_loss + tv_weight * tv_loss

    grad = tape.gradient(total, generated)
    optimizer.apply_gradients([(grad, generated)])
    clipped = tf.clip_by_value(generated, -127.5, 127.5)
    generated.assign(clipped)

# Training loop
for epoch in range(100):
    train_step()
    if epoch % 10 == 0:
        c_loss_val = content_weight * content_loss(content_features, feature_model(generated)[0])
        print(f"Epoch {epoch}: content={c_loss_val.numpy():.2f}")

Output:

text
Epoch 0: content=1193040.12
Epoch 10: content=225583.75
Epoch 20: content=194919.30
Epoch 30: content=205454.39
Epoch 40: content=239870.98
Epoch 50: content=286837.72
Epoch 60: content=340791.91
Epoch 70: content=400580.97
Epoch 80: content=458630.09
Epoch 90: content=521340.34

Gram matrix mengubah feature map menjadi representasi statistik yang kehilangan informasi posisi. Inilah kunci NST: kita bisa mentransfer tekstur tanpa peduli di mana tekstur itu muncul. Training loop menggunakan tf.GradientTape untuk menghitung gradien total loss terhadap setiap piksel generated image. Adam optimizer kemudian memperbarui piksel tersebut. Setelah setiap langkah, kita melakukan clipping untuk menjaga nilai piksel dalam rentang yang valid.

Mengevaluasi dan Menyesuaikan Parameter untuk Hasil Style Transfer yang Optimal

Proses training NST membutuhkan pengamatan visual untuk menentukan kapan hasilnya optimal. Kita bisa memvisualisasikan generated image di beberapa checkpoint selama training:

pythonpython
def deprocess(img):
    img = img.numpy().squeeze()
    img = img + [103.939, 116.779, 123.68]
    img = np.clip(img, 0, 255).astype(np.uint8)
    return img

fig, axes = plt.subplots(2, 5, figsize=(15, 6))
for i, ax in enumerate(axes.flat):
    epoch_chekpoint = i * 10
    # Dalam praktiknya, simpan gambar di setiap checkpoint
    ax.imshow(deprocess(generated))
    ax.set_title(f"Epoch {epoch_chekpoint}")
    ax.axis("off")
plt.tight_layout()
plt.show()

Output:

Visualisasi hasil Neural Style Transfer

Parameter yang paling berpengaruh adalah rasio content_weight terhadap style_weight. Content weight yang tinggi mempertahankan struktur objek asli, sementara style weight yang tinggi menghasilkan tekstur artistik yang dominan hingga bisa menutupi konten asli. Pemilihan layer style juga penting: menggunakan lebih banyak layer awal menghasilkan tekstur halus, sementara layer dalam menghasilkan goresan gaya yang lebih besar.

Dalam praktiknya, kita perlu bereksperimen dengan rasio yang berbeda untuk setiap pasangan content dan style image. Pasangan gambar yang berbeda membutuhkan penyesuaian parameter yang berbeda pula. Tidak ada rasio universal yang bekerja untuk semua kasus.

Keterbatasan NST berbasis Optimasi dan Alternatif Fast Style Transfer

Kelemahan utama NST berbasis optimasi adalah kecepatan. Setiap pasangan content dan style image baru membutuhkan proses training dari awal yang bisa memakan 50 sampai 200 iterasi. Untuk gambar beresolusi tinggi, waktu yang dibutuhkan bisa mencapai beberapa menit bahkan dengan GPU.

Alternatif yang lebih cepat adalah Fast Style Transfer, yang menggunakan arsitektur feed-forward. Pendekatan ini melatih sebuah jaringan transformer untuk mempelajari mapping gaya tertentu sekali, lalu melakukan inference secara instan pada gambar baru. Kekurangannya, satu model hanya bisa menghasilkan satu gaya spesifik.

Ada juga Arbitrary Style Transfer dengan arsitektur seperti AdaIN (Adaptive Instance Normalization). Pendekatan ini bisa menerima gaya gambar baru tanpa perlu retraining. Model menyesuaikan statistik mean dan variance dari feature maps content agar sesuai dengan style image.

Best practices untuk NST meliputi: melakukan preprocessing dengan resize gambar ke resolusi yang konsisten (biasanya 400-512px), menggunakan GPU untuk akselerasi, memulai training dengan resolusi rendah kemudian meningkatkan secara progresif (multi-scale), dan menggunakan total variation loss untuk mengurangi noise. Dengan pemahaman yang baik tentang trade-off setiap pendekatan, kita bisa memilih metode yang paling sesuai untuk kebutuhan proyek.

Tertarik menguasai Neural Style Transfer, GAN, dan arsitektur generatif modern lainnya secara mendalam? Program Deep Learning & Computer Vision di Rumah Coding membahas semua topik ini dengan pendekatan praktis dan proyek nyata. Daftar sekarang dan bangun portofolio AI generatif kamu.

Kursus Terkait

GreenGuard: Intelligent Plant Disease Diagnosis Web App
Kursus Premium Machine Learning

Deep Learning Bootcamp

A beginner-friendly, highly interactive bootcamp designed to take you from foundational concepts to deploying real-world Artificial Intelligence applications. Through a completely project-based approach, you will master the core of Deep Learning, Artificial Neural Networks, and Computer Vision using Python and TensorFlow, ultimately building a professional-grade AI web application for your portfolio.

Proyek Akhir

GreenGuard: Intelligent Plant Disease Diagnosis Web App

  • Interactive Image Upload UI: A clean, user-friendly interface built with Streamlit that supports drag-and-drop image uploads directly from a computer or mobile phone.
  • Real-Time AI Inference: Utilizes a lightweight, optimized CNN model (like MobileNetV2) to process the image and return a diagnosis in seconds without heavy server load.
  • Confidence Scoring Dashboard: Visually displays the model's prediction probability (e.g., "95% confident this is Tomato Late Blight") using interactive progress bars or charts.
7 Weeks Intermediate
Lihat Detail Kursus
Domain-Specific AI Knowledge Assistant
Kursus Premium Machine Learning

LLM Bootcamp

This project-based bootcamp is designed for beginners to dive practically into the world of Large Language Models (LLMs). Through hands-on building, you will learn how to interact with top-tier AI APIs, master prompt engineering, orchestrate complex workflows using LangChain, and implement Retrieval-Augmented Generation (RAG) to query your own documents. By the end of this course, you will have the skills to build, test, and deploy a fully functional, custom AI web application.

Proyek Akhir

Domain-Specific AI Knowledge Assistant

  • Dynamic Document Processing: A sidebar interface allowing users to upload new PDF or TXT files, which the app automatically chunks, embeds, and stores in the vector database.
  • Context-Aware Chat UI: A modern chat interface built with Streamlit that maintains conversation history, allowing users to ask follow-up questions naturally.
  • Strict Guardrails (Anti-Hallucination): System instructions designed so the AI politely declines to answer questions that fall outside the context of the uploaded documents.
7 Weeks Beginner
Lihat Detail Kursus
End-to-End Student Success Predictor
Kursus Premium Machine Learning

Machine Learning Bootcamp

A beginner-friendly, 7-week project-based bootcamp designed to take you from Python basics to deploying your first Machine Learning model. Through hands-on practice, you will master essential data manipulation, build predictive algorithms, and develop an end-to-end, industry-ready application to kickstart your career in data science.

Proyek Akhir

End-to-End Student Success Predictor

  • Automated Data Pipeline: A preprocessing script that automatically cleans missing values, encodes categorical data (like course type or student background), and scales numerical inputs.
  • Predictive Engine: A tuned machine learning classification model (e.g., Random Forest) specifically optimized for high Recall, ensuring that "at-risk" students are not missed.
  • Interactive Web Dashboard: A user-friendly Streamlit interface featuring a sidebar where instructors can manually input a student's study hours, quiz scores, and login frequency to get an instant pass/fail probability.
7 Weeks Intermediate
Lihat Detail Kursus

Artikel Terkait