Langsung ke konten
KamusNgoding
Menengah Deep-learning 6 menit baca

CNN vs RNN: Perbedaan dan Kapan Menggunakannya

#cnn #rnn #deep learning #neural network

CNN vs RNN: Perbedaan dan Kapan Menggunakannya

Pendahuluan

Saat mulai mendalami deep learning, dua arsitektur yang paling sering disebut adalah CNN (Convolutional Neural Network) dan RNN (Recurrent Neural Network). Keduanya adalah fondasi dari sebagian besar aplikasi AI modern — mulai dari pengenalan wajah di smartphone hingga fitur autocomplete di keyboard.

Tapi pertanyaan yang sering muncul: kapan harus pakai CNN, dan kapan harus pakai RNN?

Artikel ini akan menjawab pertanyaan itu secara praktis, lengkap dengan kode yang bisa langsung kamu jalankan. Jika kamu ingin membangun aplikasi seperti Gojek yang butuh fitur pengenalan gambar untuk verifikasi driver, atau sistem rekomendasi berbasis histori pengguna seperti Tokopedia, pemahaman ini krusial.


Memahami Convolutional Neural Network (CNN)

CNN dirancang untuk memproses data yang memiliki struktur grid — paling umum adalah gambar (2D grid piksel). Ide utamanya adalah ekstraksi fitur lokal menggunakan filter yang bergeser (konvolusi) di atas input.

Cara Kerja CNN

CNN terdiri dari tiga jenis layer utama:

  • Convolutional Layer: Mendeteksi fitur lokal (tepi, tekstur, pola)
  • Pooling Layer: Mereduksi dimensi, menjaga fitur penting
  • Fully Connected Layer: Klasifikasi akhir
import tensorflow as tf
from tensorflow.keras import layers, models

# Menetapkan seed agar hasil lebih konsisten saat dijalankan ulang
tf.random.set_seed(42)

# Membangun model CNN sederhana untuk klasifikasi gambar CIFAR-10
model_cnn = models.Sequential([
    # Layer input menjelaskan bentuk data gambar: 32x32 piksel dengan 3 channel warna
    layers.Input(shape=(32, 32, 3)),

    # Blok konvolusi pertama: mengekstrak fitur dasar seperti tepi dan pola sederhana
    layers.Conv2D(32, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),  # Mengurangi ukuran fitur agar komputasi lebih efisien

    # Blok konvolusi kedua: menangkap fitur yang lebih kompleks
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),

    # Blok konvolusi ketiga: memperdalam representasi fitur
    layers.Conv2D(64, (3, 3), activation='relu'),

    # Mengubah output fitur 2D menjadi vektor 1D sebelum masuk ke layer Dense
    layers.Flatten(),
    layers.Dense(64, activation='relu'),  # Layer fully connected untuk belajar pola akhir
    layers.Dense(10, activation='softmax')  # Output 10 kelas untuk CIFAR-10
])

# Compile model: menentukan optimizer, fungsi loss, dan metrik evaluasi
model_cnn.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy']
)

# Menampilkan ringkasan arsitektur model
model_cnn.summary()

# Output yang diharapkan:
# > Model: "sequential"
# > Total params: 122,570

Karakteristik Utama CNN

PropertiNilai
Input idealGambar, sinyal audio (spektrogram), data grid
Parameter sharingYa — filter yang sama dipakai di seluruh input
Invariansi posisiYa — bisa mengenali objek di mana saja di gambar
Memori konteksTidak ada — setiap patch diproses independen

CNN sangat efisien karena parameter sharing: satu filter digunakan di seluruh gambar, sehingga jumlah parameter jauh lebih kecil dibanding fully connected network.


Memahami Recurrent Neural Network (RNN)

RNN dirancang untuk memproses data sekuensial — data yang urutannya penting. Contohnya: teks, audio waveform, data time-series harga saham, atau log aktivitas pengguna.

Cara Kerja RNN

RNN punya hidden state (memori internal) yang di-update setiap langkah waktu. Output dari step sebelumnya menjadi input untuk step berikutnya.

import numpy as np
import tensorflow as tf
from tensorflow.keras import layers, models

# Tetapkan seed agar hasil contoh lebih konsisten saat dijalankan
tf.random.set_seed(42)
np.random.seed(42)

# Konfigurasi dasar model
VOCAB_SIZE = 10000   # Jumlah maksimum kata unik dalam vocabulary
EMBED_DIM = 64       # Dimensi vektor embedding untuk setiap kata
MAX_LEN = 200        # Panjang maksimum setiap input teks
BATCH_SIZE = 4

# Contoh data input dummy:
# Setiap angka merepresentasikan token/kata yang sudah diubah menjadi integer
x_dummy = np.random.randint(0, VOCAB_SIZE, size=(BATCH_SIZE, MAX_LEN))

# Model LSTM untuk klasifikasi sentimen biner
model_rnn = models.Sequential([
    # Embedding: mengubah token integer menjadi vektor padat
    layers.Embedding(input_dim=VOCAB_SIZE, output_dim=EMBED_DIM),

    # LSTM pertama mengembalikan seluruh urutan output ke layer berikutnya
    layers.LSTM(64, return_sequences=True),

    # LSTM kedua merangkum informasi urutan menjadi satu vektor
    layers.LSTM(32),

    # Dense layer untuk mempelajari pola non-linear sebelum output
    layers.Dense(16, activation='relu'),

    # Output sigmoid: menghasilkan probabilitas sentimen positif (0-1)
    layers.Dense(1, activation='sigmoid')
])

# Compile model dengan loss untuk klasifikasi biner
model_rnn.compile(
    optimizer='adam',
    loss='binary_crossentropy',
    metrics=['accuracy']
)

# Tampilkan ringkasan arsitektur model
model_rnn.summary()

# Jalankan prediksi contoh agar kode benar-benar runnable
predictions = model_rnn.predict(x_dummy, verbose=0)

# Cetak bentuk output dan satu contoh nilai prediksi
print("Shape output prediksi:", predictions.shape)
print("Contoh skor sentimen:", float(predictions[0, 0]))

# Output yang diharapkan:
# > Ringkasan model (Model: "sequential", daftar layer, dan jumlah parameter) akan tampil
# > Shape output prediksi: (4, 1)
# > Contoh skor sentimen: nilai float antara 0.0 dan 1.0

Varian RNN yang Populer

RNN vanilla punya masalah vanishing gradient — sulit mengingat konteks yang jauh. Dua varian yang mengatasi ini:

import tensorflow as tf
from tensorflow.keras import layers

# Contoh data input:
# batch_size=2, panjang_sequence=10, jumlah_fitur=8
x = tf.random.normal((2, 10, 8))

# LSTM cocok untuk menangkap pola urutan yang panjang
lstm_layer = layers.LSTM(128, return_sequences=False)
lstm_output = lstm_layer(x)

# GRU mirip LSTM, tetapi lebih ringan dan lebih cepat dilatih
gru_layer = layers.GRU(128, return_sequences=False)
gru_output = gru_layer(x)

# Bidirectional membaca sequence dari depan dan belakang
bi_lstm = layers.Bidirectional(layers.LSTM(64))
bi_output = bi_lstm(x)

# Tampilkan bentuk output dari masing-masing layer
print("Shape output LSTM:", lstm_output.shape)
print("Shape output GRU:", gru_output.shape)
print("Shape output Bidirectional LSTM:", bi_output.shape)

# Output yang diharapkan:
# > Shape output LSTM: (2, 128)
# > Shape output GRU: (2, 128)
# > Shape output Bidirectional LSTM: (2, 128)

Perbedaan Utama: Arsitektur, Tipe Data, dan Aplikasi

Perbandingan Langsung

AspekCNNRNN/LSTM
Tipe dataSpasial (gambar, grid)Sekuensial (teks, time-series)
Urutan dataTidak pentingSangat penting
MemoriTidak ada memori antar posisiAda hidden state (memori)
KomputasiParalel (cepat)Sekuensial (lebih lambat)
Kedalaman konteksLokal (kernel size)Seluruh sekuens (teoritis)
ParameterRelatif sedikit (weight sharing)Lebih banyak

Kapan Gunakan CNN?

Gunakan CNN ketika:

  • Input berupa gambar (klasifikasi, deteksi objek, segmentasi)
  • Data memiliki pola lokal yang berulang (tekstur, tepi)
  • Posisi relatif antar fitur penting, bukan urutan absolut
  • Butuh training yang cepat (CNN lebih mudah diparalelkan)
# Contoh use case CNN untuk deep learning
# CNN cocok untuk data gambar karena bisa belajar pola visual seperti tepi, tekstur, dan bentuk.

# Input contoh: gambar KTP berukuran 224x224 piksel
input_size = (224, 224)

# Daftar contoh penggunaan CNN di dunia nyata
use_cnn_for = [
    "Klasifikasi gambar produk (seperti Tokopedia)",
    "Deteksi helm pada pengemudi (safety monitoring)",
    "OCR dokumen (KTP, STNK)",
    "Medical imaging (deteksi anomali X-ray)"
]

# Tampilkan informasi ukuran input
print(f"Ukuran input gambar: {input_size[0]}x{input_size[1]} piksel")

# Tampilkan semua use case CNN satu per satu
print("Contoh penggunaan CNN:")
for i, use_case in enumerate(use_cnn_for, start=1):
    print(f"{i}. {use_case}")

# Output yang diharapkan:
# > Ukuran input gambar: 224x224 piksel
# > Contoh penggunaan CNN:
# > 1. Klasifikasi gambar produk (seperti Tokopedia)
# > 2. Deteksi helm pada pengemudi (safety monitoring)
# > 3. OCR dokumen (KTP, STNK)
# > 4. Medical imaging (deteksi anomali X-ray)

Kapan Gunakan RNN/LSTM?

Gunakan RNN ketika:

  • Input berupa teks atau urutan kata
  • Data adalah time-series (harga saham, sensor IoT)
  • Konteks sebelumnya mempengaruhi interpretasi sekarang
  • Task melibatkan generasi sekuens (terjemahan, teks generation)
# Contoh use case RNN untuk analisis ulasan produk dan data berurutan

# List berisi beberapa contoh penggunaan RNN di dunia nyata
use_rnn_for = [
    "Analisis sentimen ulasan pelanggan",
    "Prediksi teks berikutnya (autocomplete)",
    "Penerjemahan bahasa (seq2seq)",
    "Forecasting demand produk (time-series)",
    "Deteksi anomali log server"
]

# Tampilkan judul agar output lebih jelas
print("Contoh penggunaan RNN:")

# enumerate(..., start=1) memberi nomor urut mulai dari 1
for i, use_case in enumerate(use_rnn_for, start=1):
    print(f"{i}. {use_case}")

# Output yang diharapkan:
# > Contoh penggunaan RNN:
# > 1. Analisis sentimen ulasan pelanggan
# > 2. Prediksi teks berikutnya (autocomplete)
# > 3. Penerjemahan bahasa (seq2seq)
# > 4. Forecasting demand produk (time-series)
# > 5. Deteksi anomali log server

Contoh Kasus Nyata

Kasus 1: Sistem Moderasi Konten (Teks + Gambar)

Bayangkan kamu membangun platform e-commerce seperti Bukalapak yang perlu memvalidasi listing produk. Kamu butuh keduanya:

import tensorflow as tf
from tensorflow.keras import layers, Input, Model

# Fungsi untuk membangun model multimodal:
# CNN untuk memproses gambar, LSTM untuk memproses teks
def build_multimodal_model():
    # Input gambar berukuran 224x224 dengan 3 channel warna (RGB)
    image_input = Input(shape=(224, 224, 3), name="image_input")

    # Cabang CNN untuk ekstraksi fitur dari gambar
    x = layers.Conv2D(32, (3, 3), activation="relu")(image_input)
    x = layers.MaxPooling2D(pool_size=(2, 2))(x)
    x = layers.Conv2D(64, (3, 3), activation="relu")(x)
    x = layers.GlobalAveragePooling2D()(x)
    image_features = layers.Dense(128, activation="relu")(x)

    # Input teks berupa urutan token dengan panjang 100
    text_input = Input(shape=(100,), name="text_input")

    # Embedding mengubah token menjadi vektor, lalu LSTM membaca urutan kata
    y = layers.Embedding(input_dim=10000, output_dim=64)(text_input)
    y = layers.LSTM(64)(y)
    text_features = layers.Dense(128, activation="relu")(y)

    # Menggabungkan fitur dari gambar dan teks
    combined = layers.concatenate([image_features, text_features])

    # Lapisan akhir untuk klasifikasi biner
    z = layers.Dense(64, activation="relu")(combined)
    output = layers.Dense(1, activation="sigmoid", name="is_valid")(z)

    # Membuat model dengan dua input dan satu output
    model = Model(inputs=[image_input, text_input], outputs=output)
    return model


# Bangun model
model = build_multimodal_model()

# Compile model agar siap dilatih
model.compile(
    optimizer="adam",
    loss="binary_crossentropy",
    metrics=["accuracy"]
)

# Tampilkan ringkasan arsitektur model
model.summary()

# Pesan singkat bahwa model berhasil dibuat
print("Model hybrid CNN + LSTM siap digunakan!")

# Output yang diharapkan:
# > Model: "model"
# > Total params: ...
# > Model hybrid CNN + LSTM siap digunakan!

Kasus 2: Prediksi Time-Series dengan LSTM

import numpy as np
import tensorflow as tf
from tensorflow.keras import layers, models

# Fungsi untuk mengubah data time series menjadi pasangan input-output
# X berisi urutan data sebelumnya, y berisi nilai target setelah urutan tersebut
def create_sequences(data, seq_length=30):
    X, y = [], []
    for i in range(len(data) - seq_length):
        X.append(data[i:i + seq_length])
        y.append(data[i + seq_length])
    return np.array(X), np.array(y)

# Set seed agar hasil random konsisten saat dijalankan ulang
np.random.seed(42)
tf.random.set_seed(42)

# Membuat data dummy berbentuk pola musiman + noise
# Dalam kasus nyata, ganti ini dengan data demand harian asli
demand_data = np.sin(np.linspace(0, 100, 1000)) + np.random.normal(0, 0.1, 1000)

# Panjang urutan input: model melihat 30 hari sebelumnya untuk prediksi hari berikutnya
seq_length = 30
X, y = create_sequences(demand_data, seq_length=seq_length)

# Ubah bentuk input menjadi (jumlah_sampel, jumlah_timestep, jumlah_fitur)
# Karena hanya ada 1 fitur per waktu, jumlah_fitur = 1
X = X.reshape(X.shape[0], X.shape[1], 1)

# Membangun model LSTM untuk forecasting time series
model = models.Sequential([
    layers.Input(shape=(seq_length, 1)),              # Bentuk input: 30 timestep, 1 fitur
    layers.LSTM(64, return_sequences=True),           # LSTM pertama mengembalikan seluruh urutan
    layers.LSTM(32),                                  # LSTM kedua menghasilkan representasi akhir
    layers.Dense(16, activation="relu"),              # Layer dense untuk belajar pola non-linear
    layers.Dense(1)                                   # Output: 1 nilai prediksi
])

# Compile model dengan optimizer Adam dan loss MSE
model.compile(optimizer="adam", loss="mse")

# Latih model menggunakan 20% data training sebagai validasi
history = model.fit(
    X,
    y,
    epochs=10,
    batch_size=32,
    validation_split=0.2,
    verbose=1
)

# Ambil satu sampel terakhir untuk mencoba prediksi
sample_input = X[-1:]
prediction = model.predict(sample_input, verbose=0)

# Tampilkan hasil prediksi
print("Shape X:", X.shape)
print("Shape y:", y.shape)
print("Prediksi demand berikutnya:", round(float(prediction[0][0]), 4))

# Output yang diharapkan:
# > Shape X: (970, 30, 1)
# > Shape y: (970,)
# > Prediksi demand berikutnya: [angka prediksi, misalnya -0.43]

Untuk memahami lebih dalam tentang arsitektur yang terinspirasi dari RNN seperti Transformer, kamu bisa baca Mengenal Large Language Model (LLM): Dasar-Dasar AI Modern. Dan jika kamu ingin memahami efisiensi komputasi dari kedua arsitektur ini secara teoritis, artikel Mengenal Big O Notation: Cara Mengukur Efisiensi Algoritma akan sangat membantu.


Troubleshooting: Error yang Sering Muncul

Input Shape Salah pada CNN

Penyebab: CNN mengharapkan input 4D (batch, height, width, channels), tapi sering lupa menambahkan dimensi channel atau batch.

Solusi:

import numpy as np
import tensorflow as tf
from tensorflow.keras import layers, models

# Buat ulang model CNN untuk demo ini
model_cnn = models.Sequential([
    layers.Input(shape=(32, 32, 3)),
    layers.Conv2D(32, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Flatten(),
    layers.Dense(10, activation='softmax')
])
model_cnn.compile(optimizer='adam', loss='sparse_categorical_crossentropy')

# ❌ Salah — shape (32, 32, 3) tanpa batch dimension
image = np.random.rand(32, 32, 3)
# model_cnn.predict(image)  # Error: Expected input shape (None, 32, 32, 3)

# ✅ Benar — tambahkan batch dimension dengan expand_dims
image = np.expand_dims(image, axis=0)  # Shape jadi (1, 32, 32, 3)
prediction = model_cnn.predict(image, verbose=0)
print(f"Prediction shape: {prediction.shape}")

# Atau untuk batch gambar:
batch_images = np.random.rand(16, 32, 32, 3)  # 16 gambar sekaligus
predictions = model_cnn.predict(batch_images, verbose=0)
print(f"Batch prediction shape: {predictions.shape}")

# Output yang diharapkan:
# > Prediction shape: (1, 10)
# > Batch prediction shape: (16, 10)

LSTM Gradient Exploding/Vanishing

Penyebab: Saat training RNN pada sekuens panjang, gradient bisa meledak (NaN loss) atau menghilang (model tidak belajar). Ini adalah masalah klasik RNN vanilla.

Solusi:

from tensorflow.keras import layers, models
from tensorflow.keras.optimizers import Adam

# ✅ Gunakan gradient clipping untuk mencegah exploding gradient
optimizer = Adam(learning_rate=0.001, clipnorm=1.0)

# ✅ Gunakan LSTM atau GRU, bukan SimpleRNN
model_fixed = models.Sequential([
    layers.Embedding(10000, 64, input_length=200),
    # Hindari SimpleRNN untuk sekuens panjang:
    # layers.SimpleRNN(64)  # Rentan vanishing gradient

    # Gunakan LSTM atau GRU sebagai gantinya
    layers.LSTM(64, recurrent_dropout=0.2),  # recurrent_dropout tambah regularisasi
    layers.Dense(1, activation='sigmoid')
])

model_fixed.compile(optimizer=optimizer, loss='binary_crossentropy', metrics=['accuracy'])
model_fixed.summary()

# Output yang diharapkan:
# > Model: "sequential"
# > Total params: ...

OOM (Out of Memory) saat Training CNN dengan Gambar Resolusi Tinggi

Penyebab: Gambar beresolusi tinggi (misalnya 1024x1024) dengan batch size besar menghabiskan seluruh VRAM GPU.

Solusi:

import tensorflow as tf
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import os

# ✅ Gunakan ImageDataGenerator dengan flow_from_directory
# untuk loading data secara bertahap (tidak sekaligus ke memory)
datagen = ImageDataGenerator(
    rescale=1./255,
    validation_split=0.2
)

# Asumsikan folder 'data/images/' sudah ada dengan subfolder per kelas
# train_generator = datagen.flow_from_directory(
#     'data/images/',
#     target_size=(224, 224),  # Resize ke ukuran lebih kecil dari resolusi asli
#     batch_size=16,            # Kurangi batch size jika masih OOM (coba 8 atau 4)
#     class_mode='categorical',
#     subset='training'
# )

# ✅ Atau aktifkan mixed precision training untuk hemat memori ~50%
tf.keras.mixed_precision.set_global_policy('mixed_float16')
print("Policy aktif:", tf.keras.mixed_precision.global_policy().name)

# Output yang diharapkan:
# > Policy aktif: mixed_float16

Sequence Length Tidak Konsisten di LSTM

Penyebab: RNN/LSTM memerlukan input dengan panjang sekuens yang sama dalam satu batch, tapi teks asli memiliki panjang berbeda-beda.

Solusi:

from tensorflow.keras.preprocessing.sequence import pad_sequences

# Data teks dengan panjang berbeda
sequences = [
    [1, 2, 3],
    [4, 5, 6, 7, 8],
    [9, 10]
]

# ✅ Padding: seragamkan panjang dengan 0
MAX_LEN = 10
padded = pad_sequences(
    sequences,
    maxlen=MAX_LEN,
    padding='post',    # Tambahkan 0 di akhir
    truncating='post'  # Potong dari akhir jika terlalu panjang
)

print("Hasil padding:")
print(padded)

# Output yang diharapkan:
# > Hasil padding:
# > [[ 1  2  3  0  0  0  0  0  0  0]
# >  [ 4  5  6  7  8  0  0  0  0  0]
# >  [ 9 10  0  0  0  0  0  0  0  0]]

Pertanyaan yang Sering Diajukan

Apa perbedaan mendasar antara CNN dan RNN?

CNN memproses data spasial (seperti gambar) dengan mengekstrak pola lokal menggunakan filter konvolusi yang bergeser — posisi piksel penting, tapi tidak ada memori antar posisi. RNN memproses data sekuensial dengan menyimpan “memori” dari step sebelumnya dalam hidden state, sehingga cocok untuk data di mana urutan menentukan makna (seperti kalimat atau time-series).

Bisakah CNN digunakan untuk data teks?

Ya, bisa! CNN 1D (Conv1D) sering dipakai untuk klasifikasi teks karena bisa menangkap n-gram (pola frasa pendek) dengan cepat. Namun, CNN tidak memahami ketergantungan jangka panjang dalam teks sebaik LSTM. Untuk task sederhana seperti analisis sentimen kalimat pendek, Conv1D bisa lebih cepat dan ringan dari LSTM.

Mengapa LSTM lebih baik dari RNN biasa?

RNN biasa (SimpleRNN) sangat rentan terhadap masalah vanishing gradient — saat backpropagation melalui banyak langkah waktu, gradientnya mengecil mendekati nol sehingga model gagal belajar dari konteks yang jauh. LSTM mengatasi ini dengan mekanisme gate (input gate, forget gate, output gate) yang mengontrol aliran informasi secara selektif, memungkinkan model mengingat informasi penting dari jauh.

Apa itu CNN-LSTM dan kapan digunakan?

CNN-LSTM adalah arsitektur hybrid di mana CNN digunakan untuk mengekstrak fitur spasial, kemudian hasilnya diumpankan ke LSTM untuk memproses urutan fitur tersebut. Cocok untuk task seperti: video classification (frame = spasial, urutan frame = sekuensial), activity recognition dari kamera, atau analisis sinyal berulang dari sensor. Ini adalah kombinasi terbaik dari kedua dunia.

Apakah Transformer sudah menggantikan RNN sepenuhnya?

Untuk banyak task NLP modern, Transformer (yang menjadi basis model seperti BERT dan GPT) memang sudah menggantikan RNN karena lebih paralel dan lebih baik menangkap konteks jarak jauh. Namun RNN/LSTM masih relevan untuk: perangkat edge dengan resource terbatas, time-series dengan pola temporal yang kuat, dan kasus di mana interpretabilitas sekuensial penting. Transformer juga membutuhkan data yang jauh lebih banyak untuk training.


Kesimpulan

CNN dan RNN adalah dua alat yang berbeda untuk masalah yang berbeda — bukan persaingan, tapi komplemen. Gunakan CNN saat datamu bersifat spasial dan pola lokalnya yang penting (gambar, video frame, spektrogram). Gunakan RNN/LSTM saat urutannya yang penting dan konteks historis menentukan makna (teks, time-series, log aktivitas).

Dalam praktiknya, banyak sistem produksi modern — seperti aplikasi yang ingin kamu bangun — menggabungkan keduanya dalam arsitektur hybrid. Mulailah dengan memahami sifat datamu: apakah ia spasial atau sekuensial? Jawaban itu akan menentukan arsitektur yang tepat.

Selamat bereksperimen dan terus eksplorasi! Jika ada pertanyaan atau kamu ingin mendalami topik tertentu lebih jauh, jangan ragu untuk menjelajahi artikel-artikel lainnya di KamusNgoding — komunitas developer Indonesia terus berkumbang bersamamu.

Artikel Terkait