Memahami pemrosesan data berurutan: RNN, LSTM, dan GRU, masalah vanishing gradient, dan peran gate memory, lalu praktik forecasting time series dan text generation sederhana dengan LSTM.

Semua arsitektur sejauh ini menerima input yang ukurannya tetap — gambar 28x28 atau vektor fitur 784. Di dunia nyata banyak data justru berurutan dengan panjang bervariasi: harga saham, cuaca, teks, audio, log server. Model perlu memahami urutan dan konteks: kata yang muncul lebih dulu menentukan makna kata berikutnya.
Episode ini memperkenalkan keluarga RNN (Recurrent Neural Network) dan penerusnya LSTM/GRU. Penting untuk dipahami: di era transformer (episode 12) model ini sudah jarang jadi pilihan pertama untuk teks besar, tetapi tetap relevan untuk time series dan sequence pendek, dan konsepnya — state, konteks, vanishing gradient — adalah fondasi yang menjelaskan mengapa transformer lahir.
RNN menambahkan hidden state yang dioper dari satu langkah waktu ke langkah berikutnya. Di setiap langkah, output dihitung dari input saat ini dan state sebelumnya — itulah "memori":
h_t = tanh(W_h * h_{t-1} + W_x * x_t + b)
y_t = W_y * h_t + bSetiap langkah memakai bobot yang sama (weight sharing) — seperti filter CNN yang digeser, RNN "mengeser" bobot sepanjang waktu. Sayangnya RNN naif punya masalah fatal.
Saat backpropagation menembus banyak langkah waktu, gradien dikalikan berulang kali dengan matriks bobot. Jika nilai eigen di bawah 1, gradien menyusut eksponensial — informasi dari 10 langkah lalu sudah tidak sampai ke update bobot. RNN praktis tidak bisa mengingat konteks jauh. Ini kebalikan dari masalah CNN, tetapi sumbernya sama: perkalian berulang.
LSTM (Long Short-Term Memory) memperkenalkan cell state yang dijalankan lurus sepanjang sequence, diatur oleh tiga gate yang menentukan apa yang diingat dan dilupakan:
Karena cell state mengalir lurus dengan operasi penjumlahan (bukan perkalian berulang), gradien punya "jalan raya" yang tidak menghilang. LSTM bisa mengingat konteks ratusan langkah.
GRU (Gated Recurrent Unit) menggabungkan forget dan input gate menjadi satu update gate plus satu reset gate. Parameter lebih sedikit, hasil sering setara dengan LSTM — pilihan hemat untuk data terbatas.
| Model | Parameter | Memori jangka panjang | Kapan dipakai |
|---|---|---|---|
| RNN | Sedikit | Buruk | Hanya pengantar konsep |
| LSTM | Banyak | Sangat baik | Baseline sequence yang aman |
| GRU | Lebih sedikit | Baik | Data terbatas / biaya rendah |
Tugas klasik: memprediksi nilai berikutnya dari deret. Siapkan data berbentuk jendela berjalan (window): 60 hari terakhir untuk memprediksi hari ke-61:
import torch
import numpy as np
def make_windows(series, window=60):
X, y = [], []
for i in range(window, len(series)):
X.append(series[i - window : i])
y.append(series[i])
return torch.tensor(X, dtype=torch.float32).unsqueeze(-1), \
torch.tensor(y, dtype=torch.float32)Lalu bangun LSTM satu lapis:
import torch.nn as nn
class LSTMForecast(nn.Module):
def __init__(self, window=60, hidden=32):
super().__init__()
self.lstm = nn.LSTM(input_size=1, hidden_size=hidden, batch_first=True)
self.fc = nn.Linear(hidden, 1)
def forward(self, x):
out, (h, c) = self.lstm(x)
return self.fc(out[:, -1, :]) # prediksi dari langkah terakhir
model = LSTMForecast()batch_first=True membuat input berbentuk (batch, window, features). Di forward, kita mengambil output langkah terakhir untuk memprediksi nilai berikutnya.
Latih dengan MSELoss dan Adam seperti biasa. Pola penting: sequence yang acak (noise murni) tidak bisa diprediksi — jangan heran jika model memprediksi rata-rata. Time series forecasting menuntut data yang memang memiliki struktur.
Tip
Untuk forecasting, lakukan standardisasi (min-max atau z-score) terhadap deret, dan selalu ukur dengan metrik yang relevan: RMSE dalam satuan asli atau MAPE dalam persen. Normalized RMSE yang tampak kecil bisa menipu jika skala data sangat besar.
LSTM juga bisa menghasilkan teks: model dilatih memprediksi karakter/kata berikutnya, lalu generasi dilakukan dengan memberi makan prediksi kembali ke input (autoregressive):
def generate(model, prompt, token_to_idx, idx_to_token, max_len=200):
model.eval()
chars = list(prompt)
for _ in range(max_len):
x = torch.tensor([[token_to_idx[c] for c in chars[-50:]]])
with torch.no_grad():
logits = model(x)
next_idx = torch.argmax(logits[:, -1, :], dim=-1).item()
chars.append(idx_to_token[next_idx])
return "".join(chars)Detail: model mengeluarkan distribusi per token; argmax memilih token paling mungkin (deterministik), sedangkan sampling dengan suhu (temperature) memilih acak berbobot untuk variasi yang lebih menarik:
probs = torch.softmax(logits[:, -1, :] / temperature, dim=-1)
next_idx = torch.multinomial(probs, 1).item()Suhu tinggi = hasil liar; suhu rendah = hasil repetitif. 0.7-0.9 adalah sweet spot untuk teks yang kreatif namun koheren.
(batch, seq_len, features) — jangan lupa batch_first=True atau transpose.clip_grad_norm_ dari episode 6.Warning
Untuk teks dan sequence panjang, jangan pilih LSTM secara default — transformer (episode 12) hampir selalu menang karena memproses sequence secara paralel dan menangkap konteks global. LSTM tetap berharga untuk time series pendek, edge device dengan sumber daya terbatas, dan sebagai bahan pemahaman sejarah arsitektur.
Pada episode 11 ini, kalian telah menguasai sequence modeling.
Inti yang harus dibawa pulang:
Di episode 12 selanjutnya kita akan membedah transformer — self-attention, multi-head, positional encoding, arsitektur encoder-decoder, hingga implementasi transformer kecil untuk sequence modeling. Sampai jumpa di episode 12!